From 56e17cd39cdfd31c294c2f27ccc1afe257e28ee9 Mon Sep 17 00:00:00 2001 From: Dmitry Tomashevich <39378793+Dmitriynj@users.noreply.github.com> Date: Fri, 1 Oct 2021 15:17:19 +0300 Subject: [PATCH 01/98] [Discover] Save collapse sidebar state in local storage (#113287) * [Discover] fix selected fields persist * [Discover] apply solution for entire sidebar instead of "Selected fields" collapse button * [Discover] update unit tests * [Discover] update unit tests * [Discover] improve tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../discover/public/__mocks__/services.ts | 3 ++ .../layout/discover_layout.test.tsx | 34 +++++++++++++++++-- .../components/layout/discover_layout.tsx | 18 ++++++++-- .../sidebar/discover_sidebar_responsive.tsx | 2 +- src/plugins/discover/public/build_services.ts | 6 +++- 5 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index d24aefb6c8192..30d66b113e528 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -89,4 +89,7 @@ export const discoverServiceMock = { useChartsTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), useChartsBaseTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), }, + storage: { + get: jest.fn(), + }, } as unknown as DiscoverServices; diff --git a/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.test.tsx index 7b2825907ba29..6ebed3185e2f1 100644 --- a/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.test.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { Subject, BehaviorSubject } from 'rxjs'; import { mountWithIntl } from '@kbn/test/jest'; import { setHeaderActionMenuMounter } from '../../../../../kibana_services'; -import { DiscoverLayout } from './discover_layout'; +import { DiscoverLayout, SIDEBAR_CLOSED_KEY } from './discover_layout'; import { esHits } from '../../../../../__mocks__/es_hits'; import { indexPatternMock } from '../../../../../__mocks__/index_pattern'; import { savedSearchMock } from '../../../../../__mocks__/saved_search'; @@ -31,15 +31,21 @@ import { FetchStatus } from '../../../../types'; import { ElasticSearchHit } from '../../../../doc_views/doc_views_types'; import { RequestAdapter } from '../../../../../../../inspector'; import { Chart } from '../chart/point_series'; +import { DiscoverSidebar } from '../sidebar/discover_sidebar'; setHeaderActionMenuMounter(jest.fn()); -function getProps(indexPattern: IndexPattern): DiscoverLayoutProps { +function getProps(indexPattern: IndexPattern, wasSidebarClosed?: boolean): DiscoverLayoutProps { const searchSourceMock = createSearchSourceMock({}); const services = discoverServiceMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; }; + services.storage.get = (key: string) => { + if (key === SIDEBAR_CLOSED_KEY) { + return wasSidebarClosed; + } + }; const indexPatternList = [indexPattern].map((ip) => { return { ...ip, ...{ attributes: { title: ip.title } } }; @@ -139,10 +145,34 @@ describe('Discover component', () => { const component = mountWithIntl(); expect(component.find('[data-test-subj="discoverChartOptionsToggle"]').exists()).toBeFalsy(); }); + test('selected index pattern with time field displays chart toggle', () => { const component = mountWithIntl( ); expect(component.find('[data-test-subj="discoverChartOptionsToggle"]').exists()).toBeTruthy(); }); + + describe('sidebar', () => { + test('should be opened if discover:sidebarClosed was not set', () => { + const component = mountWithIntl( + + ); + expect(component.find(DiscoverSidebar).length).toBe(1); + }); + + test('should be opened if discover:sidebarClosed is false', () => { + const component = mountWithIntl( + + ); + expect(component.find(DiscoverSidebar).length).toBe(1); + }); + + test('should be closed if discover:sidebarClosed is true', () => { + const component = mountWithIntl( + + ); + expect(component.find(DiscoverSidebar).length).toBe(0); + }); + }); }); diff --git a/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.tsx index c2d09f31e3e0a..4bbef32dcbadd 100644 --- a/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.tsx @@ -40,6 +40,11 @@ import { DiscoverDocuments } from './discover_documents'; import { FetchStatus } from '../../../../types'; import { useDataState } from '../../utils/use_data_state'; +/** + * Local storage key for sidebar persistence state + */ +export const SIDEBAR_CLOSED_KEY = 'discover:sidebarClosed'; + const SidebarMemoized = React.memo(DiscoverSidebarResponsive); const TopNavMemoized = React.memo(DiscoverTopNav); const DiscoverChartMemoized = React.memo(DiscoverChart); @@ -60,7 +65,8 @@ export function DiscoverLayout({ state, stateContainer, }: DiscoverLayoutProps) { - const { trackUiMetric, capabilities, indexPatterns, data, uiSettings, filterManager } = services; + const { trackUiMetric, capabilities, indexPatterns, data, uiSettings, filterManager, storage } = + services; const { main$, charts$, totalHits$ } = savedSearchData$; const [expandedDoc, setExpandedDoc] = useState(undefined); @@ -78,7 +84,8 @@ export function DiscoverLayout({ return indexPattern.type !== 'rollup' ? indexPattern.timeFieldName : undefined; }, [indexPattern]); - const [isSidebarClosed, setIsSidebarClosed] = useState(false); + const initialSidebarClosed = Boolean(storage.get(SIDEBAR_CLOSED_KEY)); + const [isSidebarClosed, setIsSidebarClosed] = useState(initialSidebarClosed); const useNewFieldsApi = useMemo(() => !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), [uiSettings]); const resultState = useMemo( @@ -144,6 +151,11 @@ export function DiscoverLayout({ filterManager.setFilters(disabledFilters); }, [filterManager]); + const toggleSidebarCollapse = useCallback(() => { + storage.set(SIDEBAR_CLOSED_KEY, !isSidebarClosed); + setIsSidebarClosed(!isSidebarClosed); + }, [isSidebarClosed, storage]); + const contentCentered = resultState === 'uninitialized' || resultState === 'none'; return ( @@ -192,7 +204,7 @@ export function DiscoverLayout({ iconType={isSidebarClosed ? 'menuRight' : 'menuLeft'} iconSize="m" size="xs" - onClick={() => setIsSidebarClosed(!isSidebarClosed)} + onClick={toggleSidebarCollapse} data-test-subj="collapseSideBarButton" aria-controls="discover-sidebar" aria-expanded={isSidebarClosed ? 'false' : 'true'} diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx index ade9c3aae4b28..90357b73c6881 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx @@ -217,7 +217,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) return ( <> - {props.isClosed ? null : ( + {!props.isClosed && ( void; indexPatternFieldEditor: IndexPatternFieldEditorStart; http: HttpStart; + storage: Storage; } export function buildServices( @@ -75,6 +77,7 @@ export function buildServices( }; const savedObjectService = createSavedSearchesLoader(services); const { usageCollection } = plugins; + const storage = new Storage(localStorage); return { addBasePath: core.http.basePath.prepend, @@ -100,6 +103,7 @@ export function buildServices( timefilter: plugins.data.query.timefilter.timefilter, toastNotifications: core.notifications.toasts, uiSettings: core.uiSettings, + storage, trackUiMetric: usageCollection?.reportUiCounter.bind(usageCollection, 'discover'), indexPatternFieldEditor: plugins.indexPatternFieldEditor, http: core.http, From 8928a1ef98406f44e51eb3aadbec21b26e838faa Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Fri, 1 Oct 2021 09:18:23 -0500 Subject: [PATCH 02/98] [systemd] Use a private /tmp directory (#112372) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../systemd/usr/lib/systemd/system/kibana.service | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dev/build/tasks/os_packages/service_templates/systemd/usr/lib/systemd/system/kibana.service b/src/dev/build/tasks/os_packages/service_templates/systemd/usr/lib/systemd/system/kibana.service index df33b82f1f967..21f1a011f2397 100644 --- a/src/dev/build/tasks/os_packages/service_templates/systemd/usr/lib/systemd/system/kibana.service +++ b/src/dev/build/tasks/os_packages/service_templates/systemd/usr/lib/systemd/system/kibana.service @@ -8,6 +8,7 @@ After=network-online.target Type=simple User=kibana Group=kibana +PrivateTmp=true Environment=KBN_HOME=/usr/share/kibana Environment=KBN_PATH_CONF=/etc/kibana From 88fa27debe6ec6ecc7351e6f0a30abf23e19c342 Mon Sep 17 00:00:00 2001 From: Dmitry Tomashevich <39378793+Dmitriynj@users.noreply.github.com> Date: Fri, 1 Oct 2021 18:14:10 +0300 Subject: [PATCH 03/98] [Discover] Fix doc viewer table columns (#113124) * [Discover] fix doc viewer table columns * [Discover] apply suggestions * [Discover] apply suggestion * [Discover] fix action column * [Discover] do not apply min-width to actions column Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/application/components/doc_viewer/doc_viewer.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss index 83b5ce2849c90..16712ae8dbb78 100644 --- a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss +++ b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss @@ -12,6 +12,11 @@ font-size: $euiFontSizeXS; font-family: $euiCodeFontFamily; + // set min-width for each column except actions + .euiTableRowCell:nth-child(n+2) { + min-width: $euiSizeM * 9; + } + .kbnDocViewer__buttons { // Show all icons if one is focused, &:focus-within { From 2d2878a904a98462d5bc5e63bedc62b0d6110079 Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Fri, 1 Oct 2021 10:22:03 -0500 Subject: [PATCH 04/98] Exclude cypress folders from Jest test coverage (#113482) --- x-pack/plugins/enterprise_search/jest.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/plugins/enterprise_search/jest.config.js b/x-pack/plugins/enterprise_search/jest.config.js index 263713697b7e0..b5e6105ff41f2 100644 --- a/x-pack/plugins/enterprise_search/jest.config.js +++ b/x-pack/plugins/enterprise_search/jest.config.js @@ -18,4 +18,8 @@ module.exports = { '!/x-pack/plugins/enterprise_search/public/applications/test_helpers/**/*.{ts,tsx}', ], coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/enterprise_search', + modulePathIgnorePatterns: [ + '/x-pack/plugins/enterprise_search/public/applications/app_search/cypress', + '/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress', + ], }; From 4f583eb16b5d57b97206848525987aa9ce02d926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Fri, 1 Oct 2021 11:25:17 -0400 Subject: [PATCH 05/98] [APM] Disabling apm e2e test (#113618) --- vars/tasks.groovy | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/vars/tasks.groovy b/vars/tasks.groovy index 1842e278282b1..5c8f133331e55 100644 --- a/vars/tasks.groovy +++ b/vars/tasks.groovy @@ -146,13 +146,14 @@ def functionalXpack(Map params = [:]) { } } - whenChanged([ - 'x-pack/plugins/apm/', - ]) { - if (githubPr.isPr()) { - task(kibanaPipeline.functionalTestProcess('xpack-APMCypress', './test/scripts/jenkins_apm_cypress.sh')) - } - } + //temporarily disable apm e2e test since it's breaking due to a version upgrade. + // whenChanged([ + // 'x-pack/plugins/apm/', + // ]) { + // if (githubPr.isPr()) { + // task(kibanaPipeline.functionalTestProcess('xpack-APMCypress', './test/scripts/jenkins_apm_cypress.sh')) + // } + // } whenChanged([ 'x-pack/plugins/uptime/', From 753defe366d0aaea4e1ed6bef5a7c4160dc315cf Mon Sep 17 00:00:00 2001 From: Davey Holler Date: Fri, 1 Oct 2021 08:45:46 -0700 Subject: [PATCH 06/98] App Search Automated Curation Suggestion Detail View (#113342) --- .../curations/curations_router.test.tsx | 2 +- .../components/curations/curations_router.tsx | 6 +- .../curation_action_bar.test.tsx | 29 ++ .../curation_action_bar.tsx | 81 +++ .../curation_actions_popover.test.tsx | 69 +++ .../curation_actions_popover.tsx | 102 ++++ .../curation_result_panel.scss | 24 + .../curation_result_panel.test.tsx | 53 ++ .../curation_result_panel.tsx | 91 ++++ .../curation_suggestion.test.tsx | 55 ++ .../curation_suggestion.tsx | 120 +++++ .../views/curation_suggestion/index.ts | 8 + .../views/curation_suggestion/temp_data.ts | 470 ++++++++++++++++++ .../components/curations/views/index.ts | 1 + 14 files changed, 1109 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_action_bar.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_action_bar.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_actions_popover.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_actions_popover.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.scss create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/index.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/temp_data.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx index a241edb8020a4..9598212d3e0c9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx @@ -19,6 +19,6 @@ describe('CurationsRouter', () => { const wrapper = shallow(); expect(wrapper.find(Switch)).toHaveLength(1); - expect(wrapper.find(Route)).toHaveLength(3); + expect(wrapper.find(Route)).toHaveLength(4); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.tsx index 40f2d07ab61ab..693e5406b714b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.tsx @@ -12,10 +12,11 @@ import { ENGINE_CURATIONS_PATH, ENGINE_CURATIONS_NEW_PATH, ENGINE_CURATION_PATH, + ENGINE_CURATION_SUGGESTION_PATH, } from '../../routes'; import { Curation } from './curation'; -import { Curations, CurationCreation } from './views'; +import { Curations, CurationCreation, CurationSuggestion } from './views'; export const CurationsRouter: React.FC = () => { return ( @@ -26,6 +27,9 @@ export const CurationsRouter: React.FC = () => { + + + diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_action_bar.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_action_bar.test.tsx new file mode 100644 index 0000000000000..4bd586d9d2e91 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_action_bar.test.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { CurationActionBar } from './curation_action_bar'; + +describe('CurationActionBar', () => { + const handleAcceptClick = jest.fn(); + const handleRejectClick = jest.fn(); + + it('renders', () => { + const wrapper = shallow( + + ); + + wrapper.find('[data-test-subj="rejectButton"]').simulate('click'); + expect(handleRejectClick).toHaveBeenCalled(); + + wrapper.find('[data-test-subj="acceptButton"]').simulate('click'); + expect(handleAcceptClick).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_action_bar.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_action_bar.tsx new file mode 100644 index 0000000000000..42f4cbbb7d7a9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_action_bar.tsx @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { CurationActionsPopover } from './curation_actions_popover'; + +interface Props { + onAcceptClick: (event: React.MouseEvent) => void; + onRejectClick: (event: React.MouseEvent) => void; +} + +export const CurationActionBar: React.FC = ({ onAcceptClick, onRejectClick }) => { + return ( + + + + + + +

+ {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.title', + { defaultMessage: 'Manage suggestion' } + )} +

+
+
+ + + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.rejectButtonLabel', + { defaultMessage: 'Reject' } + )} + + + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.acceptButtonLabel', + { defaultMessage: 'Accept' } + )} + + + + {}} + onAutomate={() => {}} + onReject={() => {}} + onTurnOff={() => {}} + /> + + + +
+
+
+
+ ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_actions_popover.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_actions_popover.test.tsx new file mode 100644 index 0000000000000..33d00ca2b7899 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_actions_popover.test.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { CurationActionsPopover } from './curation_actions_popover'; + +describe('CurationActionsPopover', () => { + const handleAccept = jest.fn(); + const handleAutomate = jest.fn(); + const handleReject = jest.fn(); + const handleTurnOff = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders', () => { + const wrapper = shallow( + + ); + expect(wrapper.isEmptyRender()).toBe(false); + + wrapper.find('[data-test-subj="acceptButton"]').simulate('click'); + expect(handleAccept).toHaveBeenCalled(); + + wrapper.find('[data-test-subj="automateButton"]').simulate('click'); + expect(handleAutomate).toHaveBeenCalled(); + + wrapper.find('[data-test-subj="rejectButton"]').simulate('click'); + expect(handleReject).toHaveBeenCalled(); + + wrapper.find('[data-test-subj="turnoffButton"]').simulate('click'); + expect(handleTurnOff).toHaveBeenCalled(); + }); + + it('can open and close', () => { + const wrapper = shallow( + + ); + + expect(wrapper.prop('isOpen')).toBe(false); + + const button = shallow(wrapper.prop('button')); + button.simulate('click'); + + expect(wrapper.prop('isOpen')).toBe(true); + + wrapper.prop('closePopover')(); + + expect(wrapper.prop('isOpen')).toBe(false); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_actions_popover.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_actions_popover.tsx new file mode 100644 index 0000000000000..ef7b42fb705f1 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_actions_popover.tsx @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; + +import { + EuiButtonIcon, + EuiListGroup, + EuiListGroupItem, + EuiPopover, + EuiPopoverTitle, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +interface Props { + onAccept: () => void; + onAutomate: () => void; + onReject: () => void; + onTurnOff: () => void; +} + +export const CurationActionsPopover: React.FC = ({ + onAccept, + onAutomate, + onReject, + onTurnOff, +}) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const onButtonClick = () => setIsPopoverOpen(!isPopoverOpen); + const closePopover = () => setIsPopoverOpen(false); + + const button = ( + + ); + return ( + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.actionsPopoverTitle', + { + defaultMessage: 'Manage suggestion', + } + )} + + + + + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.scss new file mode 100644 index 0000000000000..1fa988014edb7 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.scss @@ -0,0 +1,24 @@ +.curationResultPanel { + border-radius: $euiSizeM; + margin-top: $euiSizeS; + padding: $euiSizeXS; +} + +.curationResultPanel--current, .curationResultPanel--promoted { + border: $euiBorderWidthThick solid $euiColorPrimary; + background-color: tintOrShade($euiColorPrimary, 90%, 70%); // Copied from @elastit/eui/src/global_styling/variables/_panels.scss +} + +.curationResultPanel--suggested { + border: $euiBorderWidthThick solid $euiColorSecondary; + background-color: tintOrShade($euiColorSuccess, 90%, 70%); // Copied from @elastit/eui/src/global_styling/variables/_panels.scss +} + +.curationResultPanel--hidden { + border: $euiBorderWidthThick solid $euiColorAccent; + background-color: tintOrShade($euiColorAccent, 90%, 70%); // Copied from @elastit/eui/src/global_styling/variables/_panels.scss +} + +.curationResultPanel__header { + flex-grow: 0; +} \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.test.tsx new file mode 100644 index 0000000000000..fad4e54721bb3 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.test.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { Result } from '../../../result'; + +import { CurationResultPanel } from './curation_result_panel'; + +describe('CurationResultPanel', () => { + const results = [ + { + id: { raw: 'foo' }, + _meta: { engine: 'some-engine', id: 'foo' }, + }, + { + id: { raw: 'bar' }, + _meta: { engine: 'some-engine', id: 'bar' }, + }, + ]; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders results', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="suggestedText"]').exists()).toBe(false); + expect(wrapper.find(Result).length).toBe(2); + }); + + it('renders a no results message when there are no results', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="noResults"]').exists()).toBe(true); + expect(wrapper.find(Result).length).toBe(0); + }); + + it('shows text about automation when variant is "suggested"', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="suggestedText"]').exists()).toBe(true); + }); + + it('renders the right class name for the provided variant', () => { + const wrapper = shallow(); + expect(wrapper.find('.curationResultPanel--promoted').exists()).toBe(true); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.tsx new file mode 100644 index 0000000000000..12bbf07f97bb3 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.tsx @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiNotificationBadge, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { Result } from '../../../result'; +import { Result as ResultType } from '../../../result/types'; +import './curation_result_panel.scss'; + +interface Props { + variant: 'current' | 'promoted' | 'suggested' | 'hidden'; + results: ResultType[]; +} + +export const CurationResultPanel: React.FC = ({ variant, results }) => { + // TODO wire up + const count = 3; + + return ( + <> + + + {count} + + + +
+ {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.resultPanelTitle', + { defaultMessage: 'Promoted results' } + )} +
+
+
+ {variant === 'suggested' && ( + + +

+ {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.resultPanelDescription', + { defaultMessage: 'This curation can be automated by App Search' } + )} +

+
+
+ )} +
+ + 0 ? 'flexStart' : 'center'} + gutterSize="s" + direction="column" + className={`curationResultPanel curationResultPanel--${variant}`} + > + {results.length > 0 ? ( + results.map((result) => ( + + + + )) + ) : ( + +

+ + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.noResultsMessage', + { defaultMessage: 'There are currently no promoted documents for this query' } + )} + +

+
+ )} +
+ + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx new file mode 100644 index 0000000000000..9bfc12dfe7cc2 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockUseParams } from '../../../../../__mocks__/react_router'; +import '../../../../__mocks__/engine_logic.mock'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { AppSearchPageTemplate } from '../../../layout'; + +import { CurationSuggestion } from './curation_suggestion'; + +describe('CurationSuggestion', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockUseParams.mockReturnValue({ query: 'some%20query' }); + }); + + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.is(AppSearchPageTemplate)).toBe(true); + }); + + it('displays the decoded query in the title', () => { + const wrapper = shallow(); + + expect(wrapper.prop('pageHeader').pageTitle).toEqual('some query'); + }); + + // TODO This will need to come from somewhere else when wired up + it('displays an empty query if "" is encoded in as the qery', () => { + mockUseParams.mockReturnValue({ query: '%22%22' }); + + const wrapper = shallow(); + + expect(wrapper.prop('pageHeader').pageTitle).toEqual('""'); + }); + + it('displays has a button to display organic results', () => { + const wrapper = shallow(); + + expect(wrapper.find('[data-test-subj="organicResults"]').exists()).toBe(false); + wrapper.find('[data-test-subj="showOrganicResults"]').simulate('click'); + expect(wrapper.find('[data-test-subj="organicResults"]').exists()).toBe(true); + wrapper.find('[data-test-subj="showOrganicResults"]').simulate('click'); + expect(wrapper.find('[data-test-subj="organicResults"]').exists()).toBe(false); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.tsx new file mode 100644 index 0000000000000..4fab9db47af90 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.tsx @@ -0,0 +1,120 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; + +import { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPanel, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { useDecodedParams } from '../../../../utils/encode_path_params'; +import { AppSearchPageTemplate } from '../../../layout'; +import { Result } from '../../../result'; +import { Result as ResultType } from '../../../result/types'; +import { getCurationsBreadcrumbs } from '../../utils'; + +import { CurationActionBar } from './curation_action_bar'; +import { CurationResultPanel } from './curation_result_panel'; + +import { DATA } from './temp_data'; + +export const CurationSuggestion: React.FC = () => { + const { query } = useDecodedParams(); + const [showOrganicResults, setShowOrganicResults] = useState(false); + const currentOrganicResults = [...DATA].splice(5, 4); + const proposedOrganicResults = [...DATA].splice(2, 4); + + const queryTitle = query === '""' ? query : `${query}`; + + return ( + + alert('Accepted')} + onRejectClick={() => alert('Rejected')} + /> + + + + +

Current

+
+ + +
+ + +

Suggested

+
+ + +
+
+ + + setShowOrganicResults(!showOrganicResults)} + data-test-subj="showOrganicResults" + > + {showOrganicResults ? 'Collapse' : 'Expand'} organic search results + + {showOrganicResults && ( + <> + + + + + {currentOrganicResults.length > 0 && ( + + {currentOrganicResults.map((result: ResultType) => ( + + + + ))} + + )} + + + {proposedOrganicResults.length > 0 && ( + + {proposedOrganicResults.map((result: ResultType) => ( + + + + ))} + + )} + + + + + )} + +
+ ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/index.ts new file mode 100644 index 0000000000000..9cb1809e20442 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/index.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { CurationSuggestion } from './curation_suggestion'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/temp_data.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/temp_data.ts new file mode 100644 index 0000000000000..83bbc977427a9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/temp_data.ts @@ -0,0 +1,470 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Result } from '../../../result/types'; + +export const DATA: Result[] = [ + { + visitors: { + raw: 5028868.0, + }, + square_km: { + raw: 3082.7, + }, + world_heritage_site: { + raw: 'true', + snippet: 'true', + }, + date_established: { + raw: '1890-10-01T05:00:00+00:00', + }, + description: { + raw: "Yosemite features sheer granite cliffs, exceptionally tall waterfalls, and old-growth forests at a unique intersection of geology and hydrology. Half Dome and El Capitan rise from the park's centerpiece, the glacier-carved Yosemite Valley, and from its vertical walls drop Yosemite Falls, one of North America's tallest waterfalls at 2,425 feet (739 m) high. Three giant sequoia groves, along with a pristine wilderness in the heart of the Sierra Nevada, are home to a wide variety of rare plant and animal species.", + snippet: + 'Yosemite features sheer granite cliffs, exceptionally tall waterfalls, and old-growth forests', + }, + location: { + raw: '37.83,-119.5', + }, + acres: { + raw: 761747.5, + }, + title: { + raw: 'Yosemite', + snippet: 'Yosemite', + }, + nps_link: { + raw: 'https://www.nps.gov/yose/index.htm', + snippet: 'https://www.nps.gov/yose/index.htm', + }, + states: { + raw: ['California'], + snippet: 'California', + }, + _meta: { + engine: 'national-parks-demo', + score: 7543305.0, + id: 'park_yosemite', + }, + id: { + raw: 'park_yosemite', + }, + }, + { + visitors: { + raw: 4517585.0, + }, + square_km: { + raw: 1075.6, + }, + world_heritage_site: { + raw: 'false', + snippet: 'false', + }, + date_established: { + raw: '1915-01-26T06:00:00+00:00', + }, + description: { + raw: 'Bisected north to south by the Continental Divide, this portion of the Rockies has ecosystems varying from over 150 riparian lakes to montane and subalpine forests to treeless alpine tundra. Wildlife including mule deer, bighorn sheep, black bears, and cougars inhabit its igneous mountains and glacial valleys. Longs Peak, a classic Colorado fourteener, and the scenic Bear Lake are popular destinations, as well as the historic Trail Ridge Road, which reaches an elevation of more than 12,000 feet (3,700 m).', + snippet: + ' varying from over 150 riparian lakes to montane and subalpine forests to treeless alpine tundra. Wildlife', + }, + location: { + raw: '40.4,-105.58', + }, + acres: { + raw: 265795.2, + }, + title: { + raw: 'Rocky Mountain', + snippet: 'Rocky Mountain', + }, + nps_link: { + raw: 'https://www.nps.gov/romo/index.htm', + snippet: 'https://www.nps.gov/romo/index.htm', + }, + states: { + raw: ['Colorado'], + snippet: 'Colorado', + }, + _meta: { + engine: 'national-parks-demo', + score: 6776380.0, + id: 'park_rocky-mountain', + }, + id: { + raw: 'park_rocky-mountain', + }, + }, + { + visitors: { + raw: 4295127.0, + }, + square_km: { + raw: 595.8, + }, + world_heritage_site: { + raw: 'false', + snippet: 'false', + }, + date_established: { + raw: '1919-11-19T06:00:00+00:00', + }, + description: { + raw: 'Located at the junction of the Colorado Plateau, Great Basin, and Mojave Desert, this park contains sandstone features such as mesas, rock towers, and canyons, including the Virgin River Narrows. The various sandstone formations and the forks of the Virgin River create a wilderness divided into four ecosystems: desert, riparian, woodland, and coniferous forest.', + snippet: ' into four ecosystems: desert, riparian, woodland, and coniferous forest.', + }, + location: { + raw: '37.3,-113.05', + }, + acres: { + raw: 147237.02, + }, + title: { + raw: 'Zion', + snippet: 'Zion', + }, + nps_link: { + raw: 'https://www.nps.gov/zion/index.htm', + snippet: 'https://www.nps.gov/zion/index.htm', + }, + states: { + raw: ['Utah'], + snippet: 'Utah', + }, + _meta: { + engine: 'national-parks-demo', + score: 6442695.0, + id: 'park_zion', + }, + id: { + raw: 'park_zion', + }, + }, + { + visitors: { + raw: 3303393.0, + }, + square_km: { + raw: 198.5, + }, + world_heritage_site: { + raw: 'false', + snippet: 'false', + }, + date_established: { + raw: '1919-02-26T06:00:00+00:00', + }, + description: { + raw: 'Covering most of Mount Desert Island and other coastal islands, Acadia features the tallest mountain on the Atlantic coast of the United States, granite peaks, ocean shoreline, woodlands, and lakes. There are freshwater, estuary, forest, and intertidal habitats.', + snippet: + ' mountain on the Atlantic coast of the United States, granite peaks, ocean shoreline, woodlands, and lakes. There are freshwater, estuary, forest, and intertidal habitats.', + }, + location: { + raw: '44.35,-68.21', + }, + acres: { + raw: 49057.36, + }, + title: { + raw: 'Acadia', + snippet: 'Acadia', + }, + nps_link: { + raw: 'https://www.nps.gov/acad/index.htm', + snippet: 'https://www.nps.gov/acad/index.htm', + }, + states: { + raw: ['Maine'], + snippet: 'Maine', + }, + _meta: { + engine: 'national-parks-demo', + score: 4955094.5, + id: 'park_acadia', + }, + id: { + raw: 'park_acadia', + }, + }, + { + visitors: { + raw: 1887580.0, + }, + square_km: { + raw: 1308.9, + }, + world_heritage_site: { + raw: 'true', + snippet: 'true', + }, + date_established: { + raw: '1916-08-01T05:00:00+00:00', + }, + description: { + raw: "This park on the Big Island protects the Kīlauea and Mauna Loa volcanoes, two of the world's most active geological features. Diverse ecosystems range from tropical forests at sea level to barren lava beds at more than 13,000 feet (4,000 m).", + snippet: + ' active geological features. Diverse ecosystems range from tropical forests at sea level to barren lava beds at more than 13,000 feet (4,000 m).', + }, + location: { + raw: '19.38,-155.2', + }, + acres: { + raw: 323431.38, + }, + title: { + raw: 'Hawaii Volcanoes', + snippet: 'Hawaii Volcanoes', + }, + nps_link: { + raw: 'https://www.nps.gov/havo/index.htm', + snippet: 'https://www.nps.gov/havo/index.htm', + }, + states: { + raw: ['Hawaii'], + snippet: 'Hawaii', + }, + _meta: { + engine: 'national-parks-demo', + score: 2831373.2, + id: 'park_hawaii-volcanoes', + }, + id: { + raw: 'park_hawaii-volcanoes', + }, + }, + { + visitors: { + raw: 1437341.0, + }, + square_km: { + raw: 806.1, + }, + world_heritage_site: { + raw: 'false', + snippet: 'false', + }, + date_established: { + raw: '1935-12-26T06:00:00+00:00', + }, + description: { + raw: "Shenandoah's Blue Ridge Mountains are covered by hardwood forests that teem with a wide variety of wildlife. The Skyline Drive and Appalachian Trail run the entire length of this narrow park, along with more than 500 miles (800 km) of hiking trails passing scenic overlooks and cataracts of the Shenandoah River.", + snippet: + 'Shenandoah's Blue Ridge Mountains are covered by hardwood forests that teem with a wide variety', + }, + location: { + raw: '38.53,-78.35', + }, + acres: { + raw: 199195.27, + }, + title: { + raw: 'Shenandoah', + snippet: 'Shenandoah', + }, + nps_link: { + raw: 'https://www.nps.gov/shen/index.htm', + snippet: 'https://www.nps.gov/shen/index.htm', + }, + states: { + raw: ['Virginia'], + snippet: 'Virginia', + }, + _meta: { + engine: 'national-parks-demo', + score: 2156015.5, + id: 'park_shenandoah', + }, + id: { + raw: 'park_shenandoah', + }, + }, + { + visitors: { + raw: 1356913.0, + }, + square_km: { + raw: 956.6, + }, + world_heritage_site: { + raw: 'false', + snippet: 'false', + }, + date_established: { + raw: '1899-03-02T06:00:00+00:00', + }, + description: { + raw: 'Mount Rainier, an active stratovolcano, is the most prominent peak in the Cascades and is covered by 26 named glaciers including Carbon Glacier and Emmons Glacier, the largest in the contiguous United States. The mountain is popular for climbing, and more than half of the park is covered by subalpine and alpine forests and meadows seasonally in bloom with wildflowers. Paradise on the south slope is the snowiest place on Earth where snowfall is measured regularly. The Longmire visitor center is the start of the Wonderland Trail, which encircles the mountain.', + snippet: + ' by subalpine and alpine forests and meadows seasonally in bloom with wildflowers. Paradise on the south slope', + }, + location: { + raw: '46.85,-121.75', + }, + acres: { + raw: 236381.64, + }, + title: { + raw: 'Mount Rainier', + snippet: 'Mount Rainier', + }, + nps_link: { + raw: 'https://www.nps.gov/mora/index.htm', + snippet: 'https://www.nps.gov/mora/index.htm', + }, + states: { + raw: ['Washington'], + snippet: 'Washington', + }, + _meta: { + engine: 'national-parks-demo', + score: 2035372.0, + id: 'park_mount-rainier', + }, + id: { + raw: 'park_mount-rainier', + }, + }, + { + visitors: { + raw: 1254688.0, + }, + square_km: { + raw: 1635.2, + }, + world_heritage_site: { + raw: 'false', + snippet: 'false', + }, + date_established: { + raw: '1890-09-25T05:00:00+00:00', + }, + description: { + raw: "This park protects the Giant Forest, which boasts some of the world's largest trees, the General Sherman being the largest measured tree in the park. Other features include over 240 caves, a long segment of the Sierra Nevada including the tallest mountain in the contiguous United States, and Moro Rock, a large granite dome.", + snippet: + 'This park protects the Giant Forest, which boasts some of the world's largest trees, the General', + }, + location: { + raw: '36.43,-118.68', + }, + acres: { + raw: 404062.63, + }, + title: { + raw: 'Sequoia', + snippet: 'Sequoia', + }, + nps_link: { + raw: 'https://www.nps.gov/seki/index.htm', + snippet: 'https://www.nps.gov/seki/index.htm', + }, + states: { + raw: ['California'], + snippet: 'California', + }, + _meta: { + engine: 'national-parks-demo', + score: 1882038.0, + id: 'park_sequoia', + }, + id: { + raw: 'park_sequoia', + }, + }, + { + visitors: { + raw: 643274.0, + }, + square_km: { + raw: 896.0, + }, + world_heritage_site: { + raw: 'false', + snippet: 'false', + }, + date_established: { + raw: '1962-12-09T06:00:00+00:00', + }, + description: { + raw: 'This portion of the Chinle Formation has a large concentration of 225-million-year-old petrified wood. The surrounding Painted Desert features eroded cliffs of red-hued volcanic rock called bentonite. Dinosaur fossils and over 350 Native American sites are also protected in this park.', + snippet: + 'This portion of the Chinle Formation has a large concentration of 225-million-year-old petrified', + }, + location: { + raw: '35.07,-109.78', + }, + acres: { + raw: 221415.77, + }, + title: { + raw: 'Petrified Forest', + snippet: 'Petrified Forest', + }, + nps_link: { + raw: 'https://www.nps.gov/pefo/index.htm', + snippet: 'https://www.nps.gov/pefo/index.htm', + }, + states: { + raw: ['Arizona'], + snippet: 'Arizona', + }, + _meta: { + engine: 'national-parks-demo', + score: 964919.94, + id: 'park_petrified-forest', + }, + id: { + raw: 'park_petrified-forest', + }, + }, + { + visitors: { + raw: 617377.0, + }, + square_km: { + raw: 137.5, + }, + world_heritage_site: { + raw: 'false', + snippet: 'false', + }, + date_established: { + raw: '1903-01-09T06:00:00+00:00', + }, + description: { + raw: "Wind Cave is distinctive for its calcite fin formations called boxwork, a unique formation rarely found elsewhere, and needle-like growths called frostwork. The cave is one of the longest and most complex caves in the world. Above ground is a mixed-grass prairie with animals such as bison, black-footed ferrets, and prairie dogs, and ponderosa pine forests that are home to cougars and elk. The cave is culturally significant to the Lakota people as the site 'from which Wakan Tanka, the Great Mystery, sent the buffalo out into their hunting grounds.'", + snippet: + '-footed ferrets, and prairie dogs, and ponderosa pine forests that are home to cougars and elk', + }, + location: { + raw: '43.57,-103.48', + }, + acres: { + raw: 33970.84, + }, + title: { + raw: 'Wind Cave', + snippet: 'Wind Cave', + }, + nps_link: { + raw: 'https://www.nps.gov/wica/index.htm', + snippet: 'https://www.nps.gov/wica/index.htm', + }, + states: { + raw: ['South Dakota'], + snippet: 'South Dakota', + }, + _meta: { + engine: 'national-parks-demo', + score: 926068.7, + id: 'park_wind-cave', + }, + id: { + raw: 'park_wind-cave', + }, + }, +]; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/index.ts index ca6924879324a..7268c0fdbc4dc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/index.ts @@ -7,3 +7,4 @@ export { Curations } from './curations'; export { CurationCreation } from './curation_creation'; +export { CurationSuggestion } from './curation_suggestion'; From 33b501c5c72a8a58f1c8973c059cac6a2b7562c7 Mon Sep 17 00:00:00 2001 From: Tre Date: Fri, 1 Oct 2021 11:51:15 -0400 Subject: [PATCH 07/98] [Archive Migration] xpack..saved_objects_management/spaces_integration (#113047) --- .../spaces_integration.ts | 13 +-- .../spaces_integration/data.json | 96 ------------------- .../spaces_integration/mappings.json | 27 ------ .../spaces_integration.json | 44 +++++++++ 4 files changed, 51 insertions(+), 129 deletions(-) delete mode 100644 x-pack/test/functional/es_archives/saved_objects_management/spaces_integration/data.json delete mode 100644 x-pack/test/functional/es_archives/saved_objects_management/spaces_integration/mappings.json create mode 100644 x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/spaces_integration.json diff --git a/x-pack/test/functional/apps/saved_objects_management/spaces_integration.ts b/x-pack/test/functional/apps/saved_objects_management/spaces_integration.ts index e4da0b341dce9..62c742e39d02b 100644 --- a/x-pack/test/functional/apps/saved_objects_management/spaces_integration.ts +++ b/x-pack/test/functional/apps/saved_objects_management/spaces_integration.ts @@ -13,7 +13,6 @@ const getSpacePrefix = (spaceId: string) => { }; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects([ 'common', 'security', @@ -22,6 +21,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { 'settings', ]); const find = getService('find'); + const kibanaServer = getService('kibanaServer'); + const spacesService = getService('spaces'); const spaceId = 'space_1'; @@ -32,15 +33,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('spaces integration', () => { before(async () => { - await esArchiver.load( - 'x-pack/test/functional/es_archives/saved_objects_management/spaces_integration' + await spacesService.create({ id: spaceId, name: spaceId }); + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/spaces_integration', + { space: spaceId } ); }); after(async () => { - await esArchiver.unload( - 'x-pack/test/functional/es_archives/saved_objects_management/spaces_integration' - ); + await spacesService.delete(spaceId); }); beforeEach(async () => { diff --git a/x-pack/test/functional/es_archives/saved_objects_management/spaces_integration/data.json b/x-pack/test/functional/es_archives/saved_objects_management/spaces_integration/data.json deleted file mode 100644 index e6f4a0d00e198..0000000000000 --- a/x-pack/test/functional/es_archives/saved_objects_management/spaces_integration/data.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "type": "doc", - "value": { - "id": "space:default", - "index": ".kibana", - "source": { - "space": { - "_reserved": true, - "description": "This is the default space", - "name": "Default Space" - }, - "type": "space", - "updated_at": "2017-09-21T18:49:16.270Z" - }, - "type": "doc" - } -} - -{ - "type": "doc", - "value": { - "id": "space:space_1", - "index": ".kibana", - "source": { - "space": { - "description": "This is the first test space", - "name": "Space 1" - }, - "type": "space", - "updated_at": "2017-09-21T18:49:16.270Z" - }, - "type": "doc" - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "index-pattern:logstash-*", - "source": { - "index-pattern": { - "title": "logstash-*", - "timeFieldName": "@timestamp", - "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]" - }, - "type": "index-pattern", - "migrationVersion": { - "index-pattern": "6.5.0" - }, - "updated_at": "2018-12-21T00:43:07.096Z" - } - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "space_1:visualization:75c3e060-1e7c-11e9-8488-65449e65d0ed", - "source": { - "visualization": { - "title": "A Pie", - "visState": "{\"title\":\"A Pie\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"dimensions\":{\"metric\":{\"accessor\":0,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"count\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" - } - }, - "type": "visualization", - "namespace": "space_1", - "updated_at": "2019-01-22T19:32:31.206Z" - } - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "config:6.0.0", - "source": { - "config": { - "buildNum": 9007199254740991, - "defaultIndex": "logstash-*" - }, - "type": "config", - "updated_at": "2019-01-22T19:32:02.235Z" - } - } -} diff --git a/x-pack/test/functional/es_archives/saved_objects_management/spaces_integration/mappings.json b/x-pack/test/functional/es_archives/saved_objects_management/spaces_integration/mappings.json deleted file mode 100644 index 036dd7fad63f8..0000000000000 --- a/x-pack/test/functional/es_archives/saved_objects_management/spaces_integration/mappings.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "index", - "value": { - "aliases": { - ".kibana_$KIBANA_PACKAGE_VERSION": {}, - ".kibana": {} - }, - "index": ".kibana_$KIBANA_PACKAGE_VERSION_001", - "mappings": { - "dynamic": "false", - "properties": { - "type": { "type": "keyword" }, - "migrationVersion": { - "dynamic": "true", - "type": "object" - } - } - }, - "settings": { - "index": { - "auto_expand_replicas": "0-1", - "number_of_replicas": "0", - "number_of_shards": "1" - } - } - } -} diff --git a/x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/spaces_integration.json b/x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/spaces_integration.json new file mode 100644 index 0000000000000..4a7ab6d406736 --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/saved_objects_management/spaces_integration.json @@ -0,0 +1,44 @@ +{ + "attributes": { + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "@timestamp", + "title": "logstash-*" + }, + "coreMigrationVersion": "7.16.0", + "id": "logstash-*", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2021-09-29T14:44:14.268Z", + "version": "WzExLDFd" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "A Pie", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"A Pie\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"dimensions\":{\"metric\":{\"accessor\":0,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"count\"}},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "7.16.0", + "id": "75c3e060-1e7c-11e9-8488-65449e65d0ed", + "migrationVersion": { + "visualization": "7.14.0" + }, + "references": [ + { + "id": "logstash-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2021-09-29T14:45:14.428Z", + "version": "WzEzLDFd" +} \ No newline at end of file From 0b4a8c081c32556ac5bbb9cf247b146bf097e9b1 Mon Sep 17 00:00:00 2001 From: Tre Date: Fri, 1 Oct 2021 11:52:20 -0400 Subject: [PATCH 08/98] [QA][SO INFO SVC] Add jq filtering (#113302) --- package.json | 1 + .../services/saved_object_info/README.md | 68 +- .../services/saved_object_info/index.ts | 2 +- .../saved_object_info/saved_object_info.ts | 17 +- .../saved_objects_info_svc.md | 35 - yarn.lock | 618 +++++++++++++++++- 6 files changed, 687 insertions(+), 54 deletions(-) delete mode 100644 test/common/services/saved_object_info/saved_objects_info_svc.md diff --git a/package.json b/package.json index 3da4475e2cd01..28ed283aab2a5 100644 --- a/package.json +++ b/package.json @@ -771,6 +771,7 @@ "multimatch": "^4.0.0", "mutation-observer": "^1.0.3", "ncp": "^2.0.0", + "node-jq": "2.0.0", "node-sass": "^6.0.1", "null-loader": "^3.0.0", "nyc": "^15.0.1", diff --git a/test/common/services/saved_object_info/README.md b/test/common/services/saved_object_info/README.md index 5f081e48e2639..c5e36f2596ddc 100644 --- a/test/common/services/saved_object_info/README.md +++ b/test/common/services/saved_object_info/README.md @@ -1,6 +1,70 @@ -# Tips for using the SO INFO SVC CLI with JQ +# Tips for using the SO INFO SVC -## Myriad ways to use jq to discern discrete info from the svc +## From an FTR test +``` + ... + const soInfo = getService('savedObjectInfo'); + const log = getService('log'); + + describe('some test suite', function () { + ... + + after(async () => { + // "Normal" logging, without JQ + await soInfo.logSoTypes(log); + // Without a title, using JQ + await soInfo.filterSoTypes(log, '.[] | .key'); + // With a title, using JQ + await soInfo.filterSoTypes( + log, + 'reduce .[].doc_count as $item (0; . + $item)', + 'TOTAL count of ALL Saved Object types' + ); + // With a title, using JQ + await soInfo.filterSoTypes( + log, + '.[] | select(.key =="canvas-workpad-template") | .doc_count', + 'TOTAL count of canvas-workpad-template' + ); + }); +``` + +## From the CLI + +Run the cli +> the **--esUrl** arg is required; tells the svc which elastic search endpoint to use + +```shell + λ node scripts/saved_objs_info.js --esUrl http://elastic:changeme@localhost:9220 --soTypes +``` + +Result + +```shell + ### types: + + [ + { + doc_count: 5, + key: 'canvas-workpad-template' + }, + { + doc_count: 1, + key: 'apm-telemetry' + }, + { + doc_count: 1, + key: 'config' + }, + { + doc_count: 1, + key: 'space' + } + ] +``` + + +### Myriad ways to use JQ to discern discrete info from the svc Below, I will leave out the so types call, which is: `node scripts/saved_objs_info.js --esUrl http://elastic:changeme@localhost:9220 --soTypes --json` diff --git a/test/common/services/saved_object_info/index.ts b/test/common/services/saved_object_info/index.ts index 41367694373f3..799c9964fde7f 100644 --- a/test/common/services/saved_object_info/index.ts +++ b/test/common/services/saved_object_info/index.ts @@ -33,7 +33,7 @@ Show information pertaining to the saved objects in the .kibana index Examples: -See 'saved_objects_info_svc.md' +See 'README.md' `, flags: expectedFlags(), diff --git a/test/common/services/saved_object_info/saved_object_info.ts b/test/common/services/saved_object_info/saved_object_info.ts index 61472ea98d879..a75dfd8f3b5aa 100644 --- a/test/common/services/saved_object_info/saved_object_info.ts +++ b/test/common/services/saved_object_info/saved_object_info.ts @@ -13,6 +13,7 @@ import { flow, pipe } from 'fp-ts/function'; import * as TE from 'fp-ts/lib/TaskEither'; import * as T from 'fp-ts/lib/Task'; import { ToolingLog } from '@kbn/dev-utils'; +import { run as jq } from 'node-jq'; import { FtrService } from '../../ftr_provider_context'; import { print } from './utils'; @@ -60,8 +61,22 @@ export const types = export class SavedObjectInfoService extends FtrService { private readonly config = this.ctx.getService('config'); + private readonly typesF = async () => + await types(url.format(this.config.get('servers.elasticsearch')))(); + public async logSoTypes(log: ToolingLog, msg: string | null = null) { // @ts-ignore - pipe(await types(url.format(this.config.get('servers.elasticsearch'))), print(log)(msg)); + pipe(await this.typesF(), print(log)(msg)); + } + + /** + * See test/common/services/saved_object_info/README.md for "jq filtering" ideas. + */ + public async filterSoTypes(log: ToolingLog, jqFilter: string, title: string | null = null) { + pipe(await this.typesF(), filterAndLog); + + async function filterAndLog(payload: any) { + log.info(`${title ? title + '\n' : ''}${await jq(jqFilter, payload, { input: 'json' })}`); + } } } diff --git a/test/common/services/saved_object_info/saved_objects_info_svc.md b/test/common/services/saved_object_info/saved_objects_info_svc.md deleted file mode 100644 index 2d623129e2906..0000000000000 --- a/test/common/services/saved_object_info/saved_objects_info_svc.md +++ /dev/null @@ -1,35 +0,0 @@ -# Saved Objects Info Svc w/ CLI - -## Used via the cli - -Run the cli -> the **--esUrl** arg is required; tells the svc which elastic search endpoint to use - -```shell - λ node scripts/saved_objs_info.js --esUrl http://elastic:changeme@localhost:9220 --soTypes -``` - -Result - -```shell - ### types: - - [ - { - doc_count: 5, - key: 'canvas-workpad-template' - }, - { - doc_count: 1, - key: 'apm-telemetry' - }, - { - doc_count: 1, - key: 'config' - }, - { - doc_count: 1, - key: 'space' - } - ] -``` diff --git a/yarn.lock b/yarn.lock index 2813a39fa47a4..4eceb4a18162e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3804,6 +3804,11 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== +"@sindresorhus/is@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" + integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== + "@sindresorhus/is@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4" @@ -7254,6 +7259,13 @@ arch@^2.2.0: resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== +archive-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" + integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= + dependencies: + file-type "^4.2.0" + archiver-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2" @@ -8461,6 +8473,17 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +bin-build@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861" + integrity sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA== + dependencies: + decompress "^4.0.0" + download "^6.2.2" + execa "^0.7.0" + p-map-series "^1.0.0" + tempfile "^2.0.0" + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -8476,6 +8499,14 @@ binary-search@^1.3.3: resolved "https://registry.yarnpkg.com/binary-search/-/binary-search-1.3.6.tgz#e32426016a0c5092f0f3598836a1c7da3560565c" integrity sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA== +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + bl@^4.0.1, bl@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" @@ -8934,6 +8965,19 @@ btoa-lite@^1.0.0: resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -8954,6 +8998,11 @@ buffer-equal@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -9091,6 +9140,19 @@ cacheable-lookup@^5.0.3: resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz#049fdc59dffdd4fc285e8f4f82936591bd59fec3" integrity sha512-W+JBqF9SWe18A72XFzN/V/CULFzPm7sBXzzR6ekkE+3tLG72wFZrBiBZhrZuDoYexop4PHJVdFAKb/Nj9+tm9w== +cacheable-request@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" + integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0= + dependencies: + clone-response "1.0.2" + get-stream "3.0.0" + http-cache-semantics "3.8.1" + keyv "3.0.0" + lowercase-keys "1.0.0" + normalize-url "2.0.1" + responselike "1.0.2" + cacheable-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" @@ -9284,6 +9346,16 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= +caw@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" + integrity sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA== + dependencies: + get-proxy "^2.0.0" + isurl "^1.0.0-alpha5" + tunnel-agent "^0.6.0" + url-to-options "^1.0.1" + ccount@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17" @@ -9728,7 +9800,7 @@ clone-regexp@^2.1.0: dependencies: is-regexp "^2.0.0" -clone-response@^1.0.2: +clone-response@1.0.2, clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= @@ -10013,6 +10085,13 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commander@~2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= + dependencies: + graceful-readlink ">= 1.0.0" + common-tags@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -10123,7 +10202,7 @@ concaveman@*: robust-predicates "^2.0.4" tinyqueue "^2.0.3" -config-chain@^1.1.12: +config-chain@^1.1.11, config-chain@^1.1.12: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== @@ -10209,7 +10288,7 @@ contains-path@^0.1.0: resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= -content-disposition@0.5.3: +content-disposition@0.5.3, content-disposition@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== @@ -10532,6 +10611,15 @@ cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -11497,7 +11585,7 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -decompress-response@^3.3.0: +decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= @@ -11518,6 +11606,59 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" +decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== + dependencies: + file-type "^5.2.0" + is-stream "^1.1.0" + tar-stream "^1.5.2" + +decompress-tarbz2@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== + dependencies: + decompress-tar "^4.1.0" + file-type "^6.1.0" + is-stream "^1.1.0" + seek-bzip "^1.0.5" + unbzip2-stream "^1.0.9" + +decompress-targz@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== + dependencies: + decompress-tar "^4.1.1" + file-type "^5.2.0" + is-stream "^1.1.0" + +decompress-unzip@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= + dependencies: + file-type "^3.8.0" + get-stream "^2.2.0" + pify "^2.3.0" + yauzl "^2.4.2" + +decompress@^4.0.0, decompress@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" + integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== + dependencies: + decompress-tar "^4.0.0" + decompress-tarbz2 "^4.0.0" + decompress-targz "^4.0.0" + decompress-unzip "^4.0.1" + graceful-fs "^4.1.10" + make-dir "^1.0.0" + pify "^2.3.0" + strip-dirs "^2.0.0" + dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -12202,6 +12343,40 @@ dotignore@^0.1.2: dependencies: minimatch "^3.0.4" +download@^6.2.2: + version "6.2.5" + resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" + integrity sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA== + dependencies: + caw "^2.0.0" + content-disposition "^0.5.2" + decompress "^4.0.0" + ext-name "^5.0.0" + file-type "5.2.0" + filenamify "^2.0.0" + get-stream "^3.0.0" + got "^7.0.0" + make-dir "^1.0.0" + p-event "^1.0.0" + pify "^3.0.0" + +download@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/download/-/download-8.0.0.tgz#afc0b309730811731aae9f5371c9f46be73e51b1" + integrity sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA== + dependencies: + archive-type "^4.0.0" + content-disposition "^0.5.2" + decompress "^4.2.1" + ext-name "^5.0.0" + file-type "^11.1.0" + filenamify "^3.0.0" + get-stream "^4.1.0" + got "^8.3.1" + make-dir "^2.1.0" + p-event "^2.1.0" + pify "^4.0.1" + downshift@^3.2.10: version "3.4.8" resolved "https://registry.yarnpkg.com/downshift/-/downshift-3.4.8.tgz#06b7ad9e9c423a58e8a9049b2a00a5d19c7ef954" @@ -13319,6 +13494,19 @@ execa@4.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -13488,6 +13676,21 @@ express@^4.16.3, express@^4.17.0, express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" +ext-list@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" + integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA== + dependencies: + mime-db "^1.28.0" + +ext-name@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" + integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== + dependencies: + ext-list "^2.0.0" + sort-keys-length "^1.0.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -13833,11 +14036,36 @@ file-system-cache@^1.0.5: fs-extra "^0.30.0" ramda "^0.21.0" +file-type@5.2.0, file-type@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha1-LdvqfHP/42No365J3DOMBYwritY= + file-type@^10.9.0: version "10.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.9.0.tgz#f6c12c7cb9e6b8aeefd6917555fd4f9eadf31891" integrity sha512-9C5qtGR/fNibHC5gzuMmmgnjH3QDDLKMa8lYe9CiZVmAnI4aUaoMh40QyUPzzs0RYo837SOBKh7TYwle4G8E4w== +file-type@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-11.1.0.tgz#93780f3fed98b599755d846b99a1617a2ad063b8" + integrity sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g== + +file-type@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= + +file-type@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" + integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= + +file-type@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== + file-type@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18" @@ -13850,6 +14078,29 @@ filelist@^1.0.1: dependencies: minimatch "^3.0.4" +filename-reserved-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" + integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= + +filenamify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.0.0.tgz#bd162262c0b6e94bfbcdcf19a3bbb3764f785695" + integrity sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU= + dependencies: + filename-reserved-regex "^2.0.0" + strip-outer "^1.0.0" + trim-repeated "^1.0.0" + +filenamify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-3.0.0.tgz#9603eb688179f8c5d40d828626dcbb92c3a4672c" + integrity sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g== + dependencies: + filename-reserved-regex "^2.0.0" + strip-outer "^1.0.0" + trim-repeated "^1.0.0" + filesize@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" @@ -14242,7 +14493,7 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -from2@^2.1.0: +from2@^2.1.0, from2@^2.1.1: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= @@ -14505,6 +14756,13 @@ get-port@^5.0.0: resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== +get-proxy@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" + integrity sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw== + dependencies: + npm-conf "^1.1.0" + get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -14525,6 +14783,19 @@ get-stdin@^8.0.0: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== +get-stream@3.0.0, get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -14920,6 +15191,49 @@ got@^3.2.0: read-all-stream "^3.0.0" timed-out "^2.0.0" +got@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + dependencies: + decompress-response "^3.2.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-plain-obj "^1.1.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + p-cancelable "^0.3.0" + p-timeout "^1.1.1" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + url-parse-lax "^1.0.0" + url-to-options "^1.0.1" + +got@^8.3.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" + integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== + dependencies: + "@sindresorhus/is" "^0.7.0" + cacheable-request "^2.1.1" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + into-stream "^3.1.0" + is-retry-allowed "^1.1.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + mimic-response "^1.0.0" + p-cancelable "^0.4.0" + p-timeout "^2.0.1" + pify "^3.0.0" + safe-buffer "^5.1.1" + timed-out "^4.0.1" + url-parse-lax "^3.0.0" + url-to-options "^1.0.1" + got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -14942,11 +15256,16 @@ graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, g resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -graceful-fs@^4.2.3, graceful-fs@^4.2.6: +graceful-fs@^4.1.10, graceful-fs@^4.2.3, graceful-fs@^4.2.6: version "4.2.6" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + graphlib@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" @@ -15198,11 +15517,23 @@ has-glob@^1.0.0: dependencies: is-glob "^3.0.0" +has-symbol-support-x@^1.4.1: + version "1.4.2" + 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, has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + dependencies: + has-symbol-support-x "^1.4.1" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -15669,6 +16000,11 @@ htmlparser2@~3.3.0: domutils "1.1" readable-stream "1.0" +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" @@ -16166,6 +16502,14 @@ intl@^1.2.5: resolved "https://registry.yarnpkg.com/intl/-/intl-1.2.5.tgz#82244a2190c4e419f8371f5aa34daa3420e2abde" integrity sha1-giRKIZDE5Bn4Nx9ao02qNCDiq94= +into-stream@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" + integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY= + dependencies: + from2 "^2.1.1" + p-is-promise "^1.1.0" + invariant@2.2.4, invariant@^2.1.0, invariant@^2.1.1, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -16522,6 +16866,13 @@ is-interactive@^1.0.0: resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== +is-invalid-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-invalid-path/-/is-invalid-path-0.1.0.tgz#307a855b3cf1a938b44ea70d2c61106053714f34" + integrity sha1-MHqFWzzxqTi0TqcNLGEQYFNxTzQ= + dependencies: + is-glob "^2.0.0" + is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" @@ -16540,6 +16891,11 @@ is-native@^1.0.1: is-nil "^1.0.0" to-source-code "^1.0.0" +is-natural-number@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= + is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" @@ -16714,6 +17070,11 @@ is-resolvable@^1.0.0: resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== +is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== + is-root@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" @@ -16788,6 +17149,13 @@ is-valid-glob@^1.0.0: resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= +is-valid-path@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-valid-path/-/is-valid-path-0.1.1.tgz#110f9ff74c37f663e1ec7915eb451f2db93ac9df" + integrity sha1-EQ+f90w39mPh7HkV60UfLbk6yd8= + dependencies: + is-invalid-path "^0.1.0" + is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -16993,6 +17361,14 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + iterate-iterator@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.1.tgz#1693a768c1ddd79c969051459453f082fe82e9f6" @@ -18084,7 +18460,7 @@ kea@^2.4.2: resolved "https://registry.yarnpkg.com/kea/-/kea-2.4.2.tgz#53af42702f2c8962422e456e5dd943391bad26e9" integrity sha512-cdGds/gsJsbo/KbVAMk5/tTr229eDibVT1wmPPxPO/10zYb8GFoP3udBIQb+Hop5qGEu2wIHVdXwJvXqSS8JAg== -keyv@^3.0.0: +keyv@3.0.0, keyv@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" integrity sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA== @@ -18844,6 +19220,11 @@ lower-case@^2.0.1: dependencies: tslib "^1.10.0" +lowercase-keys@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -18862,7 +19243,7 @@ lowlight@^1.14.0: fault "^1.0.0" highlight.js "~10.4.0" -lru-cache@^4.0.0, lru-cache@^4.1.5: +lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -18908,6 +19289,13 @@ magic-string@0.25.1: dependencies: sourcemap-codec "^1.4.1" +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -19433,6 +19821,11 @@ mime-db@1.45.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== +mime-db@^1.28.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" + integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== + mime-types@^2.0.1, mime-types@^2.1.12, mime-types@^2.1.26, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" @@ -20276,6 +20669,19 @@ node-jose@1.1.0: node-forge "^0.7.6" uuid "^3.3.2" +node-jq@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/node-jq/-/node-jq-2.0.0.tgz#f0777ee2be6f6bfcf0ef58cc44689c422def6d97" + integrity sha512-gp8Xkr5RlZrXVK+VuUaF0JKtsGrElHb1hOjugdJFiCMHUup1OqsSBXZyeuwPkpty3P9taFHJmw4uzjQFIMFv4g== + dependencies: + bin-build "^3.0.0" + download "^8.0.0" + is-valid-path "^0.1.1" + joi "^17.4.0" + strip-eof "^2.0.0" + strip-final-newline "^2.0.0" + tempfile "^3.0.0" + "node-libs-browser@^1.0.0 || ^2.0.0", node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -20452,6 +20858,15 @@ normalize-selector@^0.2.0: resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= +normalize-url@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + normalize-url@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" @@ -20469,6 +20884,14 @@ now-and-later@^2.0.0: dependencies: once "^1.3.2" +npm-conf@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" + integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== + dependencies: + config-chain "^1.1.11" + pify "^3.0.0" + npm-normalize-package-bin@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" @@ -20970,6 +21393,16 @@ p-all@^2.1.0: dependencies: p-map "^2.0.0" +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + +p-cancelable@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" + integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== + p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -20985,6 +21418,20 @@ p-each-series@^2.1.0: resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== +p-event@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" + integrity sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU= + dependencies: + p-timeout "^1.1.1" + +p-event@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" + integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== + dependencies: + p-timeout "^2.0.1" + p-event@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.1.0.tgz#e92bb866d7e8e5b732293b1c8269d38e9982bf8e" @@ -21004,6 +21451,11 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-is-promise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" + integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -21053,6 +21505,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map-series@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" + integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco= + dependencies: + p-reduce "^1.0.0" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -21072,6 +21531,11 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +p-reduce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" + integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= + p-retry@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" @@ -21087,6 +21551,13 @@ p-retry@^4.2.0: "@types/retry" "^0.12.0" retry "^0.12.0" +p-timeout@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= + dependencies: + p-finally "^1.0.0" + p-timeout@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" @@ -21579,7 +22050,7 @@ picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== -pify@^2.0.0, pify@^2.2.0: +pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -22236,7 +22707,7 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prepend-http@^1.0.0: +prepend-http@^1.0.0, prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= @@ -22684,6 +23155,15 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + query-string@^6.13.2: version "6.13.2" resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.2.tgz#3585aa9412c957cbd358fd5eaca7466f05586dda" @@ -23696,7 +24176,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -"readable-stream@1 || 2", "readable-stream@2 || 3", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.3, readable-stream@~2.3.6: +"readable-stream@1 || 2", "readable-stream@2 || 3", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.3, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -24528,7 +25008,7 @@ resolve@~1.10.1: dependencies: path-parse "^1.0.6" -responselike@^1.0.2: +responselike@1.0.2, responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= @@ -24935,6 +25415,13 @@ seedrandom@^3.0.5: resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== +seek-bzip@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= + dependencies: + commander "~2.8.1" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -25503,6 +25990,20 @@ sonic-boom@^2.1.0: dependencies: atomic-sleep "^1.0.0" +sort-keys-length@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" + integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= + dependencies: + sort-keys "^1.0.0" + +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= + dependencies: + is-plain-obj "^1.0.0" + sort-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" @@ -26051,6 +26552,11 @@ stream-to-async-iterator@^0.2.0: resolved "https://registry.yarnpkg.com/stream-to-async-iterator/-/stream-to-async-iterator-0.2.0.tgz#bef5c885e9524f98b2fa5effecc357bd58483780" integrity sha1-vvXIhelST5iy+l7/7MNXvVhIN4A= +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -26273,11 +26779,23 @@ strip-bom@^4.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== +strip-dirs@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== + dependencies: + is-natural-number "^4.0.1" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-eof@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-2.0.0.tgz#2e3f3c5145d02de826eafb23e65b2faf675448b4" + integrity sha512-zLsJC+5P5hGu4Zmoq6I4uo6bTf1Nx6Z/vnZedxwnrcfkc38Vz6UiuqGOtS9bewFaoTCDErpqkV7v02htp9KEow== + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -26300,6 +26818,13 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-outer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.0.tgz#aac0ba60d2e90c5d4f275fd8869fd9a2d310ffb8" + integrity sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g= + dependencies: + escape-string-regexp "^1.0.2" + strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -26745,6 +27270,19 @@ tar-fs@^2.1.0: pump "^3.0.0" tar-stream "^2.0.0" +tar-stream@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + tar-stream@^2.0.0: version "2.1.3" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41" @@ -26844,6 +27382,27 @@ temp-dir@^1.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + +tempfile@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" + integrity sha1-awRGhWqbERTRhW/8vlCczLCXcmU= + dependencies: + temp-dir "^1.0.0" + uuid "^3.0.1" + +tempfile@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-3.0.0.tgz#5376a3492de7c54150d0cc0612c3f00e2cdaf76c" + integrity sha512-uNFCg478XovRi85iD42egu+eSFUmmka750Jy7L5tfHI5hQKKtbPnxaSaXAbBqCDYrw3wx4tXjKwci4/QmsZJxw== + dependencies: + temp-dir "^2.0.0" + uuid "^3.3.2" + tempy@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.3.0.tgz#6f6c5b295695a16130996ad5ab01a8bd726e8bf8" @@ -27049,6 +27608,11 @@ timed-out@^2.0.0: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" integrity sha1-84sK6B03R9YoAB9B2vxlKs5nHAo= +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + timers-browserify@^1.0.1: version "1.4.2" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" @@ -27161,6 +27725,11 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + to-camel-case@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-camel-case/-/to-camel-case-1.0.0.tgz#1a56054b2f9d696298ce66a60897322b6f423e46" @@ -27353,6 +27922,13 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== +trim-repeated@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" + integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= + dependencies: + escape-string-regexp "^1.0.2" + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -27704,7 +28280,7 @@ unbox-primitive@^1.0.0: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" -unbzip2-stream@^1.3.3: +unbzip2-stream@^1.0.9, unbzip2-stream@^1.3.3: version "1.4.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== @@ -28199,6 +28775,13 @@ url-loader@^4.0.0: mime-types "^2.1.26" schema-utils "^2.6.5" +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -28219,6 +28802,11 @@ url-template@^2.0.8: resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" integrity sha1-/FZaPMy/93MMd19WQflVV5FDnyE= +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= + url@^0.11.0, url@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" @@ -28371,7 +28959,7 @@ uuid@^2.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" integrity sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho= -uuid@^3.0.0, uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0: +uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -29850,7 +30438,7 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" -yauzl@^2.10.0: +yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= From cc73577f84fc3d1c93d30832423f5cfd8b410609 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 1 Oct 2021 09:07:57 -0700 Subject: [PATCH 09/98] Revert "chore: add modifications to staging automatically after eslint fix (#113443)" This reverts commit 5df9d41dbceb697c76181fcddea9873ec2d9d860. --- src/dev/run_precommit_hook.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/dev/run_precommit_hook.js b/src/dev/run_precommit_hook.js index 0a594a232cc22..e1eafaf28d95d 100644 --- a/src/dev/run_precommit_hook.js +++ b/src/dev/run_precommit_hook.js @@ -6,9 +6,6 @@ * Side Public License, v 1. */ -import SimpleGit from 'simple-git/promise'; - -import { REPO_ROOT } from '@kbn/utils'; import { run, combineErrors, createFlagError, createFailError } from '@kbn/dev-utils'; import * as Eslint from './eslint'; import * as Stylelint from './stylelint'; @@ -51,11 +48,6 @@ run( await Linter.lintFiles(log, filesToLint, { fix: flags.fix, }); - - if (flags.fix) { - const simpleGit = new SimpleGit(REPO_ROOT); - await simpleGit.add(filesToLint); - } } catch (error) { errors.push(error); } From b58e7218ad5bca6dd3b1f00917b2b5afa7443739 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Fri, 1 Oct 2021 10:56:54 -0600 Subject: [PATCH 10/98] [logging] Upgrade ECS to 1.12 (#113583) --- packages/kbn-logging/src/ecs/agent.ts | 2 +- .../kbn-logging/src/ecs/autonomous_system.ts | 2 +- packages/kbn-logging/src/ecs/base.ts | 2 +- packages/kbn-logging/src/ecs/client.ts | 2 +- packages/kbn-logging/src/ecs/cloud.ts | 2 +- .../kbn-logging/src/ecs/code_signature.ts | 4 +- packages/kbn-logging/src/ecs/container.ts | 9 ++- packages/kbn-logging/src/ecs/data_stream.ts | 18 +++++ packages/kbn-logging/src/ecs/destination.ts | 2 +- packages/kbn-logging/src/ecs/dll.ts | 2 +- packages/kbn-logging/src/ecs/dns.ts | 2 +- packages/kbn-logging/src/ecs/elf.ts | 71 +++++++++++++++++++ packages/kbn-logging/src/ecs/email.ts | 48 +++++++++++++ packages/kbn-logging/src/ecs/error.ts | 2 +- packages/kbn-logging/src/ecs/event.ts | 3 +- packages/kbn-logging/src/ecs/file.ts | 5 +- packages/kbn-logging/src/ecs/geo.ts | 2 +- packages/kbn-logging/src/ecs/group.ts | 2 +- packages/kbn-logging/src/ecs/hash.ts | 2 +- packages/kbn-logging/src/ecs/host.ts | 2 +- packages/kbn-logging/src/ecs/http.ts | 2 +- packages/kbn-logging/src/ecs/index.ts | 12 +++- packages/kbn-logging/src/ecs/interface.ts | 2 +- packages/kbn-logging/src/ecs/log.ts | 3 +- packages/kbn-logging/src/ecs/network.ts | 2 +- packages/kbn-logging/src/ecs/observer.ts | 2 +- packages/kbn-logging/src/ecs/orchestrator.ts | 32 +++++++++ packages/kbn-logging/src/ecs/organization.ts | 2 +- packages/kbn-logging/src/ecs/os.ts | 2 +- packages/kbn-logging/src/ecs/package.ts | 2 +- packages/kbn-logging/src/ecs/pe.ts | 2 +- packages/kbn-logging/src/ecs/process.ts | 7 +- packages/kbn-logging/src/ecs/registry.ts | 2 +- packages/kbn-logging/src/ecs/related.ts | 2 +- packages/kbn-logging/src/ecs/rule.ts | 2 +- packages/kbn-logging/src/ecs/server.ts | 2 +- packages/kbn-logging/src/ecs/service.ts | 4 +- packages/kbn-logging/src/ecs/source.ts | 2 +- packages/kbn-logging/src/ecs/threat.ts | 67 ++++++++++++++++- packages/kbn-logging/src/ecs/tls.ts | 2 +- packages/kbn-logging/src/ecs/tracing.ts | 2 +- packages/kbn-logging/src/ecs/url.ts | 2 +- packages/kbn-logging/src/ecs/user.ts | 2 +- packages/kbn-logging/src/ecs/user_agent.ts | 2 +- packages/kbn-logging/src/ecs/vlan.ts | 2 +- packages/kbn-logging/src/ecs/vulnerability.ts | 2 +- packages/kbn-logging/src/ecs/x509.ts | 2 +- .../__snapshots__/logging_system.test.ts.snap | 10 +-- .../__snapshots__/json_layout.test.ts.snap | 12 ++-- .../logging/layouts/json_layout.test.ts | 16 ++--- .../server/logging/layouts/json_layout.ts | 2 +- .../security/server/audit/audit_events.ts | 2 +- 52 files changed, 326 insertions(+), 67 deletions(-) create mode 100644 packages/kbn-logging/src/ecs/data_stream.ts create mode 100644 packages/kbn-logging/src/ecs/elf.ts create mode 100644 packages/kbn-logging/src/ecs/email.ts create mode 100644 packages/kbn-logging/src/ecs/orchestrator.ts diff --git a/packages/kbn-logging/src/ecs/agent.ts b/packages/kbn-logging/src/ecs/agent.ts index 0c2e7f7bbe44f..fc01fc649d266 100644 --- a/packages/kbn-logging/src/ecs/agent.ts +++ b/packages/kbn-logging/src/ecs/agent.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-agent.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-agent.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/autonomous_system.ts b/packages/kbn-logging/src/ecs/autonomous_system.ts index 85569b7dbabe1..5e59cb84e198b 100644 --- a/packages/kbn-logging/src/ecs/autonomous_system.ts +++ b/packages/kbn-logging/src/ecs/autonomous_system.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-as.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-as.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/base.ts b/packages/kbn-logging/src/ecs/base.ts index cf12cf0ea6e53..95c67623869f5 100644 --- a/packages/kbn-logging/src/ecs/base.ts +++ b/packages/kbn-logging/src/ecs/base.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-base.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-base.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/client.ts b/packages/kbn-logging/src/ecs/client.ts index ebee7826104a5..ef4b227593e62 100644 --- a/packages/kbn-logging/src/ecs/client.ts +++ b/packages/kbn-logging/src/ecs/client.ts @@ -17,7 +17,7 @@ interface NestedFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-client.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-client.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/cloud.ts b/packages/kbn-logging/src/ecs/cloud.ts index 8ef15d40f5529..803fc63bef216 100644 --- a/packages/kbn-logging/src/ecs/cloud.ts +++ b/packages/kbn-logging/src/ecs/cloud.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-cloud.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-cloud.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/code_signature.ts b/packages/kbn-logging/src/ecs/code_signature.ts index 277c3901a4f8b..e2e5eaf5c89af 100644 --- a/packages/kbn-logging/src/ecs/code_signature.ts +++ b/packages/kbn-logging/src/ecs/code_signature.ts @@ -7,15 +7,17 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-code_signature.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-code_signature.html * * @internal */ export interface EcsCodeSignature { + digest_algorithm?: string; exists?: boolean; signing_id?: string; status?: string; subject_name?: string; + timestamp?: string; team_id?: string; trusted?: boolean; valid?: boolean; diff --git a/packages/kbn-logging/src/ecs/container.ts b/packages/kbn-logging/src/ecs/container.ts index 6c5c85e7107e3..746b5b917a745 100644 --- a/packages/kbn-logging/src/ecs/container.ts +++ b/packages/kbn-logging/src/ecs/container.ts @@ -7,14 +7,21 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-container.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-container.html * * @internal */ export interface EcsContainer { + cpu?: { usage?: number }; + disk?: Disk; id?: string; image?: { name?: string; tag?: string[] }; labels?: Record; name?: string; runtime?: string; } + +interface Disk { + read?: { bytes?: number }; + write?: { bytes?: number }; +} diff --git a/packages/kbn-logging/src/ecs/data_stream.ts b/packages/kbn-logging/src/ecs/data_stream.ts new file mode 100644 index 0000000000000..fae0a30f69cc4 --- /dev/null +++ b/packages/kbn-logging/src/ecs/data_stream.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * https://www.elastic.co/guide/en/ecs/1.12/ecs-data_stream.html + * + * @internal + */ +export interface EcsDataStream { + dataset?: string; + namespace?: string; + type?: 'logs' | 'metrics'; +} diff --git a/packages/kbn-logging/src/ecs/destination.ts b/packages/kbn-logging/src/ecs/destination.ts index 6d2dbc8f431c9..00473da4a1e78 100644 --- a/packages/kbn-logging/src/ecs/destination.ts +++ b/packages/kbn-logging/src/ecs/destination.ts @@ -17,7 +17,7 @@ interface NestedFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-destination.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-destination.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/dll.ts b/packages/kbn-logging/src/ecs/dll.ts index d9ffa68b3f1a5..2983361f753e7 100644 --- a/packages/kbn-logging/src/ecs/dll.ts +++ b/packages/kbn-logging/src/ecs/dll.ts @@ -17,7 +17,7 @@ interface NestedFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-dll.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-dll.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/dns.ts b/packages/kbn-logging/src/ecs/dns.ts index c7a0e7983376c..c45f8f6b91fc5 100644 --- a/packages/kbn-logging/src/ecs/dns.ts +++ b/packages/kbn-logging/src/ecs/dns.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-dns.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-dns.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/elf.ts b/packages/kbn-logging/src/ecs/elf.ts new file mode 100644 index 0000000000000..a1cb2a85038e6 --- /dev/null +++ b/packages/kbn-logging/src/ecs/elf.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * https://www.elastic.co/guide/en/ecs/1.12/ecs-elf.html + * + * @internal + */ +export interface EcsElf { + architecture?: string; + byte_order?: string; + cpu_type?: string; + creation_date?: string; + exports?: Export[]; + imports?: Import[]; + header?: Header; + sections?: Section[]; + segments?: Segment[]; + shared_libraries?: string[]; + telfhash?: string; +} + +interface Export { + binding?: string; + name?: string; + section?: string; + size?: string; + type?: string; + version?: string; + visibility?: string; +} + +interface Import { + library?: string; + name?: string; + type?: string; + version?: string; +} + +interface Header { + abi_version?: string; + class?: string; + data?: string; + entrypoint?: number; + object_version?: string; + os_abi?: string; + type?: string; + version?: string; +} + +interface Section { + chi2?: number; + entropy?: number; + flags?: string; + name?: string; + physical_offset?: string; + physical_size?: number; + type?: string; + virtual_address?: number; + virtual_size?: number; +} + +interface Segment { + sections?: string; + type?: string; +} diff --git a/packages/kbn-logging/src/ecs/email.ts b/packages/kbn-logging/src/ecs/email.ts new file mode 100644 index 0000000000000..fcc3295fd71b5 --- /dev/null +++ b/packages/kbn-logging/src/ecs/email.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EcsFile } from './file'; +import { EcsHash } from './hash'; + +interface NestedFields { + // Not all hash types are explicitly supported, see + // https://github.com/elastic/ecs/pull/1569 + hash?: Pick; +} + +interface AttachmentNestedFields { + file?: Pick; +} + +/** + * No docs yet, see https://github.com/elastic/ecs/pull/1569 + * + * @internal + */ +export interface EcsEmail extends NestedFields { + attachments?: Attachment[]; + bcc?: string[]; + cc?: string[]; + content_type?: string; + delivery_timestamp?: string; + direction?: string; + from?: string; + local_id?: string; + message_id?: string; + origination_timestamp?: string; + reply_to?: string; + subject?: string; + 'subject.text'?: string; + to?: string[]; + x_mailer?: string; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface Attachment extends AttachmentNestedFields { + // intentionally empty +} diff --git a/packages/kbn-logging/src/ecs/error.ts b/packages/kbn-logging/src/ecs/error.ts index aee010748ddf2..a48b03075d469 100644 --- a/packages/kbn-logging/src/ecs/error.ts +++ b/packages/kbn-logging/src/ecs/error.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-error.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-error.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/event.ts b/packages/kbn-logging/src/ecs/event.ts index bf711410a9dd7..2baf320de8db4 100644 --- a/packages/kbn-logging/src/ecs/event.ts +++ b/packages/kbn-logging/src/ecs/event.ts @@ -7,12 +7,13 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-event.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-event.html * * @internal */ export interface EcsEvent { action?: string; + agent_id_status?: 'verified' | 'mismatch' | 'missing' | 'auth_metadata_missing'; category?: EcsEventCategory[]; code?: string; created?: string; diff --git a/packages/kbn-logging/src/ecs/file.ts b/packages/kbn-logging/src/ecs/file.ts index c09121607e0a4..dbd1653e21190 100644 --- a/packages/kbn-logging/src/ecs/file.ts +++ b/packages/kbn-logging/src/ecs/file.ts @@ -7,19 +7,21 @@ */ import { EcsCodeSignature } from './code_signature'; +import { EcsElf } from './elf'; import { EcsHash } from './hash'; import { EcsPe } from './pe'; import { EcsX509 } from './x509'; interface NestedFields { code_signature?: EcsCodeSignature; + elf?: EcsElf; hash?: EcsHash; pe?: EcsPe; x509?: EcsX509; } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-file.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-file.html * * @internal */ @@ -32,6 +34,7 @@ export interface EcsFile extends NestedFields { directory?: string; drive_letter?: string; extension?: string; + fork_name?: string; gid?: string; group?: string; inode?: string; diff --git a/packages/kbn-logging/src/ecs/geo.ts b/packages/kbn-logging/src/ecs/geo.ts index 85d45ca803aee..2373f4f119dfc 100644 --- a/packages/kbn-logging/src/ecs/geo.ts +++ b/packages/kbn-logging/src/ecs/geo.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-geo.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-geo.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/group.ts b/packages/kbn-logging/src/ecs/group.ts index e1bc339964fc0..c0d007d3bea0a 100644 --- a/packages/kbn-logging/src/ecs/group.ts +++ b/packages/kbn-logging/src/ecs/group.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-group.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-group.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/hash.ts b/packages/kbn-logging/src/ecs/hash.ts index 2ecd49f1ca092..fcf134349d7a4 100644 --- a/packages/kbn-logging/src/ecs/hash.ts +++ b/packages/kbn-logging/src/ecs/hash.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-hash.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-hash.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/host.ts b/packages/kbn-logging/src/ecs/host.ts index 085db30e13e7e..6c5046ef458e2 100644 --- a/packages/kbn-logging/src/ecs/host.ts +++ b/packages/kbn-logging/src/ecs/host.ts @@ -18,7 +18,7 @@ interface NestedFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-host.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-host.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/http.ts b/packages/kbn-logging/src/ecs/http.ts index c734c93318f5c..914e35c0f1fd7 100644 --- a/packages/kbn-logging/src/ecs/http.ts +++ b/packages/kbn-logging/src/ecs/http.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-http.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-http.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/index.ts b/packages/kbn-logging/src/ecs/index.ts index 30da3baa43b72..613945d22ad80 100644 --- a/packages/kbn-logging/src/ecs/index.ts +++ b/packages/kbn-logging/src/ecs/index.ts @@ -13,8 +13,10 @@ import { EcsAutonomousSystem } from './autonomous_system'; import { EcsClient } from './client'; import { EcsCloud } from './cloud'; import { EcsContainer } from './container'; +import { EcsDataStream } from './data_stream'; import { EcsDestination } from './destination'; import { EcsDns } from './dns'; +import { EcsEmail } from './email'; import { EcsError } from './error'; import { EcsEvent } from './event'; import { EcsFile } from './file'; @@ -24,6 +26,7 @@ import { EcsHttp } from './http'; import { EcsLog } from './log'; import { EcsNetwork } from './network'; import { EcsObserver } from './observer'; +import { EcsOrchestrator } from './orchestrator'; import { EcsOrganization } from './organization'; import { EcsPackage } from './package'; import { EcsProcess } from './process'; @@ -45,13 +48,13 @@ export { EcsEventCategory, EcsEventKind, EcsEventOutcome, EcsEventType } from '. interface EcsField { /** - * These typings were written as of ECS 1.9.0. + * These typings were written as of ECS 1.12.0. * Don't change this value without checking the rest * of the types to conform to that ECS version. * - * https://www.elastic.co/guide/en/ecs/1.9/index.html + * https://www.elastic.co/guide/en/ecs/1.12/index.html */ - version: '1.9.0'; + version: '1.12.0'; } /** @@ -68,8 +71,10 @@ export type Ecs = EcsBase & client?: EcsClient; cloud?: EcsCloud; container?: EcsContainer; + data_stream?: EcsDataStream; destination?: EcsDestination; dns?: EcsDns; + email?: EcsEmail; error?: EcsError; event?: EcsEvent; file?: EcsFile; @@ -79,6 +84,7 @@ export type Ecs = EcsBase & log?: EcsLog; network?: EcsNetwork; observer?: EcsObserver; + orchestrator?: EcsOrchestrator; organization?: EcsOrganization; package?: EcsPackage; process?: EcsProcess; diff --git a/packages/kbn-logging/src/ecs/interface.ts b/packages/kbn-logging/src/ecs/interface.ts index 49b33e8338184..80c00fe8d8a12 100644 --- a/packages/kbn-logging/src/ecs/interface.ts +++ b/packages/kbn-logging/src/ecs/interface.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-interface.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-interface.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/log.ts b/packages/kbn-logging/src/ecs/log.ts index 8bc2e4982e96c..e55915094e528 100644 --- a/packages/kbn-logging/src/ecs/log.ts +++ b/packages/kbn-logging/src/ecs/log.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-log.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-log.html * * @internal */ @@ -16,6 +16,7 @@ export interface EcsLog { level?: string; logger?: string; origin?: Origin; + /** @deprecated - use `event.original` instead */ original?: string; syslog?: Syslog; } diff --git a/packages/kbn-logging/src/ecs/network.ts b/packages/kbn-logging/src/ecs/network.ts index 912427b6cdb7e..6d00aa10a9968 100644 --- a/packages/kbn-logging/src/ecs/network.ts +++ b/packages/kbn-logging/src/ecs/network.ts @@ -14,7 +14,7 @@ interface NestedFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-network.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-network.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/observer.ts b/packages/kbn-logging/src/ecs/observer.ts index be2636d15dcdf..89e1cbb59880c 100644 --- a/packages/kbn-logging/src/ecs/observer.ts +++ b/packages/kbn-logging/src/ecs/observer.ts @@ -29,7 +29,7 @@ interface NestedIngressFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-observer.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-observer.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/orchestrator.ts b/packages/kbn-logging/src/ecs/orchestrator.ts new file mode 100644 index 0000000000000..ac92006091a93 --- /dev/null +++ b/packages/kbn-logging/src/ecs/orchestrator.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * https://www.elastic.co/guide/en/ecs/1.12/ecs-orchestrator.html + * + * @internal + */ +export interface EcsOrchestrator { + api_version?: string; + cluster?: Cluster; + namespace?: string; + organization?: string; + resource?: Resource; + type?: string; +} + +interface Cluster { + name?: string; + url?: string; + version?: string; +} + +interface Resource { + name?: string; + type?: string; +} diff --git a/packages/kbn-logging/src/ecs/organization.ts b/packages/kbn-logging/src/ecs/organization.ts index 370e6b2646a2f..e9274f864b7d2 100644 --- a/packages/kbn-logging/src/ecs/organization.ts +++ b/packages/kbn-logging/src/ecs/organization.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-organization.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-organization.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/os.ts b/packages/kbn-logging/src/ecs/os.ts index 342eb14264fd3..76690bffaf69f 100644 --- a/packages/kbn-logging/src/ecs/os.ts +++ b/packages/kbn-logging/src/ecs/os.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-os.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-os.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/package.ts b/packages/kbn-logging/src/ecs/package.ts index 10528066f3f29..f0e75b3cd2753 100644 --- a/packages/kbn-logging/src/ecs/package.ts +++ b/packages/kbn-logging/src/ecs/package.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-package.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-package.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/pe.ts b/packages/kbn-logging/src/ecs/pe.ts index bd53b7048a50d..c017dfa87fb23 100644 --- a/packages/kbn-logging/src/ecs/pe.ts +++ b/packages/kbn-logging/src/ecs/pe.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-pe.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-pe.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/process.ts b/packages/kbn-logging/src/ecs/process.ts index 9a034c30fd531..4e527d0b21d4c 100644 --- a/packages/kbn-logging/src/ecs/process.ts +++ b/packages/kbn-logging/src/ecs/process.ts @@ -7,18 +7,21 @@ */ import { EcsCodeSignature } from './code_signature'; +import { EcsElf } from './elf'; import { EcsHash } from './hash'; import { EcsPe } from './pe'; interface NestedFields { code_signature?: EcsCodeSignature; + elf?: EcsElf; hash?: EcsHash; parent?: EcsProcess; pe?: EcsPe; + target?: EcsProcess; } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-process.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-process.html * * @internal */ @@ -26,6 +29,7 @@ export interface EcsProcess extends NestedFields { args?: string[]; args_count?: number; command_line?: string; + end?: string; entity_id?: string; executable?: string; exit_code?: number; @@ -34,7 +38,6 @@ export interface EcsProcess extends NestedFields { pid?: number; ppid?: number; start?: string; - thread?: { id?: number; name?: string }; title?: string; uptime?: number; working_directory?: string; diff --git a/packages/kbn-logging/src/ecs/registry.ts b/packages/kbn-logging/src/ecs/registry.ts index ba7ef699e2cdb..8cc12de6c136e 100644 --- a/packages/kbn-logging/src/ecs/registry.ts +++ b/packages/kbn-logging/src/ecs/registry.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-registry.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-registry.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/related.ts b/packages/kbn-logging/src/ecs/related.ts index 33c3ff50540ce..6616780177d16 100644 --- a/packages/kbn-logging/src/ecs/related.ts +++ b/packages/kbn-logging/src/ecs/related.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-related.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-related.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/rule.ts b/packages/kbn-logging/src/ecs/rule.ts index c6bf1ce96552a..5a961302de918 100644 --- a/packages/kbn-logging/src/ecs/rule.ts +++ b/packages/kbn-logging/src/ecs/rule.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-rule.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-rule.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/server.ts b/packages/kbn-logging/src/ecs/server.ts index 9b2a9b1a11b42..01b2394c6bccc 100644 --- a/packages/kbn-logging/src/ecs/server.ts +++ b/packages/kbn-logging/src/ecs/server.ts @@ -17,7 +17,7 @@ interface NestedFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-server.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-server.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/service.ts b/packages/kbn-logging/src/ecs/service.ts index 4cd79e928c076..04cff203da961 100644 --- a/packages/kbn-logging/src/ecs/service.ts +++ b/packages/kbn-logging/src/ecs/service.ts @@ -7,11 +7,13 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-service.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-service.html * * @internal */ export interface EcsService { + address?: string; + environment?: string; ephemeral_id?: string; id?: string; name?: string; diff --git a/packages/kbn-logging/src/ecs/source.ts b/packages/kbn-logging/src/ecs/source.ts index 9ec7e2521d0b9..2879adb0d996e 100644 --- a/packages/kbn-logging/src/ecs/source.ts +++ b/packages/kbn-logging/src/ecs/source.ts @@ -17,7 +17,7 @@ interface NestedFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-source.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-source.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/threat.ts b/packages/kbn-logging/src/ecs/threat.ts index ac6033949fccd..78adf583b0ee2 100644 --- a/packages/kbn-logging/src/ecs/threat.ts +++ b/packages/kbn-logging/src/ecs/threat.ts @@ -6,17 +6,82 @@ * Side Public License, v 1. */ +import { EcsAutonomousSystem } from './autonomous_system'; +import { EcsFile } from './file'; +import { EcsGeo } from './geo'; +import { EcsRegistry } from './registry'; +import { EcsUrl } from './url'; +import { EcsX509 } from './x509'; + +interface IndicatorNestedFields { + as?: EcsAutonomousSystem; + file?: EcsFile; + geo?: EcsGeo; + registry?: EcsRegistry; + url?: EcsUrl; + x509?: EcsX509; +} + /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-threat.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-threat.html * * @internal */ export interface EcsThreat { + enrichments?: Enrichment[]; + indicator?: Indicator; framework?: string; + group?: Group; + software?: Software; tactic?: Tactic; technique?: Technique; } +interface Enrichment { + indicator?: Indicator; + matched?: Matched; +} + +interface Indicator extends IndicatorNestedFields { + confidence?: string; + description?: string; + email?: { address?: string }; + first_seen?: string; + ip?: string; + last_seen?: string; + marking?: { tlp?: string }; + modified_at?: string; + port?: number; + provider?: string; + reference?: string; + scanner_stats?: number; + sightings?: number; + type?: string; +} + +interface Matched { + atomic?: string; + field?: string; + id?: string; + index?: string; + type?: string; +} + +interface Group { + alias?: string[]; + id?: string; + name?: string; + reference?: string; +} + +interface Software { + id?: string; + name?: string; + platforms?: string[]; + reference?: string; + type?: string; +} + interface Tactic { id?: string[]; name?: string[]; diff --git a/packages/kbn-logging/src/ecs/tls.ts b/packages/kbn-logging/src/ecs/tls.ts index b04d03d650908..75667170f6059 100644 --- a/packages/kbn-logging/src/ecs/tls.ts +++ b/packages/kbn-logging/src/ecs/tls.ts @@ -17,7 +17,7 @@ interface NestedServerFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-tls.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-tls.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/tracing.ts b/packages/kbn-logging/src/ecs/tracing.ts index 1abbbd4b4c8a2..ea1ff300e4c3f 100644 --- a/packages/kbn-logging/src/ecs/tracing.ts +++ b/packages/kbn-logging/src/ecs/tracing.ts @@ -12,7 +12,7 @@ * the base fields, we will need to do an intersection with these types at * the root level. * - * https://www.elastic.co/guide/en/ecs/1.9/ecs-tracing.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-tracing.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/url.ts b/packages/kbn-logging/src/ecs/url.ts index 5985b28a4f6c3..069ff6b09aec5 100644 --- a/packages/kbn-logging/src/ecs/url.ts +++ b/packages/kbn-logging/src/ecs/url.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-url.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-url.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/user.ts b/packages/kbn-logging/src/ecs/user.ts index 3ab0c946b49b7..6bce3552e23ec 100644 --- a/packages/kbn-logging/src/ecs/user.ts +++ b/packages/kbn-logging/src/ecs/user.ts @@ -20,7 +20,7 @@ interface NestedFields { * placed at the root level, but not if it is nested inside another field like * `destination`. A more detailed explanation of these nuances can be found at: * - * https://www.elastic.co/guide/en/ecs/1.9/ecs-user-usage.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-user-usage.html * * As a result, we need to export a separate `NestedUser` type to import into * other interfaces internally. This contains the reusable subset of properties diff --git a/packages/kbn-logging/src/ecs/user_agent.ts b/packages/kbn-logging/src/ecs/user_agent.ts index f77b3ba9e1f0f..0ff8aa681d964 100644 --- a/packages/kbn-logging/src/ecs/user_agent.ts +++ b/packages/kbn-logging/src/ecs/user_agent.ts @@ -13,7 +13,7 @@ interface NestedFields { } /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-user_agent.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-user_agent.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/vlan.ts b/packages/kbn-logging/src/ecs/vlan.ts index 646f8ee17fd03..a2939380ea57f 100644 --- a/packages/kbn-logging/src/ecs/vlan.ts +++ b/packages/kbn-logging/src/ecs/vlan.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-vlan.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-vlan.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/vulnerability.ts b/packages/kbn-logging/src/ecs/vulnerability.ts index 2c26d557d2ba9..a3648a9c5df17 100644 --- a/packages/kbn-logging/src/ecs/vulnerability.ts +++ b/packages/kbn-logging/src/ecs/vulnerability.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-vulnerability.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-vulnerability.html * * @internal */ diff --git a/packages/kbn-logging/src/ecs/x509.ts b/packages/kbn-logging/src/ecs/x509.ts index 35bc1b458579a..a38fb93585c83 100644 --- a/packages/kbn-logging/src/ecs/x509.ts +++ b/packages/kbn-logging/src/ecs/x509.ts @@ -7,7 +7,7 @@ */ /** - * https://www.elastic.co/guide/en/ecs/1.9/ecs-x509.html + * https://www.elastic.co/guide/en/ecs/1.12/ecs-x509.html * * @internal */ diff --git a/src/core/server/logging/__snapshots__/logging_system.test.ts.snap b/src/core/server/logging/__snapshots__/logging_system.test.ts.snap index d74317203d78e..851cfd6cf3bcc 100644 --- a/src/core/server/logging/__snapshots__/logging_system.test.ts.snap +++ b/src/core/server/logging/__snapshots__/logging_system.test.ts.snap @@ -16,7 +16,7 @@ exports[`asLoggerFactory() only allows to create new loggers. 1`] = ` Object { "@timestamp": "2012-01-30T22:33:22.011-05:00", "ecs": Object { - "version": "1.9.0", + "version": "1.12.0", }, "log": Object { "level": "TRACE", @@ -33,7 +33,7 @@ exports[`asLoggerFactory() only allows to create new loggers. 2`] = ` Object { "@timestamp": "2012-01-30T17:33:22.011-05:00", "ecs": Object { - "version": "1.9.0", + "version": "1.12.0", }, "log": Object { "level": "INFO", @@ -51,7 +51,7 @@ exports[`asLoggerFactory() only allows to create new loggers. 3`] = ` Object { "@timestamp": "2012-01-30T12:33:22.011-05:00", "ecs": Object { - "version": "1.9.0", + "version": "1.12.0", }, "log": Object { "level": "FATAL", @@ -68,7 +68,7 @@ exports[`flushes memory buffer logger and switches to real logger once config is Object { "@timestamp": "2012-02-01T09:33:22.011-05:00", "ecs": Object { - "version": "1.9.0", + "version": "1.12.0", }, "log": Object { "level": "INFO", @@ -86,7 +86,7 @@ exports[`flushes memory buffer logger and switches to real logger once config is Object { "@timestamp": "2012-01-31T23:33:22.011-05:00", "ecs": Object { - "version": "1.9.0", + "version": "1.12.0", }, "log": Object { "level": "INFO", diff --git a/src/core/server/logging/layouts/__snapshots__/json_layout.test.ts.snap b/src/core/server/logging/layouts/__snapshots__/json_layout.test.ts.snap index a131d5c8a9248..e128651e61b40 100644 --- a/src/core/server/logging/layouts/__snapshots__/json_layout.test.ts.snap +++ b/src/core/server/logging/layouts/__snapshots__/json_layout.test.ts.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`\`format()\` correctly formats record. 1`] = `"{\\"ecs\\":{\\"version\\":\\"1.9.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-1\\",\\"error\\":{\\"message\\":\\"Some error message\\",\\"type\\":\\"Some error name\\",\\"stack_trace\\":\\"Some error stack\\"},\\"log\\":{\\"level\\":\\"FATAL\\",\\"logger\\":\\"context-1\\"},\\"process\\":{\\"pid\\":5355}}"`; +exports[`\`format()\` correctly formats record. 1`] = `"{\\"ecs\\":{\\"version\\":\\"1.12.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-1\\",\\"error\\":{\\"message\\":\\"Some error message\\",\\"type\\":\\"Some error name\\",\\"stack_trace\\":\\"Some error stack\\"},\\"log\\":{\\"level\\":\\"FATAL\\",\\"logger\\":\\"context-1\\"},\\"process\\":{\\"pid\\":5355}}"`; -exports[`\`format()\` correctly formats record. 2`] = `"{\\"ecs\\":{\\"version\\":\\"1.9.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-2\\",\\"log\\":{\\"level\\":\\"ERROR\\",\\"logger\\":\\"context-2\\"},\\"process\\":{\\"pid\\":5355}}"`; +exports[`\`format()\` correctly formats record. 2`] = `"{\\"ecs\\":{\\"version\\":\\"1.12.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-2\\",\\"log\\":{\\"level\\":\\"ERROR\\",\\"logger\\":\\"context-2\\"},\\"process\\":{\\"pid\\":5355}}"`; -exports[`\`format()\` correctly formats record. 3`] = `"{\\"ecs\\":{\\"version\\":\\"1.9.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-3\\",\\"log\\":{\\"level\\":\\"WARN\\",\\"logger\\":\\"context-3\\"},\\"process\\":{\\"pid\\":5355}}"`; +exports[`\`format()\` correctly formats record. 3`] = `"{\\"ecs\\":{\\"version\\":\\"1.12.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-3\\",\\"log\\":{\\"level\\":\\"WARN\\",\\"logger\\":\\"context-3\\"},\\"process\\":{\\"pid\\":5355}}"`; -exports[`\`format()\` correctly formats record. 4`] = `"{\\"ecs\\":{\\"version\\":\\"1.9.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-4\\",\\"log\\":{\\"level\\":\\"DEBUG\\",\\"logger\\":\\"context-4\\"},\\"process\\":{\\"pid\\":5355}}"`; +exports[`\`format()\` correctly formats record. 4`] = `"{\\"ecs\\":{\\"version\\":\\"1.12.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-4\\",\\"log\\":{\\"level\\":\\"DEBUG\\",\\"logger\\":\\"context-4\\"},\\"process\\":{\\"pid\\":5355}}"`; -exports[`\`format()\` correctly formats record. 5`] = `"{\\"ecs\\":{\\"version\\":\\"1.9.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-5\\",\\"log\\":{\\"level\\":\\"INFO\\",\\"logger\\":\\"context-5\\"},\\"process\\":{\\"pid\\":5355}}"`; +exports[`\`format()\` correctly formats record. 5`] = `"{\\"ecs\\":{\\"version\\":\\"1.12.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-5\\",\\"log\\":{\\"level\\":\\"INFO\\",\\"logger\\":\\"context-5\\"},\\"process\\":{\\"pid\\":5355}}"`; -exports[`\`format()\` correctly formats record. 6`] = `"{\\"ecs\\":{\\"version\\":\\"1.9.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-6\\",\\"log\\":{\\"level\\":\\"TRACE\\",\\"logger\\":\\"context-6\\"},\\"process\\":{\\"pid\\":5355}}"`; +exports[`\`format()\` correctly formats record. 6`] = `"{\\"ecs\\":{\\"version\\":\\"1.12.0\\"},\\"@timestamp\\":\\"2012-02-01T09:30:22.011-05:00\\",\\"message\\":\\"message-6\\",\\"log\\":{\\"level\\":\\"TRACE\\",\\"logger\\":\\"context-6\\"},\\"process\\":{\\"pid\\":5355}}"`; diff --git a/src/core/server/logging/layouts/json_layout.test.ts b/src/core/server/logging/layouts/json_layout.test.ts index e76e3fb4402bb..034e2abf46461 100644 --- a/src/core/server/logging/layouts/json_layout.test.ts +++ b/src/core/server/logging/layouts/json_layout.test.ts @@ -74,7 +74,7 @@ test('`format()` correctly formats record.', () => { } }); -test('`format()` correctly formats record with meta-data', () => { +test('`format()` correctly formats record with meta-data and correct ECS version', () => { const layout = new JsonLayout(); expect( @@ -94,7 +94,7 @@ test('`format()` correctly formats record with meta-data', () => { }) ) ).toStrictEqual({ - ecs: { version: '1.9.0' }, + ecs: { version: '1.12.0' }, '@timestamp': '2012-02-01T09:30:22.011-05:00', log: { level: 'DEBUG', @@ -136,7 +136,7 @@ test('`format()` correctly formats error record with meta-data', () => { }) ) ).toStrictEqual({ - ecs: { version: '1.9.0' }, + ecs: { version: expect.any(String) }, '@timestamp': '2012-02-01T09:30:22.011-05:00', log: { level: 'DEBUG', @@ -176,7 +176,7 @@ test('format() meta can merge override logs', () => { }) ) ).toStrictEqual({ - ecs: { version: '1.9.0' }, + ecs: { version: expect.any(String) }, '@timestamp': '2012-02-01T09:30:22.011-05:00', message: 'foo', log: { @@ -206,7 +206,7 @@ test('format() meta can not override message', () => { }) ) ).toStrictEqual({ - ecs: { version: '1.9.0' }, + ecs: { version: expect.any(String) }, '@timestamp': '2012-02-01T09:30:22.011-05:00', message: 'foo', log: { @@ -235,7 +235,7 @@ test('format() meta can not override ecs version', () => { }) ) ).toStrictEqual({ - ecs: { version: '1.9.0' }, + ecs: { version: expect.any(String) }, '@timestamp': '2012-02-01T09:30:22.011-05:00', message: 'foo', log: { @@ -267,7 +267,7 @@ test('format() meta can not override logger or level', () => { }) ) ).toStrictEqual({ - ecs: { version: '1.9.0' }, + ecs: { version: expect.any(String) }, '@timestamp': '2012-02-01T09:30:22.011-05:00', message: 'foo', log: { @@ -296,7 +296,7 @@ test('format() meta can not override timestamp', () => { }) ) ).toStrictEqual({ - ecs: { version: '1.9.0' }, + ecs: { version: expect.any(String) }, '@timestamp': '2012-02-01T09:30:22.011-05:00', message: 'foo', log: { diff --git a/src/core/server/logging/layouts/json_layout.ts b/src/core/server/logging/layouts/json_layout.ts index add88cc01b6d2..820ed32045f15 100644 --- a/src/core/server/logging/layouts/json_layout.ts +++ b/src/core/server/logging/layouts/json_layout.ts @@ -43,7 +43,7 @@ export class JsonLayout implements Layout { public format(record: LogRecord): string { const log: Ecs = { - ecs: { version: '1.9.0' }, + ecs: { version: '1.12.0' }, '@timestamp': moment(record.timestamp).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), message: record.message, error: JsonLayout.errorToSerializableObject(record.error), diff --git a/x-pack/plugins/security/server/audit/audit_events.ts b/x-pack/plugins/security/server/audit/audit_events.ts index 611e7bd456da3..a4025b619365f 100644 --- a/x-pack/plugins/security/server/audit/audit_events.ts +++ b/x-pack/plugins/security/server/audit/audit_events.ts @@ -10,7 +10,7 @@ import type { EcsEventOutcome, EcsEventType, KibanaRequest, LogMeta } from 'src/ import type { AuthenticationResult } from '../authentication/authentication_result'; /** - * Audit event schema using ECS format: https://www.elastic.co/guide/en/ecs/1.9/index.html + * Audit event schema using ECS format: https://www.elastic.co/guide/en/ecs/1.12/index.html * * If you add additional fields to the schema ensure you update the Kibana Filebeat module: * https://github.com/elastic/beats/tree/master/filebeat/module/kibana From a75003dc47e27b94aa5762feea49bcd9d831f4bf Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Fri, 1 Oct 2021 10:03:14 -0700 Subject: [PATCH 11/98] Annotates beats tutorials with custom integration categories (#113565) --- src/plugins/home/server/tutorials/aerospike_metrics/index.ts | 1 + src/plugins/home/server/tutorials/apache_logs/index.ts | 1 + src/plugins/home/server/tutorials/apache_metrics/index.ts | 1 + src/plugins/home/server/tutorials/auditbeat/index.ts | 1 + src/plugins/home/server/tutorials/auditd_logs/index.ts | 1 + src/plugins/home/server/tutorials/azure_logs/index.ts | 1 + src/plugins/home/server/tutorials/azure_metrics/index.ts | 1 + src/plugins/home/server/tutorials/barracuda_logs/index.ts | 1 + src/plugins/home/server/tutorials/bluecoat_logs/index.ts | 1 + src/plugins/home/server/tutorials/cef_logs/index.ts | 1 + src/plugins/home/server/tutorials/ceph_metrics/index.ts | 1 + src/plugins/home/server/tutorials/checkpoint_logs/index.ts | 1 + src/plugins/home/server/tutorials/cisco_logs/index.ts | 1 + src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts | 1 + src/plugins/home/server/tutorials/consul_metrics/index.ts | 1 + src/plugins/home/server/tutorials/coredns_logs/index.ts | 1 + src/plugins/home/server/tutorials/coredns_metrics/index.ts | 1 + src/plugins/home/server/tutorials/couchbase_metrics/index.ts | 1 + src/plugins/home/server/tutorials/couchdb_metrics/index.ts | 1 + src/plugins/home/server/tutorials/crowdstrike_logs/index.ts | 1 + src/plugins/home/server/tutorials/cylance_logs/index.ts | 1 + src/plugins/home/server/tutorials/docker_metrics/index.ts | 1 + src/plugins/home/server/tutorials/dropwizard_metrics/index.ts | 1 + src/plugins/home/server/tutorials/elasticsearch_logs/index.ts | 1 + src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts | 1 + src/plugins/home/server/tutorials/envoyproxy_logs/index.ts | 1 + src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts | 1 + src/plugins/home/server/tutorials/etcd_metrics/index.ts | 1 + src/plugins/home/server/tutorials/f5_logs/index.ts | 1 + src/plugins/home/server/tutorials/fortinet_logs/index.ts | 1 + src/plugins/home/server/tutorials/gcp_logs/index.ts | 1 + src/plugins/home/server/tutorials/gcp_metrics/index.ts | 1 + src/plugins/home/server/tutorials/golang_metrics/index.ts | 1 + src/plugins/home/server/tutorials/gsuite_logs/index.ts | 1 + src/plugins/home/server/tutorials/haproxy_logs/index.ts | 1 + src/plugins/home/server/tutorials/haproxy_metrics/index.ts | 1 + src/plugins/home/server/tutorials/ibmmq_logs/index.ts | 1 + src/plugins/home/server/tutorials/ibmmq_metrics/index.ts | 1 + src/plugins/home/server/tutorials/icinga_logs/index.ts | 1 + src/plugins/home/server/tutorials/iis_logs/index.ts | 1 + src/plugins/home/server/tutorials/iis_metrics/index.ts | 1 + src/plugins/home/server/tutorials/imperva_logs/index.ts | 1 + src/plugins/home/server/tutorials/infoblox_logs/index.ts | 1 + src/plugins/home/server/tutorials/iptables_logs/index.ts | 1 + src/plugins/home/server/tutorials/juniper_logs/index.ts | 1 + src/plugins/home/server/tutorials/kafka_logs/index.ts | 1 + src/plugins/home/server/tutorials/kafka_metrics/index.ts | 1 + src/plugins/home/server/tutorials/kibana_logs/index.ts | 1 + src/plugins/home/server/tutorials/kibana_metrics/index.ts | 1 + src/plugins/home/server/tutorials/kubernetes_metrics/index.ts | 1 + src/plugins/home/server/tutorials/logstash_logs/index.ts | 1 + src/plugins/home/server/tutorials/logstash_metrics/index.ts | 1 + src/plugins/home/server/tutorials/memcached_metrics/index.ts | 1 + src/plugins/home/server/tutorials/microsoft_logs/index.ts | 1 + src/plugins/home/server/tutorials/misp_logs/index.ts | 1 + src/plugins/home/server/tutorials/mongodb_logs/index.ts | 1 + src/plugins/home/server/tutorials/mongodb_metrics/index.ts | 1 + src/plugins/home/server/tutorials/mssql_logs/index.ts | 1 + src/plugins/home/server/tutorials/mssql_metrics/index.ts | 1 + src/plugins/home/server/tutorials/munin_metrics/index.ts | 1 + src/plugins/home/server/tutorials/mysql_logs/index.ts | 1 + src/plugins/home/server/tutorials/mysql_metrics/index.ts | 1 + src/plugins/home/server/tutorials/nats_logs/index.ts | 1 + src/plugins/home/server/tutorials/nats_metrics/index.ts | 1 + src/plugins/home/server/tutorials/netflow_logs/index.ts | 1 + src/plugins/home/server/tutorials/netscout_logs/index.ts | 1 + src/plugins/home/server/tutorials/nginx_logs/index.ts | 1 + src/plugins/home/server/tutorials/nginx_metrics/index.ts | 1 + src/plugins/home/server/tutorials/o365_logs/index.ts | 1 + src/plugins/home/server/tutorials/okta_logs/index.ts | 1 + src/plugins/home/server/tutorials/openmetrics_metrics/index.ts | 1 + src/plugins/home/server/tutorials/osquery_logs/index.ts | 1 + src/plugins/home/server/tutorials/panw_logs/index.ts | 1 + src/plugins/home/server/tutorials/php_fpm_metrics/index.ts | 1 + src/plugins/home/server/tutorials/postgresql_logs/index.ts | 1 + src/plugins/home/server/tutorials/postgresql_metrics/index.ts | 1 + src/plugins/home/server/tutorials/rabbitmq_logs/index.ts | 1 + src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts | 1 + src/plugins/home/server/tutorials/radware_logs/index.ts | 1 + src/plugins/home/server/tutorials/redis_logs/index.ts | 1 + src/plugins/home/server/tutorials/redis_metrics/index.ts | 1 + .../home/server/tutorials/redisenterprise_metrics/index.ts | 1 + src/plugins/home/server/tutorials/santa_logs/index.ts | 1 + src/plugins/home/server/tutorials/sonicwall_logs/index.ts | 1 + src/plugins/home/server/tutorials/sophos_logs/index.ts | 1 + src/plugins/home/server/tutorials/squid_logs/index.ts | 1 + src/plugins/home/server/tutorials/stan_metrics/index.ts | 1 + src/plugins/home/server/tutorials/statsd_metrics/index.ts | 1 + src/plugins/home/server/tutorials/suricata_logs/index.ts | 1 + src/plugins/home/server/tutorials/system_logs/index.ts | 1 + src/plugins/home/server/tutorials/system_metrics/index.ts | 1 + src/plugins/home/server/tutorials/tomcat_logs/index.ts | 1 + src/plugins/home/server/tutorials/traefik_logs/index.ts | 1 + src/plugins/home/server/tutorials/traefik_metrics/index.ts | 1 + src/plugins/home/server/tutorials/uptime_monitors/index.ts | 1 + src/plugins/home/server/tutorials/uwsgi_metrics/index.ts | 1 + src/plugins/home/server/tutorials/vsphere_metrics/index.ts | 1 + src/plugins/home/server/tutorials/windows_event_logs/index.ts | 1 + src/plugins/home/server/tutorials/windows_metrics/index.ts | 1 + src/plugins/home/server/tutorials/zeek_logs/index.ts | 1 + src/plugins/home/server/tutorials/zookeeper_metrics/index.ts | 1 + src/plugins/home/server/tutorials/zscaler_logs/index.ts | 1 + 102 files changed, 102 insertions(+) diff --git a/src/plugins/home/server/tutorials/aerospike_metrics/index.ts b/src/plugins/home/server/tutorials/aerospike_metrics/index.ts index 27246b78b1d6b..75dd45272db69 100644 --- a/src/plugins/home/server/tutorials/aerospike_metrics/index.ts +++ b/src/plugins/home/server/tutorials/aerospike_metrics/index.ts @@ -56,5 +56,6 @@ export function aerospikeMetricsSpecProvider(context: TutorialContext): Tutorial onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['web'], }; } diff --git a/src/plugins/home/server/tutorials/apache_logs/index.ts b/src/plugins/home/server/tutorials/apache_logs/index.ts index 06d2035ee4713..8606a40fe0a23 100644 --- a/src/plugins/home/server/tutorials/apache_logs/index.ts +++ b/src/plugins/home/server/tutorials/apache_logs/index.ts @@ -59,5 +59,6 @@ export function apacheLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['web'], }; } diff --git a/src/plugins/home/server/tutorials/apache_metrics/index.ts b/src/plugins/home/server/tutorials/apache_metrics/index.ts index e94f64ce1f058..f013f3da737f0 100644 --- a/src/plugins/home/server/tutorials/apache_metrics/index.ts +++ b/src/plugins/home/server/tutorials/apache_metrics/index.ts @@ -58,5 +58,6 @@ export function apacheMetricsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['web'], }; } diff --git a/src/plugins/home/server/tutorials/auditbeat/index.ts b/src/plugins/home/server/tutorials/auditbeat/index.ts index dd51f0e512a5b..8bd6450b1daa4 100644 --- a/src/plugins/home/server/tutorials/auditbeat/index.ts +++ b/src/plugins/home/server/tutorials/auditbeat/index.ts @@ -58,5 +58,6 @@ processes, users, logins, sockets information, file accesses, and more. \ onPrem: onPremInstructions(platforms, context), elasticCloud: cloudInstructions(platforms), onPremElasticCloud: onPremCloudInstructions(platforms), + integrationBrowserCategories: ['web'], }; } diff --git a/src/plugins/home/server/tutorials/auditd_logs/index.ts b/src/plugins/home/server/tutorials/auditd_logs/index.ts index 5e1cea86ccfa7..a0d6f5f683e2c 100644 --- a/src/plugins/home/server/tutorials/auditd_logs/index.ts +++ b/src/plugins/home/server/tutorials/auditd_logs/index.ts @@ -59,5 +59,6 @@ export function auditdLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['os_system'], }; } diff --git a/src/plugins/home/server/tutorials/azure_logs/index.ts b/src/plugins/home/server/tutorials/azure_logs/index.ts index 8d8b1f2813c6a..2bf1527a79c40 100644 --- a/src/plugins/home/server/tutorials/azure_logs/index.ts +++ b/src/plugins/home/server/tutorials/azure_logs/index.ts @@ -60,5 +60,6 @@ export function azureLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['azure', 'cloud', 'network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/azure_metrics/index.ts b/src/plugins/home/server/tutorials/azure_metrics/index.ts index 9dff3956b745f..4a6112510b333 100644 --- a/src/plugins/home/server/tutorials/azure_metrics/index.ts +++ b/src/plugins/home/server/tutorials/azure_metrics/index.ts @@ -59,5 +59,6 @@ export function azureMetricsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['azure', 'cloud', 'network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/barracuda_logs/index.ts b/src/plugins/home/server/tutorials/barracuda_logs/index.ts index c85e92d884f93..35ce10e00892e 100644 --- a/src/plugins/home/server/tutorials/barracuda_logs/index.ts +++ b/src/plugins/home/server/tutorials/barracuda_logs/index.ts @@ -56,5 +56,6 @@ export function barracudaLogsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/bluecoat_logs/index.ts b/src/plugins/home/server/tutorials/bluecoat_logs/index.ts index b9a0eb6459b99..85c7dff85d3e6 100644 --- a/src/plugins/home/server/tutorials/bluecoat_logs/index.ts +++ b/src/plugins/home/server/tutorials/bluecoat_logs/index.ts @@ -56,5 +56,6 @@ export function bluecoatLogsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/cef_logs/index.ts b/src/plugins/home/server/tutorials/cef_logs/index.ts index 4204614fadc58..cfd267f661d2a 100644 --- a/src/plugins/home/server/tutorials/cef_logs/index.ts +++ b/src/plugins/home/server/tutorials/cef_logs/index.ts @@ -63,5 +63,6 @@ export function cefLogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/ceph_metrics/index.ts b/src/plugins/home/server/tutorials/ceph_metrics/index.ts index 41e47655656ac..821067d87c905 100644 --- a/src/plugins/home/server/tutorials/ceph_metrics/index.ts +++ b/src/plugins/home/server/tutorials/ceph_metrics/index.ts @@ -56,5 +56,6 @@ export function cephMetricsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/checkpoint_logs/index.ts b/src/plugins/home/server/tutorials/checkpoint_logs/index.ts index 7171b09b02492..9c0d5591ae35b 100644 --- a/src/plugins/home/server/tutorials/checkpoint_logs/index.ts +++ b/src/plugins/home/server/tutorials/checkpoint_logs/index.ts @@ -56,5 +56,6 @@ export function checkpointLogsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/cisco_logs/index.ts b/src/plugins/home/server/tutorials/cisco_logs/index.ts index f2b21013037bb..50b79f448b316 100644 --- a/src/plugins/home/server/tutorials/cisco_logs/index.ts +++ b/src/plugins/home/server/tutorials/cisco_logs/index.ts @@ -59,5 +59,6 @@ export function ciscoLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts b/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts index a6ed3ad22ff7f..e43d05a0a098f 100644 --- a/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts @@ -61,5 +61,6 @@ export function cockroachdbMetricsSpecProvider(context: TutorialContext): Tutori onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['security', 'network', 'web'], }; } diff --git a/src/plugins/home/server/tutorials/consul_metrics/index.ts b/src/plugins/home/server/tutorials/consul_metrics/index.ts index fd82227f01fcb..915920db5882c 100644 --- a/src/plugins/home/server/tutorials/consul_metrics/index.ts +++ b/src/plugins/home/server/tutorials/consul_metrics/index.ts @@ -58,5 +58,6 @@ export function consulMetricsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['security', 'network', 'web'], }; } diff --git a/src/plugins/home/server/tutorials/coredns_logs/index.ts b/src/plugins/home/server/tutorials/coredns_logs/index.ts index 48b9154b81f4b..298464651f7fc 100644 --- a/src/plugins/home/server/tutorials/coredns_logs/index.ts +++ b/src/plugins/home/server/tutorials/coredns_logs/index.ts @@ -59,5 +59,6 @@ export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security', 'network', 'web'], }; } diff --git a/src/plugins/home/server/tutorials/coredns_metrics/index.ts b/src/plugins/home/server/tutorials/coredns_metrics/index.ts index 50c0e5d46f86a..34912efb31a81 100644 --- a/src/plugins/home/server/tutorials/coredns_metrics/index.ts +++ b/src/plugins/home/server/tutorials/coredns_metrics/index.ts @@ -56,5 +56,6 @@ export function corednsMetricsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['security', 'network', 'web'], }; } diff --git a/src/plugins/home/server/tutorials/couchbase_metrics/index.ts b/src/plugins/home/server/tutorials/couchbase_metrics/index.ts index de8c306480774..1860991fd17b2 100644 --- a/src/plugins/home/server/tutorials/couchbase_metrics/index.ts +++ b/src/plugins/home/server/tutorials/couchbase_metrics/index.ts @@ -56,5 +56,6 @@ export function couchbaseMetricsSpecProvider(context: TutorialContext): Tutorial onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['security', 'network', 'web'], }; } diff --git a/src/plugins/home/server/tutorials/couchdb_metrics/index.ts b/src/plugins/home/server/tutorials/couchdb_metrics/index.ts index d4f4f2c5bc04c..a6c57f56cf2e1 100644 --- a/src/plugins/home/server/tutorials/couchdb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/couchdb_metrics/index.ts @@ -61,5 +61,6 @@ export function couchdbMetricsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['security', 'network', 'web'], }; } diff --git a/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts b/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts index a61ad14f9793a..baaaef50a641f 100644 --- a/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts +++ b/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts @@ -59,5 +59,6 @@ export function crowdstrikeLogsSpecProvider(context: TutorialContext): TutorialS onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/cylance_logs/index.ts b/src/plugins/home/server/tutorials/cylance_logs/index.ts index 489e2c49d765e..9766f417b8870 100644 --- a/src/plugins/home/server/tutorials/cylance_logs/index.ts +++ b/src/plugins/home/server/tutorials/cylance_logs/index.ts @@ -56,5 +56,6 @@ export function cylanceLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/docker_metrics/index.ts b/src/plugins/home/server/tutorials/docker_metrics/index.ts index 9b4dd919b338b..6a8687ef5d66e 100644 --- a/src/plugins/home/server/tutorials/docker_metrics/index.ts +++ b/src/plugins/home/server/tutorials/docker_metrics/index.ts @@ -58,5 +58,6 @@ export function dockerMetricsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['containers', 'os_system'], }; } diff --git a/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts b/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts index 6283147bc3bac..86be26dd12ca7 100644 --- a/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts +++ b/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts @@ -56,5 +56,6 @@ export function dropwizardMetricsSpecProvider(context: TutorialContext): Tutoria onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['elastic_stack', 'datastore'], }; } diff --git a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts index 94e904eb33247..1886a912fdcd2 100644 --- a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts +++ b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts @@ -58,5 +58,6 @@ export function elasticsearchLogsSpecProvider(context: TutorialContext): Tutoria onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['containers', 'os_system'], }; } diff --git a/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts b/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts index 48fa3491e43b6..2adc2fd90fa70 100644 --- a/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts +++ b/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts @@ -56,5 +56,6 @@ export function elasticsearchMetricsSpecProvider(context: TutorialContext): Tuto onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['elastic_stack', 'datastore'], }; } diff --git a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts index 74add28c1ae74..fda69a2467b25 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts @@ -62,5 +62,6 @@ export function envoyproxyLogsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['elastic_stack', 'datastore'], }; } diff --git a/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts b/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts index 18d3dfae392e7..263d1a2036fd0 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts @@ -49,5 +49,6 @@ export function envoyproxyMetricsSpecProvider(context: TutorialContext): Tutoria onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['elastic_stack', 'datastore'], }; } diff --git a/src/plugins/home/server/tutorials/etcd_metrics/index.ts b/src/plugins/home/server/tutorials/etcd_metrics/index.ts index 288124c1efbe9..cda16ecf68e34 100644 --- a/src/plugins/home/server/tutorials/etcd_metrics/index.ts +++ b/src/plugins/home/server/tutorials/etcd_metrics/index.ts @@ -56,5 +56,6 @@ export function etcdMetricsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['elastic_stack', 'datastore'], }; } diff --git a/src/plugins/home/server/tutorials/f5_logs/index.ts b/src/plugins/home/server/tutorials/f5_logs/index.ts index 976c207305376..ebcdd4ece7f45 100644 --- a/src/plugins/home/server/tutorials/f5_logs/index.ts +++ b/src/plugins/home/server/tutorials/f5_logs/index.ts @@ -57,5 +57,6 @@ export function f5LogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/fortinet_logs/index.ts b/src/plugins/home/server/tutorials/fortinet_logs/index.ts index 250e873d037b5..3e7923b680c6e 100644 --- a/src/plugins/home/server/tutorials/fortinet_logs/index.ts +++ b/src/plugins/home/server/tutorials/fortinet_logs/index.ts @@ -56,5 +56,6 @@ export function fortinetLogsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/gcp_logs/index.ts b/src/plugins/home/server/tutorials/gcp_logs/index.ts index 6aa6adb183418..feef7d673c5d9 100644 --- a/src/plugins/home/server/tutorials/gcp_logs/index.ts +++ b/src/plugins/home/server/tutorials/gcp_logs/index.ts @@ -61,5 +61,6 @@ export function gcpLogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['google_cloud', 'cloud', 'network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/gcp_metrics/index.ts b/src/plugins/home/server/tutorials/gcp_metrics/index.ts index 8416ab105de96..5f198ed5f3cf2 100644 --- a/src/plugins/home/server/tutorials/gcp_metrics/index.ts +++ b/src/plugins/home/server/tutorials/gcp_metrics/index.ts @@ -60,5 +60,6 @@ export function gcpMetricsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['google_cloud', 'cloud', 'network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/golang_metrics/index.ts b/src/plugins/home/server/tutorials/golang_metrics/index.ts index 1d298fd294a3e..85937e0dda0e0 100644 --- a/src/plugins/home/server/tutorials/golang_metrics/index.ts +++ b/src/plugins/home/server/tutorials/golang_metrics/index.ts @@ -59,5 +59,6 @@ export function golangMetricsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['google_cloud', 'cloud', 'network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/gsuite_logs/index.ts b/src/plugins/home/server/tutorials/gsuite_logs/index.ts index 2973af4b969c7..4d23c6b1cfdce 100644 --- a/src/plugins/home/server/tutorials/gsuite_logs/index.ts +++ b/src/plugins/home/server/tutorials/gsuite_logs/index.ts @@ -56,5 +56,6 @@ export function gsuiteLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/haproxy_logs/index.ts b/src/plugins/home/server/tutorials/haproxy_logs/index.ts index 9aa853af7819e..0b0fd35f07058 100644 --- a/src/plugins/home/server/tutorials/haproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/haproxy_logs/index.ts @@ -59,5 +59,6 @@ export function haproxyLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'web'], }; } diff --git a/src/plugins/home/server/tutorials/haproxy_metrics/index.ts b/src/plugins/home/server/tutorials/haproxy_metrics/index.ts index a6953808871fa..e37f0ffc4b916 100644 --- a/src/plugins/home/server/tutorials/haproxy_metrics/index.ts +++ b/src/plugins/home/server/tutorials/haproxy_metrics/index.ts @@ -56,5 +56,6 @@ export function haproxyMetricsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['network', 'web'], }; } diff --git a/src/plugins/home/server/tutorials/ibmmq_logs/index.ts b/src/plugins/home/server/tutorials/ibmmq_logs/index.ts index a777443c5f9b8..646747d1a49f8 100644 --- a/src/plugins/home/server/tutorials/ibmmq_logs/index.ts +++ b/src/plugins/home/server/tutorials/ibmmq_logs/index.ts @@ -58,5 +58,6 @@ export function ibmmqLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts b/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts index 2501aa81f0e30..3862bd9ca85eb 100644 --- a/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts +++ b/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts @@ -57,5 +57,6 @@ export function ibmmqMetricsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/icinga_logs/index.ts b/src/plugins/home/server/tutorials/icinga_logs/index.ts index b55023a77332f..0dae93b70343b 100644 --- a/src/plugins/home/server/tutorials/icinga_logs/index.ts +++ b/src/plugins/home/server/tutorials/icinga_logs/index.ts @@ -59,5 +59,6 @@ export function icingaLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/iis_logs/index.ts b/src/plugins/home/server/tutorials/iis_logs/index.ts index f87e87a6aa427..5393edf6ab148 100644 --- a/src/plugins/home/server/tutorials/iis_logs/index.ts +++ b/src/plugins/home/server/tutorials/iis_logs/index.ts @@ -59,5 +59,6 @@ export function iisLogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['web'], }; } diff --git a/src/plugins/home/server/tutorials/iis_metrics/index.ts b/src/plugins/home/server/tutorials/iis_metrics/index.ts index 56408beb2071f..dbfa474dc9c89 100644 --- a/src/plugins/home/server/tutorials/iis_metrics/index.ts +++ b/src/plugins/home/server/tutorials/iis_metrics/index.ts @@ -59,5 +59,6 @@ export function iisMetricsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['web'], }; } diff --git a/src/plugins/home/server/tutorials/imperva_logs/index.ts b/src/plugins/home/server/tutorials/imperva_logs/index.ts index 09ea5cf21ec21..71c3af3809e2e 100644 --- a/src/plugins/home/server/tutorials/imperva_logs/index.ts +++ b/src/plugins/home/server/tutorials/imperva_logs/index.ts @@ -56,5 +56,6 @@ export function impervaLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/infoblox_logs/index.ts b/src/plugins/home/server/tutorials/infoblox_logs/index.ts index 62769946067e5..5329444dfa85f 100644 --- a/src/plugins/home/server/tutorials/infoblox_logs/index.ts +++ b/src/plugins/home/server/tutorials/infoblox_logs/index.ts @@ -56,5 +56,6 @@ export function infobloxLogsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network'], }; } diff --git a/src/plugins/home/server/tutorials/iptables_logs/index.ts b/src/plugins/home/server/tutorials/iptables_logs/index.ts index b25604db39c0d..85faf169f8714 100644 --- a/src/plugins/home/server/tutorials/iptables_logs/index.ts +++ b/src/plugins/home/server/tutorials/iptables_logs/index.ts @@ -62,5 +62,6 @@ export function iptablesLogsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/juniper_logs/index.ts b/src/plugins/home/server/tutorials/juniper_logs/index.ts index f13f62d0d92e3..f9174d8a089e0 100644 --- a/src/plugins/home/server/tutorials/juniper_logs/index.ts +++ b/src/plugins/home/server/tutorials/juniper_logs/index.ts @@ -56,5 +56,6 @@ export function juniperLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/kafka_logs/index.ts b/src/plugins/home/server/tutorials/kafka_logs/index.ts index 13a4317761a86..5b877cadcbec6 100644 --- a/src/plugins/home/server/tutorials/kafka_logs/index.ts +++ b/src/plugins/home/server/tutorials/kafka_logs/index.ts @@ -59,5 +59,6 @@ export function kafkaLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/kafka_metrics/index.ts b/src/plugins/home/server/tutorials/kafka_metrics/index.ts index b6840cb69ec57..92f6744b91cbe 100644 --- a/src/plugins/home/server/tutorials/kafka_metrics/index.ts +++ b/src/plugins/home/server/tutorials/kafka_metrics/index.ts @@ -56,5 +56,6 @@ export function kafkaMetricsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/kibana_logs/index.ts b/src/plugins/home/server/tutorials/kibana_logs/index.ts index 27207de013dbd..988af821ef9e3 100644 --- a/src/plugins/home/server/tutorials/kibana_logs/index.ts +++ b/src/plugins/home/server/tutorials/kibana_logs/index.ts @@ -55,5 +55,6 @@ export function kibanaLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/kibana_metrics/index.ts b/src/plugins/home/server/tutorials/kibana_metrics/index.ts index 0e5e0c92e77e9..dfe4efe4f7337 100644 --- a/src/plugins/home/server/tutorials/kibana_metrics/index.ts +++ b/src/plugins/home/server/tutorials/kibana_metrics/index.ts @@ -56,5 +56,6 @@ export function kibanaMetricsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts b/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts index 48bc3c4b69e39..4a694560f5c28 100644 --- a/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts +++ b/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts @@ -61,5 +61,6 @@ export function kubernetesMetricsSpecProvider(context: TutorialContext): Tutoria onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['containers', 'kubernetes'], }; } diff --git a/src/plugins/home/server/tutorials/logstash_logs/index.ts b/src/plugins/home/server/tutorials/logstash_logs/index.ts index e41796b4b57bf..55491d45df28c 100644 --- a/src/plugins/home/server/tutorials/logstash_logs/index.ts +++ b/src/plugins/home/server/tutorials/logstash_logs/index.ts @@ -58,5 +58,6 @@ export function logstashLogsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['custom'], }; } diff --git a/src/plugins/home/server/tutorials/logstash_metrics/index.ts b/src/plugins/home/server/tutorials/logstash_metrics/index.ts index 0aa85745b0fa3..e7d3fae011bd2 100644 --- a/src/plugins/home/server/tutorials/logstash_metrics/index.ts +++ b/src/plugins/home/server/tutorials/logstash_metrics/index.ts @@ -57,5 +57,6 @@ export function logstashMetricsSpecProvider(context: TutorialContext): TutorialS onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['custom'], }; } diff --git a/src/plugins/home/server/tutorials/memcached_metrics/index.ts b/src/plugins/home/server/tutorials/memcached_metrics/index.ts index 5032130eed0b6..15df179b44a9e 100644 --- a/src/plugins/home/server/tutorials/memcached_metrics/index.ts +++ b/src/plugins/home/server/tutorials/memcached_metrics/index.ts @@ -56,5 +56,6 @@ export function memcachedMetricsSpecProvider(context: TutorialContext): Tutorial onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['custom'], }; } diff --git a/src/plugins/home/server/tutorials/microsoft_logs/index.ts b/src/plugins/home/server/tutorials/microsoft_logs/index.ts index ee860845c04b6..52401df1f9eb7 100644 --- a/src/plugins/home/server/tutorials/microsoft_logs/index.ts +++ b/src/plugins/home/server/tutorials/microsoft_logs/index.ts @@ -59,5 +59,6 @@ export function microsoftLogsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security', 'azure'], }; } diff --git a/src/plugins/home/server/tutorials/misp_logs/index.ts b/src/plugins/home/server/tutorials/misp_logs/index.ts index 3c341f5ad1e93..b7611b543bab1 100644 --- a/src/plugins/home/server/tutorials/misp_logs/index.ts +++ b/src/plugins/home/server/tutorials/misp_logs/index.ts @@ -59,5 +59,6 @@ export function mispLogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security', 'azure'], }; } diff --git a/src/plugins/home/server/tutorials/mongodb_logs/index.ts b/src/plugins/home/server/tutorials/mongodb_logs/index.ts index 7b5ee10c1d5e0..3c189c04da43b 100644 --- a/src/plugins/home/server/tutorials/mongodb_logs/index.ts +++ b/src/plugins/home/server/tutorials/mongodb_logs/index.ts @@ -59,5 +59,6 @@ export function mongodbLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/mongodb_metrics/index.ts b/src/plugins/home/server/tutorials/mongodb_metrics/index.ts index c7946309cb2d8..121310fba6f3a 100644 --- a/src/plugins/home/server/tutorials/mongodb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mongodb_metrics/index.ts @@ -61,5 +61,6 @@ export function mongodbMetricsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/mssql_logs/index.ts b/src/plugins/home/server/tutorials/mssql_logs/index.ts index 1b605d2c17dbb..567080910b7fe 100644 --- a/src/plugins/home/server/tutorials/mssql_logs/index.ts +++ b/src/plugins/home/server/tutorials/mssql_logs/index.ts @@ -56,5 +56,6 @@ export function mssqlLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/mssql_metrics/index.ts b/src/plugins/home/server/tutorials/mssql_metrics/index.ts index 767612e3a1c2e..998cefe2de004 100644 --- a/src/plugins/home/server/tutorials/mssql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mssql_metrics/index.ts @@ -59,5 +59,6 @@ export function mssqlMetricsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/munin_metrics/index.ts b/src/plugins/home/server/tutorials/munin_metrics/index.ts index 063770e43e6d1..1abd321e4c738 100644 --- a/src/plugins/home/server/tutorials/munin_metrics/index.ts +++ b/src/plugins/home/server/tutorials/munin_metrics/index.ts @@ -56,5 +56,6 @@ export function muninMetricsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/mysql_logs/index.ts b/src/plugins/home/server/tutorials/mysql_logs/index.ts index 79eaeb3826162..a788e736d2964 100644 --- a/src/plugins/home/server/tutorials/mysql_logs/index.ts +++ b/src/plugins/home/server/tutorials/mysql_logs/index.ts @@ -59,5 +59,6 @@ export function mysqlLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/mysql_metrics/index.ts b/src/plugins/home/server/tutorials/mysql_metrics/index.ts index 66da2d8e0a5ff..078a96f8110df 100644 --- a/src/plugins/home/server/tutorials/mysql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mysql_metrics/index.ts @@ -58,5 +58,6 @@ export function mysqlMetricsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/nats_logs/index.ts b/src/plugins/home/server/tutorials/nats_logs/index.ts index c5c7028e19163..a1dc24080bc0d 100644 --- a/src/plugins/home/server/tutorials/nats_logs/index.ts +++ b/src/plugins/home/server/tutorials/nats_logs/index.ts @@ -60,5 +60,6 @@ export function natsLogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/nats_metrics/index.ts b/src/plugins/home/server/tutorials/nats_metrics/index.ts index bf25ab9f8d33e..11494e5dc57d0 100644 --- a/src/plugins/home/server/tutorials/nats_metrics/index.ts +++ b/src/plugins/home/server/tutorials/nats_metrics/index.ts @@ -58,5 +58,6 @@ export function natsMetricsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/netflow_logs/index.ts b/src/plugins/home/server/tutorials/netflow_logs/index.ts index 1a85c3feb1173..e8404e93ae355 100644 --- a/src/plugins/home/server/tutorials/netflow_logs/index.ts +++ b/src/plugins/home/server/tutorials/netflow_logs/index.ts @@ -58,5 +58,6 @@ export function netflowLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/netscout_logs/index.ts b/src/plugins/home/server/tutorials/netscout_logs/index.ts index 57429e9acddfe..395fbb8b49d39 100644 --- a/src/plugins/home/server/tutorials/netscout_logs/index.ts +++ b/src/plugins/home/server/tutorials/netscout_logs/index.ts @@ -56,5 +56,6 @@ export function netscoutLogsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/nginx_logs/index.ts b/src/plugins/home/server/tutorials/nginx_logs/index.ts index a1419fbb42d5a..90ec6737c2461 100644 --- a/src/plugins/home/server/tutorials/nginx_logs/index.ts +++ b/src/plugins/home/server/tutorials/nginx_logs/index.ts @@ -59,5 +59,6 @@ export function nginxLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['web', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/nginx_metrics/index.ts b/src/plugins/home/server/tutorials/nginx_metrics/index.ts index 32b20844ef813..12f67a26dcf29 100644 --- a/src/plugins/home/server/tutorials/nginx_metrics/index.ts +++ b/src/plugins/home/server/tutorials/nginx_metrics/index.ts @@ -63,5 +63,6 @@ which must be enabled in your Nginx installation. \ onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['web', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/o365_logs/index.ts b/src/plugins/home/server/tutorials/o365_logs/index.ts index 50cd13298a879..e3663e2c3cd78 100644 --- a/src/plugins/home/server/tutorials/o365_logs/index.ts +++ b/src/plugins/home/server/tutorials/o365_logs/index.ts @@ -62,5 +62,6 @@ export function o365LogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/okta_logs/index.ts b/src/plugins/home/server/tutorials/okta_logs/index.ts index ac173c79db605..62cde4b5128c3 100644 --- a/src/plugins/home/server/tutorials/okta_logs/index.ts +++ b/src/plugins/home/server/tutorials/okta_logs/index.ts @@ -60,5 +60,6 @@ export function oktaLogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts b/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts index 6885c1ccea86d..acbddf5169881 100644 --- a/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts +++ b/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts @@ -49,5 +49,6 @@ export function openmetricsMetricsSpecProvider(context: TutorialContext): Tutori onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/osquery_logs/index.ts b/src/plugins/home/server/tutorials/osquery_logs/index.ts index 40ed13d767319..6bacbed57792c 100644 --- a/src/plugins/home/server/tutorials/osquery_logs/index.ts +++ b/src/plugins/home/server/tutorials/osquery_logs/index.ts @@ -62,5 +62,6 @@ export function osqueryLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security', 'os_system'], }; } diff --git a/src/plugins/home/server/tutorials/panw_logs/index.ts b/src/plugins/home/server/tutorials/panw_logs/index.ts index a46b2deb29826..3ca839556d756 100644 --- a/src/plugins/home/server/tutorials/panw_logs/index.ts +++ b/src/plugins/home/server/tutorials/panw_logs/index.ts @@ -62,5 +62,6 @@ export function panwLogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts b/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts index 229a167bb137e..ed67960ab5a1c 100644 --- a/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts +++ b/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts @@ -56,5 +56,6 @@ export function phpfpmMetricsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/postgresql_logs/index.ts b/src/plugins/home/server/tutorials/postgresql_logs/index.ts index da7b8927a610d..c5f5d879ac35d 100644 --- a/src/plugins/home/server/tutorials/postgresql_logs/index.ts +++ b/src/plugins/home/server/tutorials/postgresql_logs/index.ts @@ -62,5 +62,6 @@ export function postgresqlLogsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/postgresql_metrics/index.ts b/src/plugins/home/server/tutorials/postgresql_metrics/index.ts index eb5ed17021d1a..ca20efb44bca7 100644 --- a/src/plugins/home/server/tutorials/postgresql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/postgresql_metrics/index.ts @@ -58,5 +58,6 @@ export function postgresqlMetricsSpecProvider(context: TutorialContext): Tutoria onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['datastore'], }; } diff --git a/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts b/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts index 92e6623da6f53..0fbdb48236832 100644 --- a/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts +++ b/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts @@ -56,5 +56,6 @@ export function rabbitmqLogsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts b/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts index 56b7a8c8c2109..b58f936f205b2 100644 --- a/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts +++ b/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts @@ -62,5 +62,6 @@ export function rabbitmqMetricsSpecProvider(context: TutorialContext): TutorialS onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/radware_logs/index.ts b/src/plugins/home/server/tutorials/radware_logs/index.ts index 3d91514c2c13e..28392cf9c4362 100644 --- a/src/plugins/home/server/tutorials/radware_logs/index.ts +++ b/src/plugins/home/server/tutorials/radware_logs/index.ts @@ -56,5 +56,6 @@ export function radwareLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/redis_logs/index.ts b/src/plugins/home/server/tutorials/redis_logs/index.ts index 116099e809832..0f3a5aa812f49 100644 --- a/src/plugins/home/server/tutorials/redis_logs/index.ts +++ b/src/plugins/home/server/tutorials/redis_logs/index.ts @@ -65,5 +65,6 @@ Note that the `slowlog` fileset is experimental. \ onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['datastore', 'message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/redis_metrics/index.ts b/src/plugins/home/server/tutorials/redis_metrics/index.ts index bce77a2b18cc3..1b4ee7290a6d0 100644 --- a/src/plugins/home/server/tutorials/redis_metrics/index.ts +++ b/src/plugins/home/server/tutorials/redis_metrics/index.ts @@ -58,5 +58,6 @@ export function redisMetricsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['datastore', 'message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts b/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts index 257440ec69987..be8de9c3eab4d 100644 --- a/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts +++ b/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts @@ -57,5 +57,6 @@ export function redisenterpriseMetricsSpecProvider(context: TutorialContext): Tu onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['datastore', 'message_queue'], }; } diff --git a/src/plugins/home/server/tutorials/santa_logs/index.ts b/src/plugins/home/server/tutorials/santa_logs/index.ts index fb5ba7ede4171..10d1506438b62 100644 --- a/src/plugins/home/server/tutorials/santa_logs/index.ts +++ b/src/plugins/home/server/tutorials/santa_logs/index.ts @@ -60,5 +60,6 @@ export function santaLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security', 'os_system'], }; } diff --git a/src/plugins/home/server/tutorials/sonicwall_logs/index.ts b/src/plugins/home/server/tutorials/sonicwall_logs/index.ts index fa33f81728db7..1fa711327a07d 100644 --- a/src/plugins/home/server/tutorials/sonicwall_logs/index.ts +++ b/src/plugins/home/server/tutorials/sonicwall_logs/index.ts @@ -56,5 +56,6 @@ export function sonicwallLogsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/sophos_logs/index.ts b/src/plugins/home/server/tutorials/sophos_logs/index.ts index 19b6b3033c9f1..35b27973a55ec 100644 --- a/src/plugins/home/server/tutorials/sophos_logs/index.ts +++ b/src/plugins/home/server/tutorials/sophos_logs/index.ts @@ -56,5 +56,6 @@ export function sophosLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/squid_logs/index.ts b/src/plugins/home/server/tutorials/squid_logs/index.ts index ef6ea4aef3e17..d8d0bb6c0829b 100644 --- a/src/plugins/home/server/tutorials/squid_logs/index.ts +++ b/src/plugins/home/server/tutorials/squid_logs/index.ts @@ -56,5 +56,6 @@ export function squidLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['security'], }; } diff --git a/src/plugins/home/server/tutorials/stan_metrics/index.ts b/src/plugins/home/server/tutorials/stan_metrics/index.ts index 10b7fc08bbf19..ceb6084b539e6 100644 --- a/src/plugins/home/server/tutorials/stan_metrics/index.ts +++ b/src/plugins/home/server/tutorials/stan_metrics/index.ts @@ -58,5 +58,6 @@ export function stanMetricsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['message_queue', 'kubernetes'], }; } diff --git a/src/plugins/home/server/tutorials/statsd_metrics/index.ts b/src/plugins/home/server/tutorials/statsd_metrics/index.ts index 70a35d3f6f648..472c1406db386 100644 --- a/src/plugins/home/server/tutorials/statsd_metrics/index.ts +++ b/src/plugins/home/server/tutorials/statsd_metrics/index.ts @@ -47,5 +47,6 @@ export function statsdMetricsSpecProvider(context: TutorialContext): TutorialSch onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['message_queue', 'kubernetes'], }; } diff --git a/src/plugins/home/server/tutorials/suricata_logs/index.ts b/src/plugins/home/server/tutorials/suricata_logs/index.ts index c06c7c05c5583..3bb2b93b6301a 100644 --- a/src/plugins/home/server/tutorials/suricata_logs/index.ts +++ b/src/plugins/home/server/tutorials/suricata_logs/index.ts @@ -60,5 +60,6 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/system_logs/index.ts b/src/plugins/home/server/tutorials/system_logs/index.ts index 087f8e04e250d..6f403a6d0a71a 100644 --- a/src/plugins/home/server/tutorials/system_logs/index.ts +++ b/src/plugins/home/server/tutorials/system_logs/index.ts @@ -58,5 +58,6 @@ export function systemLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['os_system', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/system_metrics/index.ts b/src/plugins/home/server/tutorials/system_metrics/index.ts index 91e0b74a05d68..08979a3d3b003 100644 --- a/src/plugins/home/server/tutorials/system_metrics/index.ts +++ b/src/plugins/home/server/tutorials/system_metrics/index.ts @@ -59,5 +59,6 @@ It collects system wide statistics and statistics per process and filesystem. \ onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['os_system', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/tomcat_logs/index.ts b/src/plugins/home/server/tutorials/tomcat_logs/index.ts index 4632f5d64eec8..5ce4096ad4628 100644 --- a/src/plugins/home/server/tutorials/tomcat_logs/index.ts +++ b/src/plugins/home/server/tutorials/tomcat_logs/index.ts @@ -56,5 +56,6 @@ export function tomcatLogsSpecProvider(context: TutorialContext): TutorialSchema onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['web', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/traefik_logs/index.ts b/src/plugins/home/server/tutorials/traefik_logs/index.ts index 139a158d77b81..6bbc905bbd6aa 100644 --- a/src/plugins/home/server/tutorials/traefik_logs/index.ts +++ b/src/plugins/home/server/tutorials/traefik_logs/index.ts @@ -58,5 +58,6 @@ export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['web', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/traefik_metrics/index.ts b/src/plugins/home/server/tutorials/traefik_metrics/index.ts index a036de3546ba8..35d54317c8ede 100644 --- a/src/plugins/home/server/tutorials/traefik_metrics/index.ts +++ b/src/plugins/home/server/tutorials/traefik_metrics/index.ts @@ -46,5 +46,6 @@ export function traefikMetricsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['web', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/uptime_monitors/index.ts b/src/plugins/home/server/tutorials/uptime_monitors/index.ts index f04e0e1e797ef..6e949d5410115 100644 --- a/src/plugins/home/server/tutorials/uptime_monitors/index.ts +++ b/src/plugins/home/server/tutorials/uptime_monitors/index.ts @@ -57,5 +57,6 @@ export function uptimeMonitorsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions([], context), elasticCloud: cloudInstructions(), onPremElasticCloud: onPremCloudInstructions(), + integrationBrowserCategories: ['web', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts index d41bdad6a90d9..d9cfcc9f7fb75 100644 --- a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts +++ b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts @@ -59,5 +59,6 @@ export function uwsgiMetricsSpecProvider(context: TutorialContext): TutorialSche onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['web', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts index b4786d060ecd1..bcbcec59c36e4 100644 --- a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts +++ b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts @@ -56,5 +56,6 @@ export function vSphereMetricsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['web', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/windows_event_logs/index.ts b/src/plugins/home/server/tutorials/windows_event_logs/index.ts index 5b073e7a0fcde..0df7fa906e085 100644 --- a/src/plugins/home/server/tutorials/windows_event_logs/index.ts +++ b/src/plugins/home/server/tutorials/windows_event_logs/index.ts @@ -56,5 +56,6 @@ export function windowsEventLogsSpecProvider(context: TutorialContext): Tutorial onPrem: onPremInstructions(context), elasticCloud: cloudInstructions(), onPremElasticCloud: onPremCloudInstructions(), + integrationBrowserCategories: ['os_system', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/windows_metrics/index.ts b/src/plugins/home/server/tutorials/windows_metrics/index.ts index e937a962f1bd5..6c663fbb13d4d 100644 --- a/src/plugins/home/server/tutorials/windows_metrics/index.ts +++ b/src/plugins/home/server/tutorials/windows_metrics/index.ts @@ -56,5 +56,6 @@ export function windowsMetricsSpecProvider(context: TutorialContext): TutorialSc onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['os_system', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/zeek_logs/index.ts b/src/plugins/home/server/tutorials/zeek_logs/index.ts index 9c5baa8368a7c..5434dcc8527ff 100644 --- a/src/plugins/home/server/tutorials/zeek_logs/index.ts +++ b/src/plugins/home/server/tutorials/zeek_logs/index.ts @@ -60,5 +60,6 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'monitoring', 'security'], }; } diff --git a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts index 29038269b0825..85ca03acacfd4 100644 --- a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts +++ b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts @@ -57,5 +57,6 @@ export function zookeeperMetricsSpecProvider(context: TutorialContext): Tutorial onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName), onPremElasticCloud: onPremCloudInstructions(moduleName), + integrationBrowserCategories: ['datastore', 'config_management'], }; } diff --git a/src/plugins/home/server/tutorials/zscaler_logs/index.ts b/src/plugins/home/server/tutorials/zscaler_logs/index.ts index fcfcccf2c50bf..a2eb41a257a92 100644 --- a/src/plugins/home/server/tutorials/zscaler_logs/index.ts +++ b/src/plugins/home/server/tutorials/zscaler_logs/index.ts @@ -56,5 +56,6 @@ export function zscalerLogsSpecProvider(context: TutorialContext): TutorialSchem onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms), + integrationBrowserCategories: ['network', 'security'], }; } From ab166240de0782e08d9f99d81ac843efaf02284a Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Fri, 1 Oct 2021 13:23:37 -0400 Subject: [PATCH 12/98] Create standards.mdx (#113313) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- dev_docs/contributing/standards.mdx | 74 +++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 dev_docs/contributing/standards.mdx diff --git a/dev_docs/contributing/standards.mdx b/dev_docs/contributing/standards.mdx new file mode 100644 index 0000000000000..3d41de8f229cc --- /dev/null +++ b/dev_docs/contributing/standards.mdx @@ -0,0 +1,74 @@ +--- +id: kibStandards +slug: /kibana-dev-docs/standards +title: Standards and guidelines +summary: Standards and guidelines we expect every Kibana developer to abide by +date: 2021-09-28 +tags: ['contributor', 'dev', 'github', 'getting started', 'onboarding', 'kibana'] +--- + +## Developer principles + +We expect all developers to read and abide by our overarching . + +## Style guide + +Please read and abide by our . The majority of these items are linted against but some are not. + +## RESTful HTTP APIs + +### Terminology + +**REST APIs** +Technically, REST does not specify a protocol, but for readability, we’ll be calling RESTful HTTP APIs as REST APIs for short for the remainder of the section. HTTP APIs that serve HTML, CSS and images are not REST APIs. + +**End user** +Anywhere we refer to “end user” in this section, we are referring to someone who is using the REST APIs. The distinction between Product breaking changes and plugin breaking changes can also be found in this [Make it Minor strawman proposal doc](https://docs.google.com/document/d/12R0w75dSNR-VDQLGl2vxFyEHhzxNT38iamYhven9uvw/edit). This can be a tricky distinction, as some folks may consider end user to only be folks that use the Kibana UI. + +### Privacy + +| Type | Description | Guarantees | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| Internal | An API with “internal” in the route. Specifically it should be `/internal/{pluginname}/{...}`. It should only be used by the plugin that created it. | None | +| Public | Any API that is not internal based on above definition | Based on | + +### Do not access directly from plugins + +Plugins should not attempt to directly access the REST APIs created by another plugin. The plugin author who registered the public REST API should provide access to it via functionality on the plugin lifecycle contract. Accessing functionality through a client side plugin contract provides more type-safety compared to calling the REST API directly. Never attempt to call a server-side REST API if you are already on the server-side. It will not work. This should also be avoided in any code provided within a common folder. + +### Path names + +All public API path names should start with `/api/`. +All internal APIs should start with `/internal/{pluginname}/{...}`. + +### Backward compatibility and breaking changes + +Every public API should have a release tag specified at the top of it’s documentation page. Release tags are not applicable to internal APIs, as we make no guarantees on those. + +#### Release tags + +| Type | Description | Documentation | Asciidoc Tag | +| Undocumented | Every public API should be documented, but if it isn’t, we make no guarantees about it. These need to be eliminated and should become internal or documented. | +| Experimental | A public API that may break or be removed at any time. | experimental[] | +| Beta | A public API that we make a best effort not to break or remove. However, there are no guarantees. | beta[] | +| Stable | No breaking changes outside of a Major\* | stable[] | +| Deprecated | Do not use, will be removed. | deprecated[] | + +\*This is likely to change with Make it Minor as we move towards a calendar based rolling deprecation and removal policy. + +#### What constitutes a breaking change? + +- A path change +- A request payload change that adds a new required variable, or changes an existing one (new optional parameters are not breaking). +- A response payload change that removes data or changes existing data (returning additional data is not breaking). +- Status code changes + +### Telemetry + +Every team should be collecting telemetry metrics on it’s public API usage. This will be important for knowing when it’s safe to make breaking changes. The Core team will be looking into ways to make this easier and an automatic part of registration (see [#112291](https://github.com/elastic/kibana/issues/112291)). + +### Documentation + +Every public API should be documented inside the [docs/api](https://github.com/elastic/kibana/tree/master/docs/api) folder in asciidoc (this content will eventually be migrated to mdx to support the new docs system). If a public REST API is undocumented, you should either document it, or make it internal. + +Every public API should have a release tag specified using the appropriate documentation release tag above. If you do this, the docs system will provide a pop up explaining the conditions. If an API is not marked, it should be considered experimental. From 7b05ecbac1021a17337ce7f28938aa27fcb9d46b Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Fri, 1 Oct 2021 14:04:01 -0400 Subject: [PATCH 13/98] [buildkite] Add a minimal flaky test suite runner job (#113575) --- .buildkite/pipelines/flaky_tests/pipeline.js | 52 +++++++++++++ .buildkite/pipelines/flaky_tests/pipeline.sh | 5 ++ .buildkite/pipelines/flaky_tests/runner.js | 82 ++++++++++++++++++++ .buildkite/pipelines/flaky_tests/runner.sh | 8 ++ 4 files changed, 147 insertions(+) create mode 100644 .buildkite/pipelines/flaky_tests/pipeline.js create mode 100755 .buildkite/pipelines/flaky_tests/pipeline.sh create mode 100644 .buildkite/pipelines/flaky_tests/runner.js create mode 100755 .buildkite/pipelines/flaky_tests/runner.sh diff --git a/.buildkite/pipelines/flaky_tests/pipeline.js b/.buildkite/pipelines/flaky_tests/pipeline.js new file mode 100644 index 0000000000000..1d390ed0d1b63 --- /dev/null +++ b/.buildkite/pipelines/flaky_tests/pipeline.js @@ -0,0 +1,52 @@ +const stepInput = (key, nameOfSuite) => { + return { + key: `ftsr-suite/${key}`, + text: nameOfSuite, + required: false, + default: '0', + }; +}; + +const OSS_CI_GROUPS = 12; +const XPACK_CI_GROUPS = 13; + +const inputs = [ + { + key: 'ftsr-override-count', + text: 'Override for all suites', + default: 0, + required: true, + }, + { + key: 'ftsr-concurrency', + text: 'Max concurrency per step', + default: 20, + required: true, + }, +]; + +for (let i = 1; i <= OSS_CI_GROUPS; i++) { + inputs.push(stepInput(`oss/cigroup/${i}`, `OSS CI Group ${i}`)); +} + +for (let i = 1; i <= XPACK_CI_GROUPS; i++) { + inputs.push(stepInput(`xpack/cigroup/${i}`, `Default CI Group ${i}`)); +} + +const pipeline = { + steps: [ + { + input: 'Number of Runs', + fields: inputs, + }, + { + wait: '~', + }, + { + command: '.buildkite/pipelines/flaky_tests/runner.sh', + label: 'Create pipeline', + }, + ], +}; + +console.log(JSON.stringify(pipeline, null, 2)); diff --git a/.buildkite/pipelines/flaky_tests/pipeline.sh b/.buildkite/pipelines/flaky_tests/pipeline.sh new file mode 100755 index 0000000000000..6335cd5490af0 --- /dev/null +++ b/.buildkite/pipelines/flaky_tests/pipeline.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -euo pipefail + +node .buildkite/pipelines/flaky_tests/pipeline.js | buildkite-agent pipeline upload diff --git a/.buildkite/pipelines/flaky_tests/runner.js b/.buildkite/pipelines/flaky_tests/runner.js new file mode 100644 index 0000000000000..46c390ce455ca --- /dev/null +++ b/.buildkite/pipelines/flaky_tests/runner.js @@ -0,0 +1,82 @@ +const { execSync } = require('child_process'); + +const keys = execSync('buildkite-agent meta-data keys') + .toString() + .split('\n') + .filter((k) => k.startsWith('ftsr-suite/')); + +const overrideCount = parseInt( + execSync(`buildkite-agent meta-data get 'ftsr-override-count'`).toString().trim() +); + +const concurrency = + parseInt(execSync(`buildkite-agent meta-data get 'ftsr-concurrency'`).toString().trim()) || 20; + +const testSuites = []; +for (const key of keys) { + if (!key) { + continue; + } + + const value = + overrideCount || execSync(`buildkite-agent meta-data get '${key}'`).toString().trim(); + + testSuites.push({ + key: key.replace('ftsr-suite/', ''), + count: value === '' ? defaultCount : parseInt(value), + }); +} + +const steps = []; +const pipeline = { + env: { + IGNORE_SHIP_CI_STATS_ERROR: 'true', + }, + steps: steps, +}; + +steps.push({ + command: '.buildkite/scripts/steps/build_kibana.sh', + label: 'Build Kibana Distribution and Plugins', + agents: { queue: 'c2-8' }, + key: 'build', + if: "build.env('BUILD_ID_FOR_ARTIFACTS') == null || build.env('BUILD_ID_FOR_ARTIFACTS') == ''", +}); + +for (const testSuite of testSuites) { + const TEST_SUITE = testSuite.key; + const RUN_COUNT = testSuite.count; + const UUID = TEST_SUITE + process.env.UUID; + + const JOB_PARTS = TEST_SUITE.split('/'); + const IS_XPACK = JOB_PARTS[0] === 'xpack'; + const CI_GROUP = JOB_PARTS.length > 2 ? JOB_PARTS[2] : ''; + + if (RUN_COUNT < 1) { + continue; + } + + if (IS_XPACK) { + steps.push({ + command: `CI_GROUP=${CI_GROUP} .buildkite/scripts/steps/functional/xpack_cigroup.sh`, + label: `Default CI Group ${CI_GROUP}`, + agents: { queue: 'ci-group-6' }, + depends_on: 'build', + parallelism: RUN_COUNT, + concurrency: concurrency, + concurrency_group: UUID, + }); + } else { + steps.push({ + command: `CI_GROUP=${CI_GROUP} .buildkite/scripts/steps/functional/oss_cigroup.sh`, + label: `OSS CI Group ${CI_GROUP}`, + agents: { queue: 'ci-group-4d' }, + depends_on: 'build', + parallelism: RUN_COUNT, + concurrency: concurrency, + concurrency_group: UUID, + }); + } +} + +console.log(JSON.stringify(pipeline, null, 2)); diff --git a/.buildkite/pipelines/flaky_tests/runner.sh b/.buildkite/pipelines/flaky_tests/runner.sh new file mode 100755 index 0000000000000..b541af88a408a --- /dev/null +++ b/.buildkite/pipelines/flaky_tests/runner.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail + +UUID="$(cat /proc/sys/kernel/random/uuid)" +export UUID + +node .buildkite/pipelines/flaky_tests/runner.js | buildkite-agent pipeline upload From 9437e8d5380f3ba419828c753d73522267d53795 Mon Sep 17 00:00:00 2001 From: Kristof C Date: Fri, 1 Oct 2021 15:03:10 -0500 Subject: [PATCH 14/98] [Cases] [104932] Remove newline characters from summary field and add tests (#113571) * [104932] Remove newline characters from summary field and add tests * PR fix Co-authored-by: Kristof-Pierre Cummings Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../builtin_action_types/jira/service.test.ts | 51 +++++++++++++++++++ .../builtin_action_types/jira/service.ts | 10 +++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts index af518f0cebc07..2300143925b1e 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts @@ -316,6 +316,57 @@ describe('Jira service', () => { }); }); + test('removes newline characters and trialing spaces from summary', async () => { + requestMock.mockImplementationOnce(() => ({ + data: { + capabilities: { + navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', + }, + }, + })); + + // getIssueType mocks + requestMock.mockImplementationOnce(() => issueTypesResponse); + + // getIssueType mocks + requestMock.mockImplementationOnce(() => ({ + data: { id: '1', key: 'CK-1', fields: { summary: 'test', description: 'description' } }, + })); + + requestMock.mockImplementationOnce(() => ({ + data: { id: '1', key: 'CK-1', fields: { created: '2020-04-27T10:59:46.202Z' } }, + })); + + await service.createIncident({ + incident: { + summary: 'title \n \n \n howdy \r \r \n \r test', + description: 'desc', + labels: [], + priority: 'High', + issueType: null, + parent: null, + }, + }); + + expect(requestMock).toHaveBeenCalledWith({ + axios, + url: 'https://siem-kibana.atlassian.net/rest/api/2/issue', + logger, + method: 'post', + configurationUtilities, + data: { + fields: { + summary: 'title, howdy, test', + description: 'desc', + project: { key: 'CK' }, + issuetype: { id: '10006' }, + labels: [], + priority: { name: 'High' }, + }, + }, + }); + }); + test('it should call request with correct arguments', async () => { requestMock.mockImplementation(() => ({ data: { diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts index 063895c7eb5cd..be0240e705a65 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts @@ -6,6 +6,7 @@ */ import axios from 'axios'; +import { isEmpty } from 'lodash'; import { Logger } from '../../../../../../src/core/server'; import { @@ -76,7 +77,7 @@ export const createExternalService = ( const createFields = (key: string, incident: Incident): Fields => { let fields: Fields = { - summary: incident.summary, + summary: trimAndRemoveNewlines(incident.summary), project: { key }, }; @@ -103,6 +104,13 @@ export const createExternalService = ( return fields; }; + const trimAndRemoveNewlines = (str: string) => + str + .split(/[\n\r]/gm) + .map((item) => item.trim()) + .filter((item) => !isEmpty(item)) + .join(', '); + const createErrorMessage = (errorResponse: ResponseError | string | null | undefined): string => { if (errorResponse == null) { return ''; From cdc5204af97a2634f502bb7748f13bfd35fc5824 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Fri, 1 Oct 2021 16:24:28 -0400 Subject: [PATCH 15/98] [Fleet] Add APM card to integration browser (#113625) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/apm/server/tutorial/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/apm/server/tutorial/index.ts b/x-pack/plugins/apm/server/tutorial/index.ts index 4c99cce241170..66e6ffaed95a8 100644 --- a/x-pack/plugins/apm/server/tutorial/index.ts +++ b/x-pack/plugins/apm/server/tutorial/index.ts @@ -103,6 +103,8 @@ It allows you to monitor the performance of thousands of applications in real ti } ), euiIconType: 'apmApp', + eprPackageOverlap: 'apm', + integrationBrowserCategories: ['web'], artifacts, customStatusCheckName: 'apm_fleet_server_status_check', onPrem: onPremInstructions({ apmConfig, isFleetPluginEnabled }), From 17d3cb844fdeb4cc726788e89159594b7ca9bdfd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 1 Oct 2021 15:07:55 -0700 Subject: [PATCH 16/98] Update babel (master) (#113352) Signed-off-by: Tyler Smalley --- package.json | 40 +- packages/kbn-dev-utils/BUILD.bazel | 18 +- packages/kbn-pm/dist/index.js | 6416 ++++++++--------- packages/kbn-ui-shared-deps-npm/BUILD.bazel | 9 +- .../__snapshots__/html.test.js.snap | 2 +- yarn.lock | 1106 ++- 6 files changed, 4142 insertions(+), 3449 deletions(-) diff --git a/package.json b/package.json index 28ed283aab2a5..967fe03934cff 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "yarn": "^1.21.1" }, "dependencies": { - "@babel/runtime": "^7.12.5", + "@babel/runtime": "^7.15.4", "@elastic/apm-rum": "^5.9.1", "@elastic/apm-rum-react": "^1.3.1", "@elastic/charts": "34.2.1", @@ -415,23 +415,23 @@ "yauzl": "^2.10.0" }, "devDependencies": { - "@babel/cli": "^7.12.10", - "@babel/core": "^7.12.10", - "@babel/generator": "^7.12.11", - "@babel/parser": "^7.12.11", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-export-namespace-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-transform-runtime": "^7.12.10", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.10", - "@babel/traverse": "^7.12.12", - "@babel/types": "^7.12.12", + "@babel/cli": "^7.15.7", + "@babel/core": "^7.15.5", + "@babel/generator": "^7.15.4", + "@babel/parser": "^7.15.7", + "@babel/plugin-proposal-class-properties": "^7.14.5", + "@babel/plugin-proposal-export-namespace-from": "^7.14.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", + "@babel/plugin-proposal-object-rest-spread": "^7.15.6", + "@babel/plugin-proposal-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-private-methods": "^7.14.5", + "@babel/plugin-transform-runtime": "^7.15.0", + "@babel/preset-env": "^7.15.6", + "@babel/preset-react": "^7.14.5", + "@babel/preset-typescript": "^7.15.0", + "@babel/register": "^7.15.3", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.6", "@bazel/ibazel": "^0.15.10", "@bazel/typescript": "^3.8.0", "@cypress/snapshot": "^2.1.7", @@ -493,7 +493,7 @@ "@types/angular-mocks": "^1.7.0", "@types/apidoc": "^0.22.3", "@types/archiver": "^5.1.0", - "@types/babel__core": "^7.1.12", + "@types/babel__core": "^7.1.16", "@types/base64-js": "^1.2.5", "@types/bluebird": "^3.1.1", "@types/chance": "^1.0.0", @@ -659,7 +659,7 @@ "babel-plugin-add-module-exports": "^1.0.4", "babel-plugin-istanbul": "^6.0.0", "babel-plugin-require-context-hook": "^1.0.0", - "babel-plugin-styled-components": "^1.10.7", + "babel-plugin-styled-components": "^1.13.2", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "backport": "^5.6.6", "base64url": "^3.0.1", diff --git a/packages/kbn-dev-utils/BUILD.bazel b/packages/kbn-dev-utils/BUILD.bazel index 90b4d91b66692..4fd99e0144cb6 100644 --- a/packages/kbn-dev-utils/BUILD.bazel +++ b/packages/kbn-dev-utils/BUILD.bazel @@ -62,18 +62,14 @@ RUNTIME_DEPS = [ "@npm//tar", "@npm//tree-kill", "@npm//vinyl", - "@npm//yauzl" + "@npm//yauzl", ] TYPES_DEPS = [ "//packages/kbn-std", "//packages/kbn-utils", - "@npm//axios", - "@npm//execa", - "@npm//exit-hook", - "@npm//getopts", - "@npm//rxjs", - "@npm//tree-kill", + "@npm//@babel/parser", + "@npm//@babel/types", "@npm//@types/babel__core", "@npm//@types/cheerio", "@npm//@types/dedent", @@ -87,7 +83,13 @@ TYPES_DEPS = [ "@npm//@types/tar", "@npm//@types/testing-library__jest-dom", "@npm//@types/vinyl", - "@npm//@types/yauzl" + "@npm//@types/yauzl", + "@npm//axios", + "@npm//execa", + "@npm//exit-hook", + "@npm//getopts", + "@npm//rxjs", + "@npm//tree-kill", ] jsts_transpiler( diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index fb62c04a94f8a..d0afe0330fb8b 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,21 +94,21 @@ __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__(556); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(554); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildBazelProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildNonBazelProductionProjects"]; }); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(342); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(340); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjects", function() { return _utils_projects__WEBPACK_IMPORTED_MODULE_2__["getProjects"]; }); -/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(344); +/* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(342); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return _utils_project__WEBPACK_IMPORTED_MODULE_3__["Project"]; }); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(345); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(343); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "transformDependencies", function() { return _utils_package_json__WEBPACK_IMPORTED_MODULE_4__["transformDependencies"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(555); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(553); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -140,9 +140,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(131); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(550); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(222); +/* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(129); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(548); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -587,11 +587,11 @@ Object.defineProperty(exports, "ToolingLogCollectingWriter", { var _tooling_log = __webpack_require__(6); -var _tooling_log_text_writer = __webpack_require__(114); +var _tooling_log_text_writer = __webpack_require__(112); -var _log_levels = __webpack_require__(129); +var _log_levels = __webpack_require__(127); -var _tooling_log_collecting_writer = __webpack_require__(130); +var _tooling_log_collecting_writer = __webpack_require__(128); /***/ }), /* 6 */ @@ -600,20 +600,22 @@ var _tooling_log_collecting_writer = __webpack_require__(130); "use strict"; -var _interopRequireWildcard = __webpack_require__(7); - -var _interopRequireDefault = __webpack_require__(9); +var _interopRequireDefault = __webpack_require__(7); Object.defineProperty(exports, "__esModule", { value: true }); exports.ToolingLog = void 0; -var _defineProperty2 = _interopRequireDefault(__webpack_require__(10)); +var _defineProperty2 = _interopRequireDefault(__webpack_require__(8)); + +var Rx = _interopRequireWildcard(__webpack_require__(9)); + +var _tooling_log_text_writer = __webpack_require__(112); -var Rx = _interopRequireWildcard(__webpack_require__(11)); +function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } -var _tooling_log_text_writer = __webpack_require__(114); +function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -701,92 +703,6 @@ exports.ToolingLog = ToolingLog; /***/ }), /* 7 */ -/***/ (function(module, exports, __webpack_require__) { - -var _typeof = __webpack_require__(8)["default"]; - -function _getRequireWildcardCache(nodeInterop) { - if (typeof WeakMap !== "function") return null; - var cacheBabelInterop = new WeakMap(); - var cacheNodeInterop = new WeakMap(); - return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { - return nodeInterop ? cacheNodeInterop : cacheBabelInterop; - })(nodeInterop); -} - -function _interopRequireWildcard(obj, nodeInterop) { - if (!nodeInterop && obj && obj.__esModule) { - return obj; - } - - if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { - return { - "default": obj - }; - } - - var cache = _getRequireWildcardCache(nodeInterop); - - if (cache && cache.has(obj)) { - return cache.get(obj); - } - - var newObj = {}; - var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; - - for (var key in obj) { - if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { - var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; - - if (desc && (desc.get || desc.set)) { - Object.defineProperty(newObj, key, desc); - } else { - newObj[key] = obj[key]; - } - } - } - - newObj["default"] = obj; - - if (cache) { - cache.set(obj, newObj); - } - - return newObj; -} - -module.exports = _interopRequireWildcard; -module.exports["default"] = module.exports, module.exports.__esModule = true; - -/***/ }), -/* 8 */ -/***/ (function(module, exports) { - -function _typeof(obj) { - "@babel/helpers - typeof"; - - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - module.exports = _typeof = function _typeof(obj) { - return typeof obj; - }; - - module.exports["default"] = module.exports, module.exports.__esModule = true; - } else { - module.exports = _typeof = function _typeof(obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - - module.exports["default"] = module.exports, module.exports.__esModule = true; - } - - return _typeof(obj); -} - -module.exports = _typeof; -module.exports["default"] = module.exports, module.exports.__esModule = true; - -/***/ }), -/* 9 */ /***/ (function(module, exports) { function _interopRequireDefault(obj) { @@ -799,7 +715,7 @@ module.exports = _interopRequireDefault; module.exports["default"] = module.exports, module.exports.__esModule = true; /***/ }), -/* 10 */ +/* 8 */ /***/ (function(module, exports) { function _defineProperty(obj, key, value) { @@ -821,184 +737,184 @@ module.exports = _defineProperty; module.exports["default"] = module.exports, module.exports.__esModule = true; /***/ }), -/* 11 */ +/* 9 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return _internal_Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]; }); -/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(29); +/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__["ConnectableObservable"]; }); -/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); +/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(32); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__["GroupedObservable"]; }); -/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(26); +/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(24); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observable", function() { return _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__["observable"]; }); -/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(30); +/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(28); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return _internal_Subject__WEBPACK_IMPORTED_MODULE_4__["Subject"]; }); -/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(35); +/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__["BehaviorSubject"]; }); -/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(36); +/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__["ReplaySubject"]; }); -/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(53); +/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(51); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__["AsyncSubject"]; }); -/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(54); +/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(52); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asap", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asap"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asapScheduler"]; }); -/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(58); +/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(56); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "async", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["async"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["asyncScheduler"]; }); -/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(37); +/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(35); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queue", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queue"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queueScheduler"]; }); -/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(59); +/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(57); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrame"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrameScheduler"]; }); -/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(62); +/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(60); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualTimeScheduler"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualAction"]; }); -/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(43); +/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(41); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Scheduler", function() { return _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__["Scheduler"]; }); -/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(20); +/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(18); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__["Subscription"]; }); -/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(14); +/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(12); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__["Subscriber"]; }); -/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(45); +/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(43); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return _internal_Notification__WEBPACK_IMPORTED_MODULE_16__["Notification"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "NotificationKind", function() { return _internal_Notification__WEBPACK_IMPORTED_MODULE_16__["NotificationKind"]; }); -/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(27); +/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(25); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__["pipe"]; }); -/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(63); +/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(61); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "noop", function() { return _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__["noop"]; }); -/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(28); +/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(26); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "identity", function() { return _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__["identity"]; }); -/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(64); +/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(62); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__["isObservable"]; }); -/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(65); +/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(63); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__["ArgumentOutOfRangeError"]; }); -/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(66); +/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(64); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__["EmptyError"]; }); -/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(31); +/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(29); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__["ObjectUnsubscribedError"]; }); -/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(23); +/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(21); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__["UnsubscriptionError"]; }); -/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(67); +/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(65); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__["TimeoutError"]; }); -/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(68); +/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(66); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__["bindCallback"]; }); -/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(70); +/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(68); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__["bindNodeCallback"]; }); -/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(71); +/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(69); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__["combineLatest"]; }); -/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(82); +/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(80); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__["concat"]; }); -/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(94); +/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(92); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__["defer"]; }); -/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(46); +/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(44); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["empty"]; }); -/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(95); +/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(93); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__["forkJoin"]; }); -/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(86); +/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(84); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "from", function() { return _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__["from"]; }); -/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(96); +/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(94); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__["fromEvent"]; }); -/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(97); +/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(95); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__["fromEventPattern"]; }); -/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(98); +/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(96); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__["generate"]; }); -/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(99); +/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(97); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__["iif"]; }); -/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(100); +/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(98); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__["interval"]; }); -/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(102); +/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(100); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__["merge"]; }); -/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(103); +/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(101); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "never", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["never"]; }); -/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(47); +/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(45); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "of", function() { return _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__["of"]; }); -/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(104); +/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(102); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(105); +/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(103); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__["pairs"]; }); -/* harmony import */ var _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(106); +/* harmony import */ var _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(104); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_observable_partition__WEBPACK_IMPORTED_MODULE_44__["partition"]; }); -/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(109); +/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(107); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_observable_race__WEBPACK_IMPORTED_MODULE_45__["race"]; }); -/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(110); +/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(108); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "range", function() { return _internal_observable_range__WEBPACK_IMPORTED_MODULE_46__["range"]; }); -/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(52); +/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(50); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_47__["throwError"]; }); -/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(111); +/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(109); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return _internal_observable_timer__WEBPACK_IMPORTED_MODULE_48__["timer"]; }); -/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(112); +/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(110); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "using", function() { return _internal_observable_using__WEBPACK_IMPORTED_MODULE_49__["using"]; }); -/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(113); +/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(111); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_observable_zip__WEBPACK_IMPORTED_MODULE_50__["zip"]; }); -/* harmony import */ var _internal_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(87); +/* harmony import */ var _internal_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(85); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scheduled", function() { return _internal_scheduled_scheduled__WEBPACK_IMPORTED_MODULE_51__["scheduled"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["EMPTY"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["NEVER"]; }); -/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(18); +/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(16); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "config", function() { return _internal_config__WEBPACK_IMPORTED_MODULE_52__["config"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -1061,17 +977,17 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 12 */ +/* 10 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return Observable; }); -/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); -/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(25); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(26); -/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(27); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(18); +/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(11); +/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(23); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(24); +/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(25); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(16); /** PURE_IMPORTS_START _util_canReportError,_util_toSubscriber,_symbol_observable,_util_pipe,_config PURE_IMPORTS_END */ @@ -1191,13 +1107,13 @@ function getPromiseCtor(promiseCtor) { /***/ }), -/* 13 */ +/* 11 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "canReportError", function() { return canReportError; }); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(14); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); /** PURE_IMPORTS_START _Subscriber PURE_IMPORTS_END */ function canReportError(observer) { @@ -1219,20 +1135,20 @@ function canReportError(observer) { /***/ }), -/* 14 */ +/* 12 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return Subscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SafeSubscriber", function() { return SafeSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16); -/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(17); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(20); -/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(24); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(18); -/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(15); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18); +/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(22); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(16); +/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(17); /** PURE_IMPORTS_START tslib,_util_isFunction,_Observer,_Subscription,_internal_symbol_rxSubscriber,_config,_util_hostReportError PURE_IMPORTS_END */ @@ -1469,7 +1385,7 @@ var SafeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 15 */ +/* 13 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1718,7 +1634,7 @@ function __classPrivateFieldSet(receiver, privateMap, value) { /***/ }), -/* 16 */ +/* 14 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1732,14 +1648,14 @@ function isFunction(x) { /***/ }), -/* 17 */ +/* 15 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); -/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); +/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(17); /** PURE_IMPORTS_START _config,_util_hostReportError PURE_IMPORTS_END */ @@ -1760,7 +1676,7 @@ var empty = { /***/ }), -/* 18 */ +/* 16 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1788,7 +1704,7 @@ var config = { /***/ }), -/* 19 */ +/* 17 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1802,16 +1718,16 @@ function hostReportError(err) { /***/ }), -/* 20 */ +/* 18 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return Subscription; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21); -/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(22); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); -/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(23); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19); +/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); +/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(21); /** PURE_IMPORTS_START _util_isArray,_util_isObject,_util_isFunction,_util_UnsubscriptionError PURE_IMPORTS_END */ @@ -1955,7 +1871,7 @@ function flattenUnsubscriptionErrors(errors) { /***/ }), -/* 21 */ +/* 19 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1967,7 +1883,7 @@ var isArray = /*@__PURE__*/ (function () { return Array.isArray || (function (x) /***/ }), -/* 22 */ +/* 20 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -1981,7 +1897,7 @@ function isObject(x) { /***/ }), -/* 23 */ +/* 21 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -2005,7 +1921,7 @@ var UnsubscriptionError = UnsubscriptionErrorImpl; /***/ }), -/* 24 */ +/* 22 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -2023,15 +1939,15 @@ var $$rxSubscriber = rxSubscriber; /***/ }), -/* 25 */ +/* 23 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toSubscriber", function() { return toSubscriber; }); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(14); -/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(24); -/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(17); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(22); +/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(15); /** PURE_IMPORTS_START _Subscriber,_symbol_rxSubscriber,_Observer PURE_IMPORTS_END */ @@ -2054,7 +1970,7 @@ function toSubscriber(nextOrObserver, error, complete) { /***/ }), -/* 26 */ +/* 24 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -2066,14 +1982,14 @@ var observable = /*@__PURE__*/ (function () { return typeof Symbol === 'function /***/ }), -/* 27 */ +/* 25 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return pipe; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipeFromArray", function() { return pipeFromArray; }); -/* harmony import */ var _identity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(28); +/* harmony import */ var _identity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(26); /** PURE_IMPORTS_START _identity PURE_IMPORTS_END */ function pipe() { @@ -2098,7 +2014,7 @@ function pipeFromArray(fns) { /***/ }), -/* 28 */ +/* 26 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -2112,19 +2028,19 @@ function identity(x) { /***/ }), -/* 29 */ +/* 27 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return ConnectableObservable; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "connectableObservableDescriptor", function() { return connectableObservableDescriptor; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(14); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); -/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(33); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(18); +/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(31); /** PURE_IMPORTS_START tslib,_Subject,_Observable,_Subscriber,_Subscription,_operators_refCount PURE_IMPORTS_END */ @@ -2270,7 +2186,7 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 30 */ +/* 28 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -2278,13 +2194,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubjectSubscriber", function() { return SubjectSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return Subject; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnonymousSubject", function() { return AnonymousSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(20); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(31); -/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(32); -/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(24); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(29); +/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(30); +/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(22); /** PURE_IMPORTS_START tslib,_Observable,_Subscriber,_Subscription,_util_ObjectUnsubscribedError,_SubjectSubscription,_internal_symbol_rxSubscriber PURE_IMPORTS_END */ @@ -2446,7 +2362,7 @@ var AnonymousSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 31 */ +/* 29 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -2468,14 +2384,14 @@ var ObjectUnsubscribedError = ObjectUnsubscribedErrorImpl; /***/ }), -/* 32 */ +/* 30 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubjectSubscription", function() { return SubjectSubscription; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */ @@ -2511,14 +2427,14 @@ var SubjectSubscription = /*@__PURE__*/ (function (_super) { /***/ }), -/* 33 */ +/* 31 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return refCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -2580,18 +2496,18 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 34 */ +/* 32 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return groupBy; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return GroupedObservable; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(30); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(18); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(28); /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription,_Observable,_Subject PURE_IMPORTS_END */ @@ -2777,15 +2693,15 @@ var InnerRefCountSubscription = /*@__PURE__*/ (function (_super) { /***/ }), -/* 35 */ +/* 33 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return BehaviorSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(31); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /** PURE_IMPORTS_START tslib,_Subject,_util_ObjectUnsubscribedError PURE_IMPORTS_END */ @@ -2832,19 +2748,19 @@ var BehaviorSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 36 */ +/* 34 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return ReplaySubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(37); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(20); -/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(44); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(31); -/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(32); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(35); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18); +/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(42); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(29); +/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(30); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_queue,_Subscription,_operators_observeOn,_util_ObjectUnsubscribedError,_SubjectSubscription PURE_IMPORTS_END */ @@ -2969,15 +2885,15 @@ var ReplayEvent = /*@__PURE__*/ (function () { /***/ }), -/* 37 */ +/* 35 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return queueScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "queue", function() { return queue; }); -/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(38); -/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(41); +/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36); +/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(39); /** PURE_IMPORTS_START _QueueAction,_QueueScheduler PURE_IMPORTS_END */ @@ -2987,14 +2903,14 @@ var queue = queueScheduler; /***/ }), -/* 38 */ +/* 36 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueAction", function() { return QueueAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(39); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(37); /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */ @@ -3039,14 +2955,14 @@ var QueueAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 39 */ +/* 37 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncAction", function() { return AsyncAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(40); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(38); /** PURE_IMPORTS_START tslib,_Action PURE_IMPORTS_END */ @@ -3145,14 +3061,14 @@ var AsyncAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 40 */ +/* 38 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Action", function() { return Action; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */ @@ -3174,14 +3090,14 @@ var Action = /*@__PURE__*/ (function (_super) { /***/ }), -/* 41 */ +/* 39 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueScheduler", function() { return QueueScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(40); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -3197,14 +3113,14 @@ var QueueScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 42 */ +/* 40 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncScheduler", function() { return AsyncScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(43); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(41); /** PURE_IMPORTS_START tslib,_Scheduler PURE_IMPORTS_END */ @@ -3266,7 +3182,7 @@ var AsyncScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 43 */ +/* 41 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -3294,7 +3210,7 @@ var Scheduler = /*@__PURE__*/ (function () { /***/ }), -/* 44 */ +/* 42 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -3303,9 +3219,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnOperator", function() { return ObserveOnOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnSubscriber", function() { return ObserveOnSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnMessage", function() { return ObserveOnMessage; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(45); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(43); /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -3378,16 +3294,16 @@ var ObserveOnMessage = /*@__PURE__*/ (function () { /***/ }), -/* 45 */ +/* 43 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NotificationKind", function() { return NotificationKind; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return Notification; }); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(46); -/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(47); -/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(52); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(44); +/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(45); +/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(50); /** PURE_IMPORTS_START _observable_empty,_observable_of,_observable_throwError PURE_IMPORTS_END */ @@ -3467,14 +3383,14 @@ var Notification = /*@__PURE__*/ (function () { /***/ }), -/* 46 */ +/* 44 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return EMPTY; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ var EMPTY = /*@__PURE__*/ new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) { return subscriber.complete(); }); @@ -3488,15 +3404,15 @@ function emptyScheduled(scheduler) { /***/ }), -/* 47 */ +/* 45 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "of", function() { return of; }); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(48); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(49); -/* harmony import */ var _scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(51); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(46); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(47); +/* harmony import */ var _scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(49); /** PURE_IMPORTS_START _util_isScheduler,_fromArray,_scheduled_scheduleArray PURE_IMPORTS_END */ @@ -3519,7 +3435,7 @@ function of() { /***/ }), -/* 48 */ +/* 46 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -3533,15 +3449,15 @@ function isScheduler(value) { /***/ }), -/* 49 */ +/* 47 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromArray", function() { return fromArray; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(50); -/* harmony import */ var _scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(51); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(48); +/* harmony import */ var _scheduled_scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(49); /** PURE_IMPORTS_START _Observable,_util_subscribeToArray,_scheduled_scheduleArray PURE_IMPORTS_END */ @@ -3558,7 +3474,7 @@ function fromArray(input, scheduler) { /***/ }), -/* 50 */ +/* 48 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -3577,14 +3493,14 @@ var subscribeToArray = function (array) { /***/ }), -/* 51 */ +/* 49 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scheduleArray", function() { return scheduleArray; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); /** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */ @@ -3609,13 +3525,13 @@ function scheduleArray(input, scheduler) { /***/ }), -/* 52 */ +/* 50 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return throwError; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function throwError(error, scheduler) { @@ -3634,15 +3550,15 @@ function dispatch(_a) { /***/ }), -/* 53 */ +/* 51 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return AsyncSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(18); /** PURE_IMPORTS_START tslib,_Subject,_Subscription PURE_IMPORTS_END */ @@ -3693,15 +3609,15 @@ var AsyncSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 54 */ +/* 52 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return asapScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asap", function() { return asap; }); -/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55); -/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(57); +/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(53); +/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55); /** PURE_IMPORTS_START _AsapAction,_AsapScheduler PURE_IMPORTS_END */ @@ -3711,15 +3627,15 @@ var asap = asapScheduler; /***/ }), -/* 55 */ +/* 53 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapAction", function() { return AsapAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(56); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(39); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(54); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(37); /** PURE_IMPORTS_START tslib,_util_Immediate,_AsyncAction PURE_IMPORTS_END */ @@ -3762,7 +3678,7 @@ var AsapAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 56 */ +/* 54 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -3800,14 +3716,14 @@ var TestTools = { /***/ }), -/* 57 */ +/* 55 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapScheduler", function() { return AsapScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(40); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -3844,15 +3760,15 @@ var AsapScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 58 */ +/* 56 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return asyncScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "async", function() { return async; }); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(39); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(37); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(40); /** PURE_IMPORTS_START _AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ @@ -3862,15 +3778,15 @@ var async = asyncScheduler; /***/ }), -/* 59 */ +/* 57 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return animationFrameScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return animationFrame; }); -/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(60); -/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(61); +/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(58); +/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(59); /** PURE_IMPORTS_START _AnimationFrameAction,_AnimationFrameScheduler PURE_IMPORTS_END */ @@ -3880,14 +3796,14 @@ var animationFrame = animationFrameScheduler; /***/ }), -/* 60 */ +/* 58 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameAction", function() { return AnimationFrameAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(39); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(37); /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */ @@ -3929,14 +3845,14 @@ var AnimationFrameAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 61 */ +/* 59 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameScheduler", function() { return AnimationFrameScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(40); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -3973,16 +3889,16 @@ var AnimationFrameScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 62 */ +/* 60 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return VirtualTimeScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return VirtualAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(39); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(42); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(37); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(40); /** PURE_IMPORTS_START tslib,_AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ @@ -4096,7 +4012,7 @@ var VirtualAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 63 */ +/* 61 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4108,13 +4024,13 @@ function noop() { } /***/ }), -/* 64 */ +/* 62 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return isObservable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function isObservable(obj) { @@ -4124,7 +4040,7 @@ function isObservable(obj) { /***/ }), -/* 65 */ +/* 63 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4146,7 +4062,7 @@ var ArgumentOutOfRangeError = ArgumentOutOfRangeErrorImpl; /***/ }), -/* 66 */ +/* 64 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4168,7 +4084,7 @@ var EmptyError = EmptyErrorImpl; /***/ }), -/* 67 */ +/* 65 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4190,18 +4106,18 @@ var TimeoutError = TimeoutErrorImpl; /***/ }), -/* 68 */ +/* 66 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return bindCallback; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(53); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(13); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(21); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(48); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(51); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(67); +/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(19); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(46); /** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_canReportError,_util_isArray,_util_isScheduler PURE_IMPORTS_END */ @@ -4310,15 +4226,15 @@ function dispatchError(state) { /***/ }), -/* 69 */ +/* 67 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "map", function() { return map; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MapOperator", function() { return MapOperator; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -4367,18 +4283,18 @@ var MapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 70 */ +/* 68 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return bindNodeCallback; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(53); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(13); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(48); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(21); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(51); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(67); +/* harmony import */ var _util_canReportError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(46); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(19); /** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_canReportError,_util_isScheduler,_util_isArray PURE_IMPORTS_END */ @@ -4495,7 +4411,7 @@ function dispatchError(arg) { /***/ }), -/* 71 */ +/* 69 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4503,12 +4419,12 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestOperator", function() { return CombineLatestOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestSubscriber", function() { return CombineLatestSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(48); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(72); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(73); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(49); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(46); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(19); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(71); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(47); /** PURE_IMPORTS_START tslib,_util_isScheduler,_util_isArray,_OuterSubscriber,_util_subscribeToResult,_fromArray PURE_IMPORTS_END */ @@ -4613,14 +4529,14 @@ var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 72 */ +/* 70 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OuterSubscriber", function() { return OuterSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -4645,15 +4561,15 @@ var OuterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 73 */ +/* 71 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToResult", function() { return subscribeToResult; }); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(74); -/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(75); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); +/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(72); +/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(73); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10); /** PURE_IMPORTS_START _InnerSubscriber,_subscribeTo,_Observable PURE_IMPORTS_END */ @@ -4674,14 +4590,14 @@ function subscribeToResult(outerSubscriber, result, outerValue, outerIndex, inne /***/ }), -/* 74 */ +/* 72 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InnerSubscriber", function() { return InnerSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -4713,21 +4629,21 @@ var InnerSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 75 */ +/* 73 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeTo", function() { return subscribeTo; }); -/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(50); -/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(76); -/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(77); -/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(79); -/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(80); -/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(81); -/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(22); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(78); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(26); +/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(48); +/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(74); +/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(75); +/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(77); +/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(78); +/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(79); +/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(20); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(76); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(24); /** PURE_IMPORTS_START _subscribeToArray,_subscribeToPromise,_subscribeToIterable,_subscribeToObservable,_isArrayLike,_isPromise,_isObject,_symbol_iterator,_symbol_observable PURE_IMPORTS_END */ @@ -4762,13 +4678,13 @@ var subscribeTo = function (result) { /***/ }), -/* 76 */ +/* 74 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToPromise", function() { return subscribeToPromise; }); -/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19); +/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17); /** PURE_IMPORTS_START _hostReportError PURE_IMPORTS_END */ var subscribeToPromise = function (promise) { @@ -4787,13 +4703,13 @@ var subscribeToPromise = function (promise) { /***/ }), -/* 77 */ +/* 75 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToIterable", function() { return subscribeToIterable; }); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(78); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(76); /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */ var subscribeToIterable = function (iterable) { @@ -4831,7 +4747,7 @@ var subscribeToIterable = function (iterable) { /***/ }), -/* 78 */ +/* 76 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4852,13 +4768,13 @@ var $$iterator = iterator; /***/ }), -/* 79 */ +/* 77 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToObservable", function() { return subscribeToObservable; }); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(26); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(24); /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */ var subscribeToObservable = function (obj) { @@ -4876,7 +4792,7 @@ var subscribeToObservable = function (obj) { /***/ }), -/* 80 */ +/* 78 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4888,7 +4804,7 @@ var isArrayLike = (function (x) { return x && typeof x.length === 'number' && ty /***/ }), -/* 81 */ +/* 79 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4902,14 +4818,14 @@ function isPromise(value) { /***/ }), -/* 82 */ +/* 80 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; }); -/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(47); -/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(83); +/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(45); +/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(81); /** PURE_IMPORTS_START _of,_operators_concatAll PURE_IMPORTS_END */ @@ -4924,13 +4840,13 @@ function concat() { /***/ }), -/* 83 */ +/* 81 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return concatAll; }); -/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(84); +/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(82); /** PURE_IMPORTS_START _mergeAll PURE_IMPORTS_END */ function concatAll() { @@ -4940,14 +4856,14 @@ function concatAll() { /***/ }), -/* 84 */ +/* 82 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return mergeAll; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(85); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(83); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(26); /** PURE_IMPORTS_START _mergeMap,_util_identity PURE_IMPORTS_END */ @@ -4961,7 +4877,7 @@ function mergeAll(concurrent) { /***/ }), -/* 85 */ +/* 83 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -4970,10 +4886,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapOperator", function() { return MergeMapOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapSubscriber", function() { return MergeMapSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return flatMap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(86); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(67); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(84); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */ @@ -5078,15 +4994,15 @@ var flatMap = mergeMap; /***/ }), -/* 86 */ +/* 84 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "from", function() { return from; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(75); -/* harmony import */ var _scheduled_scheduled__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(87); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(73); +/* harmony import */ var _scheduled_scheduled__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(85); /** PURE_IMPORTS_START _Observable,_util_subscribeTo,_scheduled_scheduled PURE_IMPORTS_END */ @@ -5106,20 +5022,20 @@ function from(input, scheduler) { /***/ }), -/* 87 */ +/* 85 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scheduled", function() { return scheduled; }); -/* harmony import */ var _scheduleObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(88); -/* harmony import */ var _schedulePromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(89); -/* harmony import */ var _scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(51); -/* harmony import */ var _scheduleIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(90); -/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(91); -/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(81); -/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(80); -/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(92); +/* harmony import */ var _scheduleObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(86); +/* harmony import */ var _schedulePromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(87); +/* harmony import */ var _scheduleArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(49); +/* harmony import */ var _scheduleIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(88); +/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(89); +/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(79); +/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(78); +/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(90); /** PURE_IMPORTS_START _scheduleObservable,_schedulePromise,_scheduleArray,_scheduleIterable,_util_isInteropObservable,_util_isPromise,_util_isArrayLike,_util_isIterable PURE_IMPORTS_END */ @@ -5150,15 +5066,15 @@ function scheduled(input, scheduler) { /***/ }), -/* 88 */ +/* 86 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scheduleObservable", function() { return scheduleObservable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(26); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(24); /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_observable PURE_IMPORTS_END */ @@ -5181,14 +5097,14 @@ function scheduleObservable(input, scheduler) { /***/ }), -/* 89 */ +/* 87 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "schedulePromise", function() { return schedulePromise; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); /** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */ @@ -5212,15 +5128,15 @@ function schedulePromise(input, scheduler) { /***/ }), -/* 90 */ +/* 88 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scheduleIterable", function() { return scheduleIterable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(78); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(76); /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_iterator PURE_IMPORTS_END */ @@ -5270,13 +5186,13 @@ function scheduleIterable(input, scheduler) { /***/ }), -/* 91 */ +/* 89 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isInteropObservable", function() { return isInteropObservable; }); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(26); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(24); /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */ function isInteropObservable(input) { @@ -5286,13 +5202,13 @@ function isInteropObservable(input) { /***/ }), -/* 92 */ +/* 90 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isIterable", function() { return isIterable; }); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(78); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(76); /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */ function isIterable(input) { @@ -5302,7 +5218,7 @@ function isIterable(input) { /***/ }), -/* 93 */ +/* 91 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -5312,10 +5228,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SimpleOuterSubscriber", function() { return SimpleOuterSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ComplexOuterSubscriber", function() { return ComplexOuterSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "innerSubscribe", function() { return innerSubscribe; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); -/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(75); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10); +/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(73); /** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_util_subscribeTo PURE_IMPORTS_END */ @@ -5412,15 +5328,15 @@ function innerSubscribe(result, innerSubscriber) { /***/ }), -/* 94 */ +/* 92 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return defer; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(86); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(46); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(84); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(44); /** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */ @@ -5443,17 +5359,17 @@ function defer(observableFactory) { /***/ }), -/* 95 */ +/* 93 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return forkJoin; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69); -/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(22); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(86); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(67); +/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(20); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(84); /** PURE_IMPORTS_START _Observable,_util_isArray,_operators_map,_util_isObject,_from PURE_IMPORTS_END */ @@ -5526,16 +5442,16 @@ function forkJoinInternal(sources, keys) { /***/ }), -/* 96 */ +/* 94 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return fromEvent; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(69); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(67); /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */ @@ -5602,16 +5518,16 @@ function isEventTarget(sourceObj) { /***/ }), -/* 97 */ +/* 95 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return fromEventPattern; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(69); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(67); /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */ @@ -5647,15 +5563,15 @@ function fromEventPattern(addHandler, removeHandler, resultSelector) { /***/ }), -/* 98 */ +/* 96 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return generate; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(48); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(26); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(46); /** PURE_IMPORTS_START _Observable,_util_identity,_util_isScheduler PURE_IMPORTS_END */ @@ -5784,14 +5700,14 @@ function dispatch(state) { /***/ }), -/* 99 */ +/* 97 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return iif; }); -/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(94); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(46); +/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(92); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(44); /** PURE_IMPORTS_START _defer,_empty PURE_IMPORTS_END */ @@ -5808,15 +5724,15 @@ function iif(condition, trueResult, falseResult) { /***/ }), -/* 100 */ +/* 98 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return interval; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(58); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(101); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(56); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(99); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric PURE_IMPORTS_END */ @@ -5848,13 +5764,13 @@ function dispatch(state) { /***/ }), -/* 101 */ +/* 99 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNumeric", function() { return isNumeric; }); -/* harmony import */ var _isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21); +/* harmony import */ var _isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19); /** PURE_IMPORTS_START _isArray PURE_IMPORTS_END */ function isNumeric(val) { @@ -5864,16 +5780,16 @@ function isNumeric(val) { /***/ }), -/* 102 */ +/* 100 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(48); -/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(84); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(49); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(46); +/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(82); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(47); /** PURE_IMPORTS_START _Observable,_util_isScheduler,_operators_mergeAll,_fromArray PURE_IMPORTS_END */ @@ -5905,15 +5821,15 @@ function merge() { /***/ }), -/* 103 */ +/* 101 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return NEVER; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "never", function() { return never; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(63); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(61); /** PURE_IMPORTS_START _Observable,_util_noop PURE_IMPORTS_END */ @@ -5925,16 +5841,16 @@ function never() { /***/ }), -/* 104 */ +/* 102 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(86); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(46); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(84); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(19); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(44); /** PURE_IMPORTS_START _Observable,_from,_util_isArray,_empty PURE_IMPORTS_END */ @@ -5965,15 +5881,15 @@ function onErrorResumeNext() { /***/ }), -/* 105 */ +/* 103 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return pairs; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dispatch", function() { return dispatch; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); /** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */ @@ -6016,16 +5932,16 @@ function dispatch(state) { /***/ }), -/* 106 */ +/* 104 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return partition; }); -/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(107); -/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(75); -/* harmony import */ var _operators_filter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(108); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12); +/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(105); +/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(73); +/* harmony import */ var _operators_filter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(106); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10); /** PURE_IMPORTS_START _util_not,_util_subscribeTo,_operators_filter,_Observable PURE_IMPORTS_END */ @@ -6041,7 +5957,7 @@ function partition(source, predicate, thisArg) { /***/ }), -/* 107 */ +/* 105 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6060,14 +5976,14 @@ function not(pred, thisArg) { /***/ }), -/* 108 */ +/* 106 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return filter; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -6114,7 +6030,7 @@ var FilterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 109 */ +/* 107 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6122,11 +6038,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceOperator", function() { return RaceOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceSubscriber", function() { return RaceSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(49); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(72); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(73); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(47); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(71); /** PURE_IMPORTS_START tslib,_util_isArray,_fromArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -6208,14 +6124,14 @@ var RaceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 110 */ +/* 108 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "range", function() { return range; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dispatch", function() { return dispatch; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function range(start, count, scheduler) { @@ -6267,16 +6183,16 @@ function dispatch(state) { /***/ }), -/* 111 */ +/* 109 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return timer; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(58); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(101); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(48); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(56); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(99); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(46); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -6321,15 +6237,15 @@ function dispatch(state) { /***/ }), -/* 112 */ +/* 110 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "using", function() { return using; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(86); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(46); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(10); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(84); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(44); /** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */ @@ -6366,7 +6282,7 @@ function using(resourceFactory, observableFactory) { /***/ }), -/* 113 */ +/* 111 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -6374,12 +6290,12 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipOperator", function() { return ZipOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipSubscriber", function() { return ZipSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(49); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(14); -/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(78); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(47); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(19); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12); +/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(76); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_.._internal_symbol_iterator,_innerSubscribe PURE_IMPORTS_END */ @@ -6600,26 +6516,26 @@ var ZipBufferIterator = /*@__PURE__*/ (function (_super) { /***/ }), -/* 114 */ +/* 112 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var _interopRequireDefault = __webpack_require__(9); +var _interopRequireDefault = __webpack_require__(7); Object.defineProperty(exports, "__esModule", { value: true }); exports.ToolingLogTextWriter = void 0; -var _defineProperty2 = _interopRequireDefault(__webpack_require__(10)); +var _defineProperty2 = _interopRequireDefault(__webpack_require__(8)); -var _util = __webpack_require__(115); +var _util = __webpack_require__(113); -var _chalk = _interopRequireDefault(__webpack_require__(116)); +var _chalk = _interopRequireDefault(__webpack_require__(114)); -var _log_levels = __webpack_require__(129); +var _log_levels = __webpack_require__(127); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -6716,23 +6632,23 @@ class ToolingLogTextWriter { exports.ToolingLogTextWriter = ToolingLogTextWriter; /***/ }), -/* 115 */ +/* 113 */ /***/ (function(module, exports) { module.exports = require("util"); /***/ }), -/* 116 */ +/* 114 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiStyles = __webpack_require__(117); -const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(123); +const ansiStyles = __webpack_require__(115); +const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(121); const { stringReplaceAll, stringEncaseCRLFWithFirstIndex -} = __webpack_require__(127); +} = __webpack_require__(125); const {isArray} = Array; @@ -6941,7 +6857,7 @@ const chalkTag = (chalk, ...strings) => { } if (template === undefined) { - template = __webpack_require__(128); + template = __webpack_require__(126); } return template(chalk, parts.join('')); @@ -6958,7 +6874,7 @@ module.exports = chalk; /***/ }), -/* 117 */ +/* 115 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -7004,7 +6920,7 @@ const setLazyProperty = (object, property, get) => { let colorConvert; const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => { if (colorConvert === undefined) { - colorConvert = __webpack_require__(119); + colorConvert = __webpack_require__(117); } const offset = isBackground ? 10 : 0; @@ -7126,10 +7042,10 @@ Object.defineProperty(module, 'exports', { get: assembleStyles }); -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(118)(module))) +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(116)(module))) /***/ }), -/* 118 */ +/* 116 */ /***/ (function(module, exports) { module.exports = function(module) { @@ -7157,11 +7073,11 @@ module.exports = function(module) { /***/ }), -/* 119 */ +/* 117 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(120); -const route = __webpack_require__(122); +const conversions = __webpack_require__(118); +const route = __webpack_require__(120); const convert = {}; @@ -7244,12 +7160,12 @@ module.exports = convert; /***/ }), -/* 120 */ +/* 118 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ /* eslint-disable no-mixed-operators */ -const cssKeywords = __webpack_require__(121); +const cssKeywords = __webpack_require__(119); // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). @@ -8089,7 +8005,7 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 121 */ +/* 119 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8248,10 +8164,10 @@ module.exports = { /***/ }), -/* 122 */ +/* 120 */ /***/ (function(module, exports, __webpack_require__) { -const conversions = __webpack_require__(120); +const conversions = __webpack_require__(118); /* This function routes a model to all other models. @@ -8351,14 +8267,14 @@ module.exports = function (fromModel) { /***/ }), -/* 123 */ +/* 121 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const os = __webpack_require__(124); -const tty = __webpack_require__(125); -const hasFlag = __webpack_require__(126); +const os = __webpack_require__(122); +const tty = __webpack_require__(123); +const hasFlag = __webpack_require__(124); const {env} = process; @@ -8497,19 +8413,19 @@ module.exports = { /***/ }), -/* 124 */ +/* 122 */ /***/ (function(module, exports) { module.exports = require("os"); /***/ }), -/* 125 */ +/* 123 */ /***/ (function(module, exports) { module.exports = require("tty"); /***/ }), -/* 126 */ +/* 124 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8524,7 +8440,7 @@ module.exports = (flag, argv = process.argv) => { /***/ }), -/* 127 */ +/* 125 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8570,7 +8486,7 @@ module.exports = { /***/ }), -/* 128 */ +/* 126 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8711,7 +8627,7 @@ module.exports = (chalk, temporary) => { /***/ }), -/* 129 */ +/* 127 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -8790,22 +8706,22 @@ function parseLogLevel(name) { } /***/ }), -/* 130 */ +/* 128 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var _interopRequireDefault = __webpack_require__(9); +var _interopRequireDefault = __webpack_require__(7); Object.defineProperty(exports, "__esModule", { value: true }); exports.ToolingLogCollectingWriter = void 0; -var _defineProperty2 = _interopRequireDefault(__webpack_require__(10)); +var _defineProperty2 = _interopRequireDefault(__webpack_require__(8)); -var _tooling_log_text_writer = __webpack_require__(114); +var _tooling_log_text_writer = __webpack_require__(112); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -8833,18 +8749,18 @@ class ToolingLogCollectingWriter extends _tooling_log_text_writer.ToolingLogText exports.ToolingLogCollectingWriter = ToolingLogCollectingWriter; /***/ }), -/* 131 */ +/* 129 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __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__(132); -/* harmony import */ var _build__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(521); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(522); -/* harmony import */ var _reset__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(546); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(547); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(549); +/* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(130); +/* harmony import */ var _build__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(519); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(520); +/* harmony import */ var _reset__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(544); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(545); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(547); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -8868,7 +8784,7 @@ const commands = { }; /***/ }), -/* 132 */ +/* 130 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -8876,16 +8792,16 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BootstrapCommand", function() { return BootstrapCommand; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(133); +/* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(131); /* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(222); -/* harmony import */ var _utils_child_process__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(223); -/* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(232); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(342); -/* harmony import */ var _utils_yarn_lock__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(410); -/* harmony import */ var _utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(413); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(415); -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; } +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(220); +/* harmony import */ var _utils_child_process__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(221); +/* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(230); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(340); +/* harmony import */ var _utils_yarn_lock__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(408); +/* harmony import */ var _utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(411); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(413); +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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -9022,34 +8938,34 @@ const BootstrapCommand = { }; /***/ }), -/* 133 */ +/* 131 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var _interopRequireDefault = __webpack_require__(9); +var _interopRequireDefault = __webpack_require__(7); Object.defineProperty(exports, "__esModule", { value: true }); exports.CiStatsReporter = void 0; -var _util = __webpack_require__(115); +var _util = __webpack_require__(113); -var _os = _interopRequireDefault(__webpack_require__(124)); +var _os = _interopRequireDefault(__webpack_require__(122)); -var _fs = _interopRequireDefault(__webpack_require__(134)); +var _fs = _interopRequireDefault(__webpack_require__(132)); var _path = _interopRequireDefault(__webpack_require__(4)); -var _crypto = _interopRequireDefault(__webpack_require__(135)); +var _crypto = _interopRequireDefault(__webpack_require__(133)); -var _execa = _interopRequireDefault(__webpack_require__(136)); +var _execa = _interopRequireDefault(__webpack_require__(134)); -var _axios = _interopRequireDefault(__webpack_require__(179)); +var _axios = _interopRequireDefault(__webpack_require__(177)); -var _ci_stats_config = __webpack_require__(220); +var _ci_stats_config = __webpack_require__(218); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -9180,7 +9096,7 @@ class CiStatsReporter { const { kibanaPackageJson - } = __webpack_require__(221)(hideFromWebpack.join('')); + } = __webpack_require__(219)(hideFromWebpack.join('')); return kibanaPackageJson.branch; } @@ -9197,7 +9113,7 @@ class CiStatsReporter { const { REPO_ROOT - } = __webpack_require__(221)(hideFromWebpack.join('')); + } = __webpack_require__(219)(hideFromWebpack.join('')); try { return _fs.default.readFileSync(_path.default.resolve(REPO_ROOT, 'data/uuid'), 'utf-8').trim(); @@ -9273,35 +9189,35 @@ class CiStatsReporter { exports.CiStatsReporter = CiStatsReporter; /***/ }), -/* 134 */ +/* 132 */ /***/ (function(module, exports) { module.exports = require("fs"); /***/ }), -/* 135 */ +/* 133 */ /***/ (function(module, exports) { module.exports = require("crypto"); /***/ }), -/* 136 */ +/* 134 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const childProcess = __webpack_require__(137); -const crossSpawn = __webpack_require__(138); -const stripFinalNewline = __webpack_require__(151); -const npmRunPath = __webpack_require__(152); -const onetime = __webpack_require__(154); -const makeError = __webpack_require__(156); -const normalizeStdio = __webpack_require__(161); -const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = __webpack_require__(162); -const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(167); -const {mergePromise, getSpawnedPromise} = __webpack_require__(177); -const {joinCommand, parseCommand} = __webpack_require__(178); +const childProcess = __webpack_require__(135); +const crossSpawn = __webpack_require__(136); +const stripFinalNewline = __webpack_require__(149); +const npmRunPath = __webpack_require__(150); +const onetime = __webpack_require__(152); +const makeError = __webpack_require__(154); +const normalizeStdio = __webpack_require__(159); +const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = __webpack_require__(160); +const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(165); +const {mergePromise, getSpawnedPromise} = __webpack_require__(175); +const {joinCommand, parseCommand} = __webpack_require__(176); const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; @@ -9548,21 +9464,21 @@ module.exports.node = (scriptPath, args, options = {}) => { /***/ }), -/* 137 */ +/* 135 */ /***/ (function(module, exports) { module.exports = require("child_process"); /***/ }), -/* 138 */ +/* 136 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const cp = __webpack_require__(137); -const parse = __webpack_require__(139); -const enoent = __webpack_require__(150); +const cp = __webpack_require__(135); +const parse = __webpack_require__(137); +const enoent = __webpack_require__(148); function spawn(command, args, options) { // Parse the arguments @@ -9600,16 +9516,16 @@ module.exports._enoent = enoent; /***/ }), -/* 139 */ +/* 137 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const resolveCommand = __webpack_require__(140); -const escape = __webpack_require__(146); -const readShebang = __webpack_require__(147); +const resolveCommand = __webpack_require__(138); +const escape = __webpack_require__(144); +const readShebang = __webpack_require__(145); const isWin = process.platform === 'win32'; const isExecutableRegExp = /\.(?:com|exe)$/i; @@ -9698,15 +9614,15 @@ module.exports = parse; /***/ }), -/* 140 */ +/* 138 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const which = __webpack_require__(141); -const getPathKey = __webpack_require__(145); +const which = __webpack_require__(139); +const getPathKey = __webpack_require__(143); function resolveCommandAttempt(parsed, withoutPathExt) { const env = parsed.options.env || process.env; @@ -9757,7 +9673,7 @@ module.exports = resolveCommand; /***/ }), -/* 141 */ +/* 139 */ /***/ (function(module, exports, __webpack_require__) { const isWindows = process.platform === 'win32' || @@ -9766,7 +9682,7 @@ const isWindows = process.platform === 'win32' || const path = __webpack_require__(4) const COLON = isWindows ? ';' : ':' -const isexe = __webpack_require__(142) +const isexe = __webpack_require__(140) const getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) @@ -9888,15 +9804,15 @@ which.sync = whichSync /***/ }), -/* 142 */ +/* 140 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(134) +var fs = __webpack_require__(132) var core if (process.platform === 'win32' || global.TESTING_WINDOWS) { - core = __webpack_require__(143) + core = __webpack_require__(141) } else { - core = __webpack_require__(144) + core = __webpack_require__(142) } module.exports = isexe @@ -9951,13 +9867,13 @@ function sync (path, options) { /***/ }), -/* 143 */ +/* 141 */ /***/ (function(module, exports, __webpack_require__) { module.exports = isexe isexe.sync = sync -var fs = __webpack_require__(134) +var fs = __webpack_require__(132) function checkPathExt (path, options) { var pathext = options.pathExt !== undefined ? @@ -9999,13 +9915,13 @@ function sync (path, options) { /***/ }), -/* 144 */ +/* 142 */ /***/ (function(module, exports, __webpack_require__) { module.exports = isexe isexe.sync = sync -var fs = __webpack_require__(134) +var fs = __webpack_require__(132) function isexe (path, options, cb) { fs.stat(path, function (er, stat) { @@ -10046,7 +9962,7 @@ function checkMode (stat, options) { /***/ }), -/* 145 */ +/* 143 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10069,7 +9985,7 @@ module.exports.default = pathKey; /***/ }), -/* 146 */ +/* 144 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10121,14 +10037,14 @@ module.exports.argument = escapeArgument; /***/ }), -/* 147 */ +/* 145 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); -const shebangCommand = __webpack_require__(148); +const fs = __webpack_require__(132); +const shebangCommand = __webpack_require__(146); function readShebang(command) { // Read the first 150 bytes from the file @@ -10151,12 +10067,12 @@ module.exports = readShebang; /***/ }), -/* 148 */ +/* 146 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const shebangRegex = __webpack_require__(149); +const shebangRegex = __webpack_require__(147); module.exports = (string = '') => { const match = string.match(shebangRegex); @@ -10177,7 +10093,7 @@ module.exports = (string = '') => { /***/ }), -/* 149 */ +/* 147 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10186,7 +10102,7 @@ module.exports = /^#!(.*)/; /***/ }), -/* 150 */ +/* 148 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10252,7 +10168,7 @@ module.exports = { /***/ }), -/* 151 */ +/* 149 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10275,13 +10191,13 @@ module.exports = input => { /***/ }), -/* 152 */ +/* 150 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const pathKey = __webpack_require__(153); +const pathKey = __webpack_require__(151); const npmRunPath = options => { options = { @@ -10329,7 +10245,7 @@ module.exports.env = options => { /***/ }), -/* 153 */ +/* 151 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10352,12 +10268,12 @@ module.exports.default = pathKey; /***/ }), -/* 154 */ +/* 152 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(155); +const mimicFn = __webpack_require__(153); const calledFunctions = new WeakMap(); @@ -10409,7 +10325,7 @@ module.exports.callCount = fn => { /***/ }), -/* 155 */ +/* 153 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10429,12 +10345,12 @@ module.exports.default = mimicFn; /***/ }), -/* 156 */ +/* 154 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {signalsByName} = __webpack_require__(157); +const {signalsByName} = __webpack_require__(155); const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { if (timedOut) { @@ -10522,14 +10438,14 @@ module.exports = makeError; /***/ }), -/* 157 */ +/* 155 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -Object.defineProperty(exports,"__esModule",{value:true});exports.signalsByNumber=exports.signalsByName=void 0;var _os=__webpack_require__(124); +Object.defineProperty(exports,"__esModule",{value:true});exports.signalsByNumber=exports.signalsByName=void 0;var _os=__webpack_require__(122); -var _signals=__webpack_require__(158); -var _realtime=__webpack_require__(160); +var _signals=__webpack_require__(156); +var _realtime=__webpack_require__(158); @@ -10599,14 +10515,14 @@ const signalsByNumber=getSignalsByNumber();exports.signalsByNumber=signalsByNumb //# sourceMappingURL=main.js.map /***/ }), -/* 158 */ +/* 156 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -Object.defineProperty(exports,"__esModule",{value:true});exports.getSignals=void 0;var _os=__webpack_require__(124); +Object.defineProperty(exports,"__esModule",{value:true});exports.getSignals=void 0;var _os=__webpack_require__(122); -var _core=__webpack_require__(159); -var _realtime=__webpack_require__(160); +var _core=__webpack_require__(157); +var _realtime=__webpack_require__(158); @@ -10640,7 +10556,7 @@ return{name,number,description,supported,action,forced,standard}; //# sourceMappingURL=signals.js.map /***/ }), -/* 159 */ +/* 157 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10919,7 +10835,7 @@ standard:"other"}];exports.SIGNALS=SIGNALS; //# sourceMappingURL=core.js.map /***/ }), -/* 160 */ +/* 158 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -10944,7 +10860,7 @@ const SIGRTMAX=64;exports.SIGRTMAX=SIGRTMAX; //# sourceMappingURL=realtime.js.map /***/ }), -/* 161 */ +/* 159 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -11003,13 +10919,13 @@ module.exports.node = opts => { /***/ }), -/* 162 */ +/* 160 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const os = __webpack_require__(124); -const onExit = __webpack_require__(163); +const os = __webpack_require__(122); +const onExit = __webpack_require__(161); const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5; @@ -11122,16 +11038,16 @@ module.exports = { /***/ }), -/* 163 */ +/* 161 */ /***/ (function(module, exports, __webpack_require__) { // Note: since nyc uses this module to output coverage, any lines // that are in the direct sync flow of nyc's outputCoverage are // ignored, since we can never get coverage for them. -var assert = __webpack_require__(164) -var signals = __webpack_require__(165) +var assert = __webpack_require__(162) +var signals = __webpack_require__(163) -var EE = __webpack_require__(166) +var EE = __webpack_require__(164) /* istanbul ignore if */ if (typeof EE !== 'function') { EE = EE.EventEmitter @@ -11285,13 +11201,13 @@ function processEmit (ev, arg) { /***/ }), -/* 164 */ +/* 162 */ /***/ (function(module, exports) { module.exports = require("assert"); /***/ }), -/* 165 */ +/* 163 */ /***/ (function(module, exports) { // This is not the set of all possible signals. @@ -11350,20 +11266,20 @@ if (process.platform === 'linux') { /***/ }), -/* 166 */ +/* 164 */ /***/ (function(module, exports) { module.exports = require("events"); /***/ }), -/* 167 */ +/* 165 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const isStream = __webpack_require__(168); -const getStream = __webpack_require__(169); -const mergeStream = __webpack_require__(176); +const isStream = __webpack_require__(166); +const getStream = __webpack_require__(167); +const mergeStream = __webpack_require__(174); // `input` option const handleInput = (spawned, input) => { @@ -11460,7 +11376,7 @@ module.exports = { /***/ }), -/* 168 */ +/* 166 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -11496,13 +11412,13 @@ module.exports = isStream; /***/ }), -/* 169 */ +/* 167 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pump = __webpack_require__(170); -const bufferStream = __webpack_require__(174); +const pump = __webpack_require__(168); +const bufferStream = __webpack_require__(172); class MaxBufferError extends Error { constructor() { @@ -11561,12 +11477,12 @@ module.exports.MaxBufferError = MaxBufferError; /***/ }), -/* 170 */ +/* 168 */ /***/ (function(module, exports, __webpack_require__) { -var once = __webpack_require__(171) -var eos = __webpack_require__(173) -var fs = __webpack_require__(134) // we only need fs to get the ReadStream and WriteStream prototypes +var once = __webpack_require__(169) +var eos = __webpack_require__(171) +var fs = __webpack_require__(132) // we only need fs to get the ReadStream and WriteStream prototypes var noop = function () {} var ancient = /^v?\.0/.test(process.version) @@ -11649,10 +11565,10 @@ module.exports = pump /***/ }), -/* 171 */ +/* 169 */ /***/ (function(module, exports, __webpack_require__) { -var wrappy = __webpack_require__(172) +var wrappy = __webpack_require__(170) module.exports = wrappy(once) module.exports.strict = wrappy(onceStrict) @@ -11697,7 +11613,7 @@ function onceStrict (fn) { /***/ }), -/* 172 */ +/* 170 */ /***/ (function(module, exports) { // Returns a wrapper function that returns a wrapped callback @@ -11736,10 +11652,10 @@ function wrappy (fn, cb) { /***/ }), -/* 173 */ +/* 171 */ /***/ (function(module, exports, __webpack_require__) { -var once = __webpack_require__(171); +var once = __webpack_require__(169); var noop = function() {}; @@ -11836,12 +11752,12 @@ module.exports = eos; /***/ }), -/* 174 */ +/* 172 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {PassThrough: PassThroughStream} = __webpack_require__(175); +const {PassThrough: PassThroughStream} = __webpack_require__(173); module.exports = options => { options = {...options}; @@ -11895,19 +11811,19 @@ module.exports = options => { /***/ }), -/* 175 */ +/* 173 */ /***/ (function(module, exports) { module.exports = require("stream"); /***/ }), -/* 176 */ +/* 174 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const { PassThrough } = __webpack_require__(175); +const { PassThrough } = __webpack_require__(173); module.exports = function (/*streams...*/) { var sources = [] @@ -11949,7 +11865,7 @@ module.exports = function (/*streams...*/) { /***/ }), -/* 177 */ +/* 175 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -12002,7 +11918,7 @@ module.exports = { /***/ }), -/* 178 */ +/* 176 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -12047,23 +11963,23 @@ module.exports = { /***/ }), -/* 179 */ +/* 177 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = __webpack_require__(180); +module.exports = __webpack_require__(178); /***/ }), -/* 180 */ +/* 178 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); -var bind = __webpack_require__(182); -var Axios = __webpack_require__(183); -var mergeConfig = __webpack_require__(215); -var defaults = __webpack_require__(189); +var utils = __webpack_require__(179); +var bind = __webpack_require__(180); +var Axios = __webpack_require__(181); +var mergeConfig = __webpack_require__(213); +var defaults = __webpack_require__(187); /** * Create an instance of Axios @@ -12096,18 +12012,18 @@ axios.create = function create(instanceConfig) { }; // Expose Cancel & CancelToken -axios.Cancel = __webpack_require__(216); -axios.CancelToken = __webpack_require__(217); -axios.isCancel = __webpack_require__(188); +axios.Cancel = __webpack_require__(214); +axios.CancelToken = __webpack_require__(215); +axios.isCancel = __webpack_require__(186); // Expose all/spread axios.all = function all(promises) { return Promise.all(promises); }; -axios.spread = __webpack_require__(218); +axios.spread = __webpack_require__(216); // Expose isAxiosError -axios.isAxiosError = __webpack_require__(219); +axios.isAxiosError = __webpack_require__(217); module.exports = axios; @@ -12116,13 +12032,13 @@ module.exports.default = axios; /***/ }), -/* 181 */ +/* 179 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var bind = __webpack_require__(182); +var bind = __webpack_require__(180); /*global toString:true*/ @@ -12474,7 +12390,7 @@ module.exports = { /***/ }), -/* 182 */ +/* 180 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -12492,17 +12408,17 @@ module.exports = function bind(fn, thisArg) { /***/ }), -/* 183 */ +/* 181 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); -var buildURL = __webpack_require__(184); -var InterceptorManager = __webpack_require__(185); -var dispatchRequest = __webpack_require__(186); -var mergeConfig = __webpack_require__(215); +var utils = __webpack_require__(179); +var buildURL = __webpack_require__(182); +var InterceptorManager = __webpack_require__(183); +var dispatchRequest = __webpack_require__(184); +var mergeConfig = __webpack_require__(213); /** * Create a new instance of Axios @@ -12594,13 +12510,13 @@ module.exports = Axios; /***/ }), -/* 184 */ +/* 182 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); +var utils = __webpack_require__(179); function encode(val) { return encodeURIComponent(val). @@ -12671,13 +12587,13 @@ module.exports = function buildURL(url, params, paramsSerializer) { /***/ }), -/* 185 */ +/* 183 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); +var utils = __webpack_require__(179); function InterceptorManager() { this.handlers = []; @@ -12730,16 +12646,16 @@ module.exports = InterceptorManager; /***/ }), -/* 186 */ +/* 184 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); -var transformData = __webpack_require__(187); -var isCancel = __webpack_require__(188); -var defaults = __webpack_require__(189); +var utils = __webpack_require__(179); +var transformData = __webpack_require__(185); +var isCancel = __webpack_require__(186); +var defaults = __webpack_require__(187); /** * Throws a `Cancel` if cancellation has been requested. @@ -12816,13 +12732,13 @@ module.exports = function dispatchRequest(config) { /***/ }), -/* 187 */ +/* 185 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); +var utils = __webpack_require__(179); /** * Transform the data for a request or a response @@ -12843,7 +12759,7 @@ module.exports = function transformData(data, headers, fns) { /***/ }), -/* 188 */ +/* 186 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -12855,14 +12771,14 @@ module.exports = function isCancel(value) { /***/ }), -/* 189 */ +/* 187 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); -var normalizeHeaderName = __webpack_require__(190); +var utils = __webpack_require__(179); +var normalizeHeaderName = __webpack_require__(188); var DEFAULT_CONTENT_TYPE = { 'Content-Type': 'application/x-www-form-urlencoded' @@ -12878,10 +12794,10 @@ function getDefaultAdapter() { var adapter; if (typeof XMLHttpRequest !== 'undefined') { // For browsers use XHR adapter - adapter = __webpack_require__(191); + adapter = __webpack_require__(189); } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') { // For node use HTTP adapter - adapter = __webpack_require__(201); + adapter = __webpack_require__(199); } return adapter; } @@ -12960,13 +12876,13 @@ module.exports = defaults; /***/ }), -/* 190 */ +/* 188 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); +var utils = __webpack_require__(179); module.exports = function normalizeHeaderName(headers, normalizedName) { utils.forEach(headers, function processHeader(value, name) { @@ -12979,20 +12895,20 @@ module.exports = function normalizeHeaderName(headers, normalizedName) { /***/ }), -/* 191 */ +/* 189 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); -var settle = __webpack_require__(192); -var cookies = __webpack_require__(195); -var buildURL = __webpack_require__(184); -var buildFullPath = __webpack_require__(196); -var parseHeaders = __webpack_require__(199); -var isURLSameOrigin = __webpack_require__(200); -var createError = __webpack_require__(193); +var utils = __webpack_require__(179); +var settle = __webpack_require__(190); +var cookies = __webpack_require__(193); +var buildURL = __webpack_require__(182); +var buildFullPath = __webpack_require__(194); +var parseHeaders = __webpack_require__(197); +var isURLSameOrigin = __webpack_require__(198); +var createError = __webpack_require__(191); module.exports = function xhrAdapter(config) { return new Promise(function dispatchXhrRequest(resolve, reject) { @@ -13165,13 +13081,13 @@ module.exports = function xhrAdapter(config) { /***/ }), -/* 192 */ +/* 190 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var createError = __webpack_require__(193); +var createError = __webpack_require__(191); /** * Resolve or reject a Promise based on response status. @@ -13197,13 +13113,13 @@ module.exports = function settle(resolve, reject, response) { /***/ }), -/* 193 */ +/* 191 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var enhanceError = __webpack_require__(194); +var enhanceError = __webpack_require__(192); /** * Create an Error with the specified message, config, error code, request and response. @@ -13222,7 +13138,7 @@ module.exports = function createError(message, config, code, request, response) /***/ }), -/* 194 */ +/* 192 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -13271,13 +13187,13 @@ module.exports = function enhanceError(error, config, code, request, response) { /***/ }), -/* 195 */ +/* 193 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); +var utils = __webpack_require__(179); module.exports = ( utils.isStandardBrowserEnv() ? @@ -13331,14 +13247,14 @@ module.exports = ( /***/ }), -/* 196 */ +/* 194 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isAbsoluteURL = __webpack_require__(197); -var combineURLs = __webpack_require__(198); +var isAbsoluteURL = __webpack_require__(195); +var combineURLs = __webpack_require__(196); /** * Creates a new URL by combining the baseURL with the requestedURL, @@ -13358,7 +13274,7 @@ module.exports = function buildFullPath(baseURL, requestedURL) { /***/ }), -/* 197 */ +/* 195 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -13379,7 +13295,7 @@ module.exports = function isAbsoluteURL(url) { /***/ }), -/* 198 */ +/* 196 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -13400,13 +13316,13 @@ module.exports = function combineURLs(baseURL, relativeURL) { /***/ }), -/* 199 */ +/* 197 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); +var utils = __webpack_require__(179); // Headers whose duplicates are ignored by node // c.f. https://nodejs.org/api/http.html#http_message_headers @@ -13460,13 +13376,13 @@ module.exports = function parseHeaders(headers) { /***/ }), -/* 200 */ +/* 198 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); +var utils = __webpack_require__(179); module.exports = ( utils.isStandardBrowserEnv() ? @@ -13535,25 +13451,25 @@ module.exports = ( /***/ }), -/* 201 */ +/* 199 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); -var settle = __webpack_require__(192); -var buildFullPath = __webpack_require__(196); -var buildURL = __webpack_require__(184); -var http = __webpack_require__(202); -var https = __webpack_require__(203); -var httpFollow = __webpack_require__(204).http; -var httpsFollow = __webpack_require__(204).https; -var url = __webpack_require__(205); -var zlib = __webpack_require__(213); -var pkg = __webpack_require__(214); -var createError = __webpack_require__(193); -var enhanceError = __webpack_require__(194); +var utils = __webpack_require__(179); +var settle = __webpack_require__(190); +var buildFullPath = __webpack_require__(194); +var buildURL = __webpack_require__(182); +var http = __webpack_require__(200); +var https = __webpack_require__(201); +var httpFollow = __webpack_require__(202).http; +var httpsFollow = __webpack_require__(202).https; +var url = __webpack_require__(203); +var zlib = __webpack_require__(211); +var pkg = __webpack_require__(212); +var createError = __webpack_require__(191); +var enhanceError = __webpack_require__(192); var isHttps = /https:?/; @@ -13845,28 +13761,28 @@ module.exports = function httpAdapter(config) { /***/ }), -/* 202 */ +/* 200 */ /***/ (function(module, exports) { module.exports = require("http"); /***/ }), -/* 203 */ +/* 201 */ /***/ (function(module, exports) { module.exports = require("https"); /***/ }), -/* 204 */ +/* 202 */ /***/ (function(module, exports, __webpack_require__) { -var url = __webpack_require__(205); +var url = __webpack_require__(203); var URL = url.URL; -var http = __webpack_require__(202); -var https = __webpack_require__(203); -var Writable = __webpack_require__(175).Writable; -var assert = __webpack_require__(164); -var debug = __webpack_require__(206); +var http = __webpack_require__(200); +var https = __webpack_require__(201); +var Writable = __webpack_require__(173).Writable; +var assert = __webpack_require__(162); +var debug = __webpack_require__(204); // Create handlers that pass events from native requests var eventHandlers = Object.create(null); @@ -14361,19 +14277,19 @@ module.exports.wrap = wrap; /***/ }), -/* 205 */ +/* 203 */ /***/ (function(module, exports) { module.exports = require("url"); /***/ }), -/* 206 */ +/* 204 */ /***/ (function(module, exports, __webpack_require__) { var debug; try { /* eslint global-require: off */ - debug = __webpack_require__(207)("follow-redirects"); + debug = __webpack_require__(205)("follow-redirects"); } catch (error) { debug = function () { /* */ }; @@ -14382,7 +14298,7 @@ module.exports = debug; /***/ }), -/* 207 */ +/* 205 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -14391,14 +14307,14 @@ module.exports = debug; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(208); + module.exports = __webpack_require__(206); } else { - module.exports = __webpack_require__(211); + module.exports = __webpack_require__(209); } /***/ }), -/* 208 */ +/* 206 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -14407,7 +14323,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(209); +exports = module.exports = __webpack_require__(207); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -14589,7 +14505,7 @@ function localstorage() { /***/ }), -/* 209 */ +/* 207 */ /***/ (function(module, exports, __webpack_require__) { @@ -14605,7 +14521,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(210); +exports.humanize = __webpack_require__(208); /** * The currently active debug mode names, and names to skip. @@ -14797,7 +14713,7 @@ function coerce(val) { /***/ }), -/* 210 */ +/* 208 */ /***/ (function(module, exports) { /** @@ -14955,15 +14871,15 @@ function plural(ms, n, name) { /***/ }), -/* 211 */ +/* 209 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(125); -var util = __webpack_require__(115); +var tty = __webpack_require__(123); +var util = __webpack_require__(113); /** * This is the Node.js implementation of `debug()`. @@ -14971,7 +14887,7 @@ var util = __webpack_require__(115); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(209); +exports = module.exports = __webpack_require__(207); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -15143,14 +15059,14 @@ function createWritableStdioStream (fd) { break; case 'FILE': - var fs = __webpack_require__(134); + var fs = __webpack_require__(132); stream = new fs.SyncWriteStream(fd, { autoClose: false }); stream._type = 'fs'; break; case 'PIPE': case 'TCP': - var net = __webpack_require__(212); + var net = __webpack_require__(210); stream = new net.Socket({ fd: fd, readable: false, @@ -15209,31 +15125,31 @@ exports.enable(load()); /***/ }), -/* 212 */ +/* 210 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 213 */ +/* 211 */ /***/ (function(module, exports) { module.exports = require("zlib"); /***/ }), -/* 214 */ +/* 212 */ /***/ (function(module) { module.exports = JSON.parse("{\"name\":\"axios\",\"version\":\"0.21.1\",\"description\":\"Promise based HTTP client for the browser and node.js\",\"main\":\"index.js\",\"scripts\":{\"test\":\"grunt test && bundlesize\",\"start\":\"node ./sandbox/server.js\",\"build\":\"NODE_ENV=production grunt build\",\"preversion\":\"npm test\",\"version\":\"npm run build && grunt version && git add -A dist && git add CHANGELOG.md bower.json package.json\",\"postversion\":\"git push && git push --tags\",\"examples\":\"node ./examples/server.js\",\"coveralls\":\"cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js\",\"fix\":\"eslint --fix lib/**/*.js\"},\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/axios/axios.git\"},\"keywords\":[\"xhr\",\"http\",\"ajax\",\"promise\",\"node\"],\"author\":\"Matt Zabriskie\",\"license\":\"MIT\",\"bugs\":{\"url\":\"https://github.com/axios/axios/issues\"},\"homepage\":\"https://github.com/axios/axios\",\"devDependencies\":{\"bundlesize\":\"^0.17.0\",\"coveralls\":\"^3.0.0\",\"es6-promise\":\"^4.2.4\",\"grunt\":\"^1.0.2\",\"grunt-banner\":\"^0.6.0\",\"grunt-cli\":\"^1.2.0\",\"grunt-contrib-clean\":\"^1.1.0\",\"grunt-contrib-watch\":\"^1.0.0\",\"grunt-eslint\":\"^20.1.0\",\"grunt-karma\":\"^2.0.0\",\"grunt-mocha-test\":\"^0.13.3\",\"grunt-ts\":\"^6.0.0-beta.19\",\"grunt-webpack\":\"^1.0.18\",\"istanbul-instrumenter-loader\":\"^1.0.0\",\"jasmine-core\":\"^2.4.1\",\"karma\":\"^1.3.0\",\"karma-chrome-launcher\":\"^2.2.0\",\"karma-coverage\":\"^1.1.1\",\"karma-firefox-launcher\":\"^1.1.0\",\"karma-jasmine\":\"^1.1.1\",\"karma-jasmine-ajax\":\"^0.1.13\",\"karma-opera-launcher\":\"^1.0.0\",\"karma-safari-launcher\":\"^1.0.0\",\"karma-sauce-launcher\":\"^1.2.0\",\"karma-sinon\":\"^1.0.5\",\"karma-sourcemap-loader\":\"^0.3.7\",\"karma-webpack\":\"^1.7.0\",\"load-grunt-tasks\":\"^3.5.2\",\"minimist\":\"^1.2.0\",\"mocha\":\"^5.2.0\",\"sinon\":\"^4.5.0\",\"typescript\":\"^2.8.1\",\"url-search-params\":\"^0.10.0\",\"webpack\":\"^1.13.1\",\"webpack-dev-server\":\"^1.14.1\"},\"browser\":{\"./lib/adapters/http.js\":\"./lib/adapters/xhr.js\"},\"jsdelivr\":\"dist/axios.min.js\",\"unpkg\":\"dist/axios.min.js\",\"typings\":\"./index.d.ts\",\"dependencies\":{\"follow-redirects\":\"^1.10.0\"},\"bundlesize\":[{\"path\":\"./dist/axios.min.js\",\"threshold\":\"5kB\"}]}"); /***/ }), -/* 215 */ +/* 213 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(181); +var utils = __webpack_require__(179); /** * Config-specific merge-function which creates a new config-object @@ -15321,7 +15237,7 @@ module.exports = function mergeConfig(config1, config2) { /***/ }), -/* 216 */ +/* 214 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15347,13 +15263,13 @@ module.exports = Cancel; /***/ }), -/* 217 */ +/* 215 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Cancel = __webpack_require__(216); +var Cancel = __webpack_require__(214); /** * A `CancelToken` is an object that can be used to request cancellation of an operation. @@ -15411,7 +15327,7 @@ module.exports = CancelToken; /***/ }), -/* 218 */ +/* 216 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15445,7 +15361,7 @@ module.exports = function spread(callback) { /***/ }), -/* 219 */ +/* 217 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15463,7 +15379,7 @@ module.exports = function isAxiosError(payload) { /***/ }), -/* 220 */ +/* 218 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15523,7 +15439,7 @@ function parseConfig(log) { } /***/ }), -/* 221 */ +/* 219 */ /***/ (function(module, exports) { function webpackEmptyContext(req) { @@ -15534,10 +15450,10 @@ function webpackEmptyContext(req) { webpackEmptyContext.keys = function() { return []; }; webpackEmptyContext.resolve = webpackEmptyContext; module.exports = webpackEmptyContext; -webpackEmptyContext.id = 221; +webpackEmptyContext.id = 219; /***/ }), -/* 222 */ +/* 220 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -15586,23 +15502,23 @@ const log = new Log(); /***/ }), -/* 223 */ +/* 221 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "spawn", function() { return spawn; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "spawnStreaming", function() { return spawnStreaming; }); -/* harmony import */ var stream__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(175); +/* harmony import */ var stream__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(173); /* harmony import */ var stream__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(stream__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(116); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(114); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(136); +/* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(134); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(224); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(222); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(222); -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; } +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(220); +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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -15676,7 +15592,7 @@ function spawnStreaming(command, args, opts, { } /***/ }), -/* 224 */ +/* 222 */ /***/ (function(module, exports, __webpack_require__) { // Copyright IBM Corp. 2014,2018. All Rights Reserved. @@ -15684,12 +15600,12 @@ function spawnStreaming(command, args, opts, { // 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__(225); -module.exports.cli = __webpack_require__(229); +module.exports = __webpack_require__(223); +module.exports.cli = __webpack_require__(227); /***/ }), -/* 225 */ +/* 223 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -15700,13 +15616,13 @@ module.exports.cli = __webpack_require__(229); -var stream = __webpack_require__(175); -var util = __webpack_require__(115); -var fs = __webpack_require__(134); +var stream = __webpack_require__(173); +var util = __webpack_require__(113); +var fs = __webpack_require__(132); -var through = __webpack_require__(226); -var duplexer = __webpack_require__(227); -var StringDecoder = __webpack_require__(228).StringDecoder; +var through = __webpack_require__(224); +var duplexer = __webpack_require__(225); +var StringDecoder = __webpack_require__(226).StringDecoder; module.exports = Logger; @@ -15895,10 +15811,10 @@ function lineMerger(host) { /***/ }), -/* 226 */ +/* 224 */ /***/ (function(module, exports, __webpack_require__) { -var Stream = __webpack_require__(175) +var Stream = __webpack_require__(173) // through // @@ -16009,10 +15925,10 @@ function through (write, end, opts) { /***/ }), -/* 227 */ +/* 225 */ /***/ (function(module, exports, __webpack_require__) { -var Stream = __webpack_require__(175) +var Stream = __webpack_require__(173) var writeMethods = ["write", "end", "destroy"] var readMethods = ["resume", "pause"] var readEvents = ["data", "close"] @@ -16102,13 +16018,13 @@ function duplex(writer, reader) { /***/ }), -/* 228 */ +/* 226 */ /***/ (function(module, exports) { module.exports = require("string_decoder"); /***/ }), -/* 229 */ +/* 227 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -16119,11 +16035,11 @@ module.exports = require("string_decoder"); -var minimist = __webpack_require__(230); +var minimist = __webpack_require__(228); var path = __webpack_require__(4); -var Logger = __webpack_require__(225); -var pkg = __webpack_require__(231); +var Logger = __webpack_require__(223); +var pkg = __webpack_require__(229); module.exports = cli; @@ -16177,7 +16093,7 @@ function usage($0, p) { /***/ }), -/* 230 */ +/* 228 */ /***/ (function(module, exports) { module.exports = function (args, opts) { @@ -16428,13 +16344,13 @@ function isNumber (x) { /***/ }), -/* 231 */ +/* 229 */ /***/ (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\"}}"); /***/ }), -/* 232 */ +/* 230 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -16442,8 +16358,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "linkProjectExecutables", function() { return linkProjectExecutables; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(222); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(231); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(220); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -16509,7 +16425,7 @@ async function linkProjectExecutables(projectsByName, projectGraph) { } /***/ }), -/* 233 */ +/* 231 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -16526,17 +16442,17 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isFile", function() { return isFile; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createSymlink", function() { return createSymlink; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tryRealpath", function() { return tryRealpath; }); -/* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(234); +/* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(232); /* harmony import */ var cmd_shim__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cmd_shim__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(134); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(132); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(341); +/* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(339); /* harmony import */ var ncp__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ncp__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_4__); -/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(115); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(113); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_5__); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -16657,7 +16573,7 @@ async function tryRealpath(path) { } /***/ }), -/* 234 */ +/* 232 */ /***/ (function(module, exports, __webpack_require__) { // On windows, create a .cmd file. @@ -16673,11 +16589,11 @@ async function tryRealpath(path) { module.exports = cmdShim cmdShim.ifExists = cmdShimIfExists -var fs = __webpack_require__(235) +var fs = __webpack_require__(233) -var mkdir = __webpack_require__(240) +var mkdir = __webpack_require__(238) , path = __webpack_require__(4) - , toBatchSyntax = __webpack_require__(241) + , toBatchSyntax = __webpack_require__(239) , shebangExpr = /^#\!\s*(?:\/usr\/bin\/env)?\s*([^ \t]+=[^ \t]+\s+)*\s*([^ \t]+)(.*)$/ function cmdShimIfExists (from, to, cb) { @@ -16910,15 +16826,15 @@ function times(n, ok, cb) { /***/ }), -/* 235 */ +/* 233 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(134) -var polyfills = __webpack_require__(236) -var legacy = __webpack_require__(238) -var clone = __webpack_require__(239) +var fs = __webpack_require__(132) +var polyfills = __webpack_require__(234) +var legacy = __webpack_require__(236) +var clone = __webpack_require__(237) -var util = __webpack_require__(115) +var util = __webpack_require__(113) /* istanbul ignore next - node 0.x polyfill */ var gracefulQueue @@ -16999,7 +16915,7 @@ if (!fs[gracefulQueue]) { if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { process.on('exit', function() { debug(fs[gracefulQueue]) - __webpack_require__(164).equal(fs[gracefulQueue].length, 0) + __webpack_require__(162).equal(fs[gracefulQueue].length, 0) }) } } @@ -17270,10 +17186,10 @@ function retry () { /***/ }), -/* 236 */ +/* 234 */ /***/ (function(module, exports, __webpack_require__) { -var constants = __webpack_require__(237) +var constants = __webpack_require__(235) var origCwd = process.cwd var cwd = null @@ -17618,16 +17534,16 @@ function patch (fs) { /***/ }), -/* 237 */ +/* 235 */ /***/ (function(module, exports) { module.exports = require("constants"); /***/ }), -/* 238 */ +/* 236 */ /***/ (function(module, exports, __webpack_require__) { -var Stream = __webpack_require__(175).Stream +var Stream = __webpack_require__(173).Stream module.exports = legacy @@ -17748,7 +17664,7 @@ function legacy (fs) { /***/ }), -/* 239 */ +/* 237 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -17774,11 +17690,11 @@ function clone (obj) { /***/ }), -/* 240 */ +/* 238 */ /***/ (function(module, exports, __webpack_require__) { var path = __webpack_require__(4); -var fs = __webpack_require__(134); +var fs = __webpack_require__(132); var _0777 = parseInt('0777', 8); module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; @@ -17879,7 +17795,7 @@ mkdirP.sync = function sync (p, opts, made) { /***/ }), -/* 241 */ +/* 239 */ /***/ (function(module, exports) { exports.replaceDollarWithPercentPair = replaceDollarWithPercentPair @@ -17937,21 +17853,21 @@ function replaceDollarWithPercentPair(value) { /***/ }), -/* 242 */ +/* 240 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {promisify} = __webpack_require__(115); +const {promisify} = __webpack_require__(113); const path = __webpack_require__(4); -const globby = __webpack_require__(243); -const isGlob = __webpack_require__(268); -const slash = __webpack_require__(332); -const gracefulFs = __webpack_require__(235); -const isPathCwd = __webpack_require__(334); -const isPathInside = __webpack_require__(335); -const rimraf = __webpack_require__(336); -const pMap = __webpack_require__(337); +const globby = __webpack_require__(241); +const isGlob = __webpack_require__(266); +const slash = __webpack_require__(330); +const gracefulFs = __webpack_require__(233); +const isPathCwd = __webpack_require__(332); +const isPathInside = __webpack_require__(333); +const rimraf = __webpack_require__(334); +const pMap = __webpack_require__(335); const rimrafP = promisify(rimraf); @@ -18065,19 +17981,19 @@ module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options /***/ }), -/* 243 */ +/* 241 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); -const arrayUnion = __webpack_require__(244); -const merge2 = __webpack_require__(245); -const glob = __webpack_require__(246); -const fastGlob = __webpack_require__(259); -const dirGlob = __webpack_require__(328); -const gitignore = __webpack_require__(330); -const {FilterStream, UniqueStream} = __webpack_require__(333); +const fs = __webpack_require__(132); +const arrayUnion = __webpack_require__(242); +const merge2 = __webpack_require__(243); +const glob = __webpack_require__(244); +const fastGlob = __webpack_require__(257); +const dirGlob = __webpack_require__(326); +const gitignore = __webpack_require__(328); +const {FilterStream, UniqueStream} = __webpack_require__(331); const DEFAULT_FILTER = () => false; @@ -18250,7 +18166,7 @@ module.exports.gitignore = gitignore; /***/ }), -/* 244 */ +/* 242 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -18262,7 +18178,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 245 */ +/* 243 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -18274,7 +18190,7 @@ module.exports = (...arguments_) => { * Copyright (c) 2014-2020 Teambition * Licensed under the MIT license. */ -const Stream = __webpack_require__(175) +const Stream = __webpack_require__(173) const PassThrough = Stream.PassThrough const slice = Array.prototype.slice @@ -18413,7 +18329,7 @@ function pauseStreams (streams, options) { /***/ }), -/* 246 */ +/* 244 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -18458,27 +18374,27 @@ function pauseStreams (streams, options) { module.exports = glob -var fs = __webpack_require__(134) -var rp = __webpack_require__(247) -var minimatch = __webpack_require__(249) +var fs = __webpack_require__(132) +var rp = __webpack_require__(245) +var minimatch = __webpack_require__(247) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(253) -var EE = __webpack_require__(166).EventEmitter +var inherits = __webpack_require__(251) +var EE = __webpack_require__(164).EventEmitter var path = __webpack_require__(4) -var assert = __webpack_require__(164) -var isAbsolute = __webpack_require__(255) -var globSync = __webpack_require__(256) -var common = __webpack_require__(257) +var assert = __webpack_require__(162) +var isAbsolute = __webpack_require__(253) +var globSync = __webpack_require__(254) +var common = __webpack_require__(255) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts var ownProp = common.ownProp -var inflight = __webpack_require__(258) -var util = __webpack_require__(115) +var inflight = __webpack_require__(256) +var util = __webpack_require__(113) var childrenIgnored = common.childrenIgnored var isIgnored = common.isIgnored -var once = __webpack_require__(171) +var once = __webpack_require__(169) function glob (pattern, options, cb) { if (typeof options === 'function') cb = options, options = {} @@ -19209,7 +19125,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 247 */ +/* 245 */ /***/ (function(module, exports, __webpack_require__) { module.exports = realpath @@ -19219,13 +19135,13 @@ realpath.realpathSync = realpathSync realpath.monkeypatch = monkeypatch realpath.unmonkeypatch = unmonkeypatch -var fs = __webpack_require__(134) +var fs = __webpack_require__(132) var origRealpath = fs.realpath var origRealpathSync = fs.realpathSync var version = process.version var ok = /^v[0-5]\./.test(version) -var old = __webpack_require__(248) +var old = __webpack_require__(246) function newError (er) { return er && er.syscall === 'realpath' && ( @@ -19281,7 +19197,7 @@ function unmonkeypatch () { /***/ }), -/* 248 */ +/* 246 */ /***/ (function(module, exports, __webpack_require__) { // Copyright Joyent, Inc. and other Node contributors. @@ -19307,7 +19223,7 @@ function unmonkeypatch () { var pathModule = __webpack_require__(4); var isWindows = process.platform === 'win32'; -var fs = __webpack_require__(134); +var fs = __webpack_require__(132); // JavaScript implementation of realpath, ported from node pre-v6 @@ -19590,7 +19506,7 @@ exports.realpath = function realpath(p, cache, cb) { /***/ }), -/* 249 */ +/* 247 */ /***/ (function(module, exports, __webpack_require__) { module.exports = minimatch @@ -19602,7 +19518,7 @@ try { } catch (er) {} var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} -var expand = __webpack_require__(250) +var expand = __webpack_require__(248) var plTypes = { '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, @@ -20519,11 +20435,11 @@ function regExpEscape (s) { /***/ }), -/* 250 */ +/* 248 */ /***/ (function(module, exports, __webpack_require__) { -var concatMap = __webpack_require__(251); -var balanced = __webpack_require__(252); +var concatMap = __webpack_require__(249); +var balanced = __webpack_require__(250); module.exports = expandTop; @@ -20726,7 +20642,7 @@ function expand(str, isTop) { /***/ }), -/* 251 */ +/* 249 */ /***/ (function(module, exports) { module.exports = function (xs, fn) { @@ -20745,7 +20661,7 @@ var isArray = Array.isArray || function (xs) { /***/ }), -/* 252 */ +/* 250 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -20811,22 +20727,22 @@ function range(a, b, str) { /***/ }), -/* 253 */ +/* 251 */ /***/ (function(module, exports, __webpack_require__) { try { - var util = __webpack_require__(115); + var util = __webpack_require__(113); /* istanbul ignore next */ if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(254); + module.exports = __webpack_require__(252); } /***/ }), -/* 254 */ +/* 252 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -20859,7 +20775,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 255 */ +/* 253 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -20886,22 +20802,22 @@ module.exports.win32 = win32; /***/ }), -/* 256 */ +/* 254 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync globSync.GlobSync = GlobSync -var fs = __webpack_require__(134) -var rp = __webpack_require__(247) -var minimatch = __webpack_require__(249) +var fs = __webpack_require__(132) +var rp = __webpack_require__(245) +var minimatch = __webpack_require__(247) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(246).Glob -var util = __webpack_require__(115) +var Glob = __webpack_require__(244).Glob +var util = __webpack_require__(113) var path = __webpack_require__(4) -var assert = __webpack_require__(164) -var isAbsolute = __webpack_require__(255) -var common = __webpack_require__(257) +var assert = __webpack_require__(162) +var isAbsolute = __webpack_require__(253) +var common = __webpack_require__(255) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -21378,7 +21294,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 257 */ +/* 255 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -21396,8 +21312,8 @@ function ownProp (obj, field) { } var path = __webpack_require__(4) -var minimatch = __webpack_require__(249) -var isAbsolute = __webpack_require__(255) +var minimatch = __webpack_require__(247) +var isAbsolute = __webpack_require__(253) var Minimatch = minimatch.Minimatch function alphasorti (a, b) { @@ -21624,12 +21540,12 @@ function childrenIgnored (self, path) { /***/ }), -/* 258 */ +/* 256 */ /***/ (function(module, exports, __webpack_require__) { -var wrappy = __webpack_require__(172) +var wrappy = __webpack_require__(170) var reqs = Object.create(null) -var once = __webpack_require__(171) +var once = __webpack_require__(169) module.exports = wrappy(inflight) @@ -21684,17 +21600,17 @@ function slice (args) { /***/ }), -/* 259 */ +/* 257 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const taskManager = __webpack_require__(260); -const async_1 = __webpack_require__(289); -const stream_1 = __webpack_require__(324); -const sync_1 = __webpack_require__(325); -const settings_1 = __webpack_require__(327); -const utils = __webpack_require__(261); +const taskManager = __webpack_require__(258); +const async_1 = __webpack_require__(287); +const stream_1 = __webpack_require__(322); +const sync_1 = __webpack_require__(323); +const settings_1 = __webpack_require__(325); +const utils = __webpack_require__(259); async function FastGlob(source, options) { assertPatternsInput(source); const works = getWorks(source, async_1.default, options); @@ -21758,14 +21674,14 @@ module.exports = FastGlob; /***/ }), -/* 260 */ +/* 258 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertPatternGroupToTask = exports.convertPatternGroupsToTasks = exports.groupPatternsByBaseDirectory = exports.getNegativePatternsAsPositive = exports.getPositivePatterns = exports.convertPatternsToTasks = exports.generate = void 0; -const utils = __webpack_require__(261); +const utils = __webpack_require__(259); function generate(patterns, settings) { const positivePatterns = getPositivePatterns(patterns); const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); @@ -21830,31 +21746,31 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 261 */ +/* 259 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.string = exports.stream = exports.pattern = exports.path = exports.fs = exports.errno = exports.array = void 0; -const array = __webpack_require__(262); +const array = __webpack_require__(260); exports.array = array; -const errno = __webpack_require__(263); +const errno = __webpack_require__(261); exports.errno = errno; -const fs = __webpack_require__(264); +const fs = __webpack_require__(262); exports.fs = fs; -const path = __webpack_require__(265); +const path = __webpack_require__(263); exports.path = path; -const pattern = __webpack_require__(266); +const pattern = __webpack_require__(264); exports.pattern = pattern; -const stream = __webpack_require__(287); +const stream = __webpack_require__(285); exports.stream = stream; -const string = __webpack_require__(288); +const string = __webpack_require__(286); exports.string = string; /***/ }), -/* 262 */ +/* 260 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -21883,7 +21799,7 @@ exports.splitWhen = splitWhen; /***/ }), -/* 263 */ +/* 261 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -21897,7 +21813,7 @@ exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 264 */ +/* 262 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -21923,7 +21839,7 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 265 */ +/* 263 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -21963,7 +21879,7 @@ exports.removeLeadingDotSegment = removeLeadingDotSegment; /***/ }), -/* 266 */ +/* 264 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -21971,9 +21887,9 @@ exports.removeLeadingDotSegment = removeLeadingDotSegment; Object.defineProperty(exports, "__esModule", { value: true }); exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = void 0; const path = __webpack_require__(4); -const globParent = __webpack_require__(267); -const micromatch = __webpack_require__(270); -const picomatch = __webpack_require__(281); +const globParent = __webpack_require__(265); +const micromatch = __webpack_require__(268); +const picomatch = __webpack_require__(279); const GLOBSTAR = '**'; const ESCAPE_SYMBOL = '\\'; const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; @@ -22102,15 +22018,15 @@ exports.matchAny = matchAny; /***/ }), -/* 267 */ +/* 265 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isGlob = __webpack_require__(268); +var isGlob = __webpack_require__(266); var pathPosixDirname = __webpack_require__(4).posix.dirname; -var isWin32 = __webpack_require__(124).platform() === 'win32'; +var isWin32 = __webpack_require__(122).platform() === 'win32'; var slash = '/'; var backslash = /\\/g; @@ -22151,7 +22067,7 @@ module.exports = function globParent(str, opts) { /***/ }), -/* 268 */ +/* 266 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -22161,7 +22077,7 @@ module.exports = function globParent(str, opts) { * Released under the MIT License. */ -var isExtglob = __webpack_require__(269); +var isExtglob = __webpack_require__(267); var chars = { '{': '}', '(': ')', '[': ']'}; var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; @@ -22205,7 +22121,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 269 */ +/* 267 */ /***/ (function(module, exports) { /*! @@ -22231,16 +22147,16 @@ module.exports = function isExtglob(str) { /***/ }), -/* 270 */ +/* 268 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const util = __webpack_require__(115); -const braces = __webpack_require__(271); -const picomatch = __webpack_require__(281); -const utils = __webpack_require__(284); +const util = __webpack_require__(113); +const braces = __webpack_require__(269); +const picomatch = __webpack_require__(279); +const utils = __webpack_require__(282); const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); /** @@ -22705,16 +22621,16 @@ module.exports = micromatch; /***/ }), -/* 271 */ +/* 269 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(272); -const compile = __webpack_require__(274); -const expand = __webpack_require__(278); -const parse = __webpack_require__(279); +const stringify = __webpack_require__(270); +const compile = __webpack_require__(272); +const expand = __webpack_require__(276); +const parse = __webpack_require__(277); /** * Expand the given pattern or create a regex-compatible string. @@ -22882,13 +22798,13 @@ module.exports = braces; /***/ }), -/* 272 */ +/* 270 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(273); +const utils = __webpack_require__(271); module.exports = (ast, options = {}) => { let stringify = (node, parent = {}) => { @@ -22921,7 +22837,7 @@ module.exports = (ast, options = {}) => { /***/ }), -/* 273 */ +/* 271 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -23040,14 +22956,14 @@ exports.flatten = (...args) => { /***/ }), -/* 274 */ +/* 272 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(275); -const utils = __webpack_require__(273); +const fill = __webpack_require__(273); +const utils = __webpack_require__(271); const compile = (ast, options = {}) => { let walk = (node, parent = {}) => { @@ -23104,7 +23020,7 @@ module.exports = compile; /***/ }), -/* 275 */ +/* 273 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -23117,8 +23033,8 @@ module.exports = compile; -const util = __webpack_require__(115); -const toRegexRange = __webpack_require__(276); +const util = __webpack_require__(113); +const toRegexRange = __webpack_require__(274); const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); @@ -23360,7 +23276,7 @@ module.exports = fill; /***/ }), -/* 276 */ +/* 274 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -23373,7 +23289,7 @@ module.exports = fill; -const isNumber = __webpack_require__(277); +const isNumber = __webpack_require__(275); const toRegexRange = (min, max, options) => { if (isNumber(min) === false) { @@ -23655,7 +23571,7 @@ module.exports = toRegexRange; /***/ }), -/* 277 */ +/* 275 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -23680,15 +23596,15 @@ module.exports = function(num) { /***/ }), -/* 278 */ +/* 276 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(275); -const stringify = __webpack_require__(272); -const utils = __webpack_require__(273); +const fill = __webpack_require__(273); +const stringify = __webpack_require__(270); +const utils = __webpack_require__(271); const append = (queue = '', stash = '', enclose = false) => { let result = []; @@ -23800,13 +23716,13 @@ module.exports = expand; /***/ }), -/* 279 */ +/* 277 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(272); +const stringify = __webpack_require__(270); /** * Constants @@ -23828,7 +23744,7 @@ const { CHAR_SINGLE_QUOTE, /* ' */ CHAR_NO_BREAK_SPACE, CHAR_ZERO_WIDTH_NOBREAK_SPACE -} = __webpack_require__(280); +} = __webpack_require__(278); /** * parse @@ -24140,7 +24056,7 @@ module.exports = parse; /***/ }), -/* 280 */ +/* 278 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24204,27 +24120,27 @@ module.exports = { /***/ }), -/* 281 */ +/* 279 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(282); +module.exports = __webpack_require__(280); /***/ }), -/* 282 */ +/* 280 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const scan = __webpack_require__(283); -const parse = __webpack_require__(286); -const utils = __webpack_require__(284); -const constants = __webpack_require__(285); +const scan = __webpack_require__(281); +const parse = __webpack_require__(284); +const utils = __webpack_require__(282); +const constants = __webpack_require__(283); const isObject = val => val && typeof val === 'object' && !Array.isArray(val); /** @@ -24560,13 +24476,13 @@ module.exports = picomatch; /***/ }), -/* 283 */ +/* 281 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(284); +const utils = __webpack_require__(282); const { CHAR_ASTERISK, /* * */ CHAR_AT, /* @ */ @@ -24583,7 +24499,7 @@ const { CHAR_RIGHT_CURLY_BRACE, /* } */ CHAR_RIGHT_PARENTHESES, /* ) */ CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = __webpack_require__(285); +} = __webpack_require__(283); const isPathSeparator = code => { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; @@ -24950,7 +24866,7 @@ module.exports = scan; /***/ }), -/* 284 */ +/* 282 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24963,7 +24879,7 @@ const { REGEX_REMOVE_BACKSLASH, REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL -} = __webpack_require__(285); +} = __webpack_require__(283); exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); @@ -25021,7 +24937,7 @@ exports.wrapOutput = (input, state = {}, options = {}) => { /***/ }), -/* 285 */ +/* 283 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -25207,14 +25123,14 @@ module.exports = { /***/ }), -/* 286 */ +/* 284 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const constants = __webpack_require__(285); -const utils = __webpack_require__(284); +const constants = __webpack_require__(283); +const utils = __webpack_require__(282); /** * Constants @@ -26292,14 +26208,14 @@ module.exports = parse; /***/ }), -/* 287 */ +/* 285 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.merge = void 0; -const merge2 = __webpack_require__(245); +const merge2 = __webpack_require__(243); function merge(streams) { const mergedStream = merge2(streams); streams.forEach((stream) => { @@ -26316,7 +26232,7 @@ function propagateCloseEventToSources(streams) { /***/ }), -/* 288 */ +/* 286 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -26334,14 +26250,14 @@ exports.isEmpty = isEmpty; /***/ }), -/* 289 */ +/* 287 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(290); -const provider_1 = __webpack_require__(317); +const stream_1 = __webpack_require__(288); +const provider_1 = __webpack_require__(315); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -26369,16 +26285,16 @@ exports.default = ProviderAsync; /***/ }), -/* 290 */ +/* 288 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(175); -const fsStat = __webpack_require__(291); -const fsWalk = __webpack_require__(296); -const reader_1 = __webpack_require__(316); +const stream_1 = __webpack_require__(173); +const fsStat = __webpack_require__(289); +const fsWalk = __webpack_require__(294); +const reader_1 = __webpack_require__(314); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -26431,15 +26347,15 @@ exports.default = ReaderStream; /***/ }), -/* 291 */ +/* 289 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(292); -const sync = __webpack_require__(293); -const settings_1 = __webpack_require__(294); +const async = __webpack_require__(290); +const sync = __webpack_require__(291); +const settings_1 = __webpack_require__(292); exports.Settings = settings_1.default; function stat(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -26462,7 +26378,7 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 292 */ +/* 290 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -26500,7 +26416,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 293 */ +/* 291 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -26529,13 +26445,13 @@ exports.read = read; /***/ }), -/* 294 */ +/* 292 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(295); +const fs = __webpack_require__(293); class Settings { constructor(_options = {}) { this._options = _options; @@ -26552,13 +26468,13 @@ exports.default = Settings; /***/ }), -/* 295 */ +/* 293 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(134); +const fs = __webpack_require__(132); exports.FILE_SYSTEM_ADAPTER = { lstat: fs.lstat, stat: fs.stat, @@ -26575,16 +26491,16 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 296 */ +/* 294 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(297); -const stream_1 = __webpack_require__(312); -const sync_1 = __webpack_require__(313); -const settings_1 = __webpack_require__(315); +const async_1 = __webpack_require__(295); +const stream_1 = __webpack_require__(310); +const sync_1 = __webpack_require__(311); +const settings_1 = __webpack_require__(313); exports.Settings = settings_1.default; function walk(directory, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -26614,13 +26530,13 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 297 */ +/* 295 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(298); +const async_1 = __webpack_require__(296); class AsyncProvider { constructor(_root, _settings) { this._root = _root; @@ -26651,17 +26567,17 @@ function callSuccessCallback(callback, entries) { /***/ }), -/* 298 */ +/* 296 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const events_1 = __webpack_require__(166); -const fsScandir = __webpack_require__(299); -const fastq = __webpack_require__(308); -const common = __webpack_require__(310); -const reader_1 = __webpack_require__(311); +const events_1 = __webpack_require__(164); +const fsScandir = __webpack_require__(297); +const fastq = __webpack_require__(306); +const common = __webpack_require__(308); +const reader_1 = __webpack_require__(309); class AsyncReader extends reader_1.default { constructor(_root, _settings) { super(_root, _settings); @@ -26751,15 +26667,15 @@ exports.default = AsyncReader; /***/ }), -/* 299 */ +/* 297 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(300); -const sync = __webpack_require__(305); -const settings_1 = __webpack_require__(306); +const async = __webpack_require__(298); +const sync = __webpack_require__(303); +const settings_1 = __webpack_require__(304); exports.Settings = settings_1.default; function scandir(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -26782,16 +26698,16 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 300 */ +/* 298 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(291); -const rpl = __webpack_require__(301); -const constants_1 = __webpack_require__(302); -const utils = __webpack_require__(303); +const fsStat = __webpack_require__(289); +const rpl = __webpack_require__(299); +const constants_1 = __webpack_require__(300); +const utils = __webpack_require__(301); function read(directory, settings, callback) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(directory, settings, callback); @@ -26879,7 +26795,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 301 */ +/* 299 */ /***/ (function(module, exports) { module.exports = runParallel @@ -26933,7 +26849,7 @@ function runParallel (tasks, cb) { /***/ }), -/* 302 */ +/* 300 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -26953,18 +26869,18 @@ exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = IS_MATCHED_BY_MAJOR || IS_MATCHED_B /***/ }), -/* 303 */ +/* 301 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(304); +const fs = __webpack_require__(302); exports.fs = fs; /***/ }), -/* 304 */ +/* 302 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -26989,15 +26905,15 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 305 */ +/* 303 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(291); -const constants_1 = __webpack_require__(302); -const utils = __webpack_require__(303); +const fsStat = __webpack_require__(289); +const constants_1 = __webpack_require__(300); +const utils = __webpack_require__(301); function read(directory, settings) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(directory, settings); @@ -27048,15 +26964,15 @@ exports.readdir = readdir; /***/ }), -/* 306 */ +/* 304 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); -const fsStat = __webpack_require__(291); -const fs = __webpack_require__(307); +const fsStat = __webpack_require__(289); +const fs = __webpack_require__(305); class Settings { constructor(_options = {}) { this._options = _options; @@ -27079,13 +26995,13 @@ exports.default = Settings; /***/ }), -/* 307 */ +/* 305 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(134); +const fs = __webpack_require__(132); exports.FILE_SYSTEM_ADAPTER = { lstat: fs.lstat, stat: fs.stat, @@ -27104,13 +27020,13 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 308 */ +/* 306 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var reusify = __webpack_require__(309) +var reusify = __webpack_require__(307) function fastqueue (context, worker, concurrency) { if (typeof context === 'function') { @@ -27284,7 +27200,7 @@ module.exports = fastqueue /***/ }), -/* 309 */ +/* 307 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -27324,7 +27240,7 @@ module.exports = reusify /***/ }), -/* 310 */ +/* 308 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -27355,13 +27271,13 @@ exports.joinPathSegments = joinPathSegments; /***/ }), -/* 311 */ +/* 309 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const common = __webpack_require__(310); +const common = __webpack_require__(308); class Reader { constructor(_root, _settings) { this._root = _root; @@ -27373,14 +27289,14 @@ exports.default = Reader; /***/ }), -/* 312 */ +/* 310 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(175); -const async_1 = __webpack_require__(298); +const stream_1 = __webpack_require__(173); +const async_1 = __webpack_require__(296); class StreamProvider { constructor(_root, _settings) { this._root = _root; @@ -27410,13 +27326,13 @@ exports.default = StreamProvider; /***/ }), -/* 313 */ +/* 311 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(314); +const sync_1 = __webpack_require__(312); class SyncProvider { constructor(_root, _settings) { this._root = _root; @@ -27431,15 +27347,15 @@ exports.default = SyncProvider; /***/ }), -/* 314 */ +/* 312 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsScandir = __webpack_require__(299); -const common = __webpack_require__(310); -const reader_1 = __webpack_require__(311); +const fsScandir = __webpack_require__(297); +const common = __webpack_require__(308); +const reader_1 = __webpack_require__(309); class SyncReader extends reader_1.default { constructor() { super(...arguments); @@ -27497,14 +27413,14 @@ exports.default = SyncReader; /***/ }), -/* 315 */ +/* 313 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); -const fsScandir = __webpack_require__(299); +const fsScandir = __webpack_require__(297); class Settings { constructor(_options = {}) { this._options = _options; @@ -27530,15 +27446,15 @@ exports.default = Settings; /***/ }), -/* 316 */ +/* 314 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); -const fsStat = __webpack_require__(291); -const utils = __webpack_require__(261); +const fsStat = __webpack_require__(289); +const utils = __webpack_require__(259); class Reader { constructor(_settings) { this._settings = _settings; @@ -27570,17 +27486,17 @@ exports.default = Reader; /***/ }), -/* 317 */ +/* 315 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); -const deep_1 = __webpack_require__(318); -const entry_1 = __webpack_require__(321); -const error_1 = __webpack_require__(322); -const entry_2 = __webpack_require__(323); +const deep_1 = __webpack_require__(316); +const entry_1 = __webpack_require__(319); +const error_1 = __webpack_require__(320); +const entry_2 = __webpack_require__(321); class Provider { constructor(_settings) { this._settings = _settings; @@ -27625,14 +27541,14 @@ exports.default = Provider; /***/ }), -/* 318 */ +/* 316 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(261); -const partial_1 = __webpack_require__(319); +const utils = __webpack_require__(259); +const partial_1 = __webpack_require__(317); class DeepFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -27694,13 +27610,13 @@ exports.default = DeepFilter; /***/ }), -/* 319 */ +/* 317 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const matcher_1 = __webpack_require__(320); +const matcher_1 = __webpack_require__(318); class PartialMatcher extends matcher_1.default { match(filepath) { const parts = filepath.split('/'); @@ -27739,13 +27655,13 @@ exports.default = PartialMatcher; /***/ }), -/* 320 */ +/* 318 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(261); +const utils = __webpack_require__(259); class Matcher { constructor(_patterns, _settings, _micromatchOptions) { this._patterns = _patterns; @@ -27796,13 +27712,13 @@ exports.default = Matcher; /***/ }), -/* 321 */ +/* 319 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(261); +const utils = __webpack_require__(259); class EntryFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -27859,13 +27775,13 @@ exports.default = EntryFilter; /***/ }), -/* 322 */ +/* 320 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(261); +const utils = __webpack_require__(259); class ErrorFilter { constructor(_settings) { this._settings = _settings; @@ -27881,13 +27797,13 @@ exports.default = ErrorFilter; /***/ }), -/* 323 */ +/* 321 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(261); +const utils = __webpack_require__(259); class EntryTransformer { constructor(_settings) { this._settings = _settings; @@ -27914,15 +27830,15 @@ exports.default = EntryTransformer; /***/ }), -/* 324 */ +/* 322 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(175); -const stream_2 = __webpack_require__(290); -const provider_1 = __webpack_require__(317); +const stream_1 = __webpack_require__(173); +const stream_2 = __webpack_require__(288); +const provider_1 = __webpack_require__(315); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -27952,14 +27868,14 @@ exports.default = ProviderStream; /***/ }), -/* 325 */ +/* 323 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(326); -const provider_1 = __webpack_require__(317); +const sync_1 = __webpack_require__(324); +const provider_1 = __webpack_require__(315); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -27982,15 +27898,15 @@ exports.default = ProviderSync; /***/ }), -/* 326 */ +/* 324 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(291); -const fsWalk = __webpack_require__(296); -const reader_1 = __webpack_require__(316); +const fsStat = __webpack_require__(289); +const fsWalk = __webpack_require__(294); +const reader_1 = __webpack_require__(314); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -28032,15 +27948,15 @@ exports.default = ReaderSync; /***/ }), -/* 327 */ +/* 325 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DEFAULT_FILE_SYSTEM_ADAPTER = void 0; -const fs = __webpack_require__(134); -const os = __webpack_require__(124); +const fs = __webpack_require__(132); +const os = __webpack_require__(122); /** * The `os.cpus` method can return zero. We expect the number of cores to be greater than zero. * https://github.com/nodejs/node/blob/7faeddf23a98c53896f8b574a6e66589e8fb1eb8/lib/os.js#L106-L107 @@ -28096,13 +28012,13 @@ exports.default = Settings; /***/ }), -/* 328 */ +/* 326 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const pathType = __webpack_require__(329); +const pathType = __webpack_require__(327); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -28178,13 +28094,13 @@ module.exports.sync = (input, options) => { /***/ }), -/* 329 */ +/* 327 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {promisify} = __webpack_require__(115); -const fs = __webpack_require__(134); +const {promisify} = __webpack_require__(113); +const fs = __webpack_require__(132); async function isType(fsStatType, statsMethodName, filePath) { if (typeof filePath !== 'string') { @@ -28228,17 +28144,17 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 330 */ +/* 328 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {promisify} = __webpack_require__(115); -const fs = __webpack_require__(134); +const {promisify} = __webpack_require__(113); +const fs = __webpack_require__(132); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(259); -const gitIgnore = __webpack_require__(331); -const slash = __webpack_require__(332); +const fastGlob = __webpack_require__(257); +const gitIgnore = __webpack_require__(329); +const slash = __webpack_require__(330); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -28352,7 +28268,7 @@ module.exports.sync = options => { /***/ }), -/* 331 */ +/* 329 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -28955,7 +28871,7 @@ if ( /***/ }), -/* 332 */ +/* 330 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -28973,12 +28889,12 @@ module.exports = path => { /***/ }), -/* 333 */ +/* 331 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {Transform} = __webpack_require__(175); +const {Transform} = __webpack_require__(173); class ObjectTransform extends Transform { constructor() { @@ -29026,7 +28942,7 @@ module.exports = { /***/ }), -/* 334 */ +/* 332 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -29048,7 +28964,7 @@ module.exports = path_ => { /***/ }), -/* 335 */ +/* 333 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -29076,15 +28992,15 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 336 */ +/* 334 */ /***/ (function(module, exports, __webpack_require__) { -const assert = __webpack_require__(164) +const assert = __webpack_require__(162) const path = __webpack_require__(4) -const fs = __webpack_require__(134) +const fs = __webpack_require__(132) let glob = undefined try { - glob = __webpack_require__(246) + glob = __webpack_require__(244) } catch (_err) { // treat glob as optional. } @@ -29442,12 +29358,12 @@ rimraf.sync = rimrafSync /***/ }), -/* 337 */ +/* 335 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const AggregateError = __webpack_require__(338); +const AggregateError = __webpack_require__(336); module.exports = async ( iterable, @@ -29530,13 +29446,13 @@ module.exports = async ( /***/ }), -/* 338 */ +/* 336 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const indentString = __webpack_require__(339); -const cleanStack = __webpack_require__(340); +const indentString = __webpack_require__(337); +const cleanStack = __webpack_require__(338); const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); @@ -29584,7 +29500,7 @@ module.exports = AggregateError; /***/ }), -/* 339 */ +/* 337 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -29626,12 +29542,12 @@ module.exports = (string, count = 1, options) => { /***/ }), -/* 340 */ +/* 338 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const os = __webpack_require__(124); +const os = __webpack_require__(122); const extractPathRegex = /\s+at.*(?:\(|\s)(.*)\)?/; const pathRegex = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)\.js:\d+:\d+)|native)/; @@ -29673,10 +29589,10 @@ module.exports = (stack, options) => { /***/ }), -/* 341 */ +/* 339 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(134), +var fs = __webpack_require__(132), path = __webpack_require__(4); module.exports = ncp; @@ -29940,7 +29856,7 @@ function ncp (source, dest, options, callback) { /***/ }), -/* 342 */ +/* 340 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29951,14 +29867,14 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProjectGraph", function() { return buildProjectGraph; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "topologicallyBatchProjects", function() { return topologicallyBatchProjects; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "includeTransitiveProjects", function() { return includeTransitiveProjects; }); -/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(246); +/* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(244); /* harmony import */ var glob__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(glob__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); /* 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__(115); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(113); /* 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__(343); -/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(344); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(341); +/* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(342); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -30133,7 +30049,7 @@ function includeTransitiveProjects(subsetOfProjects, allProjects, { } /***/ }), -/* 343 */ +/* 341 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30155,23 +30071,23 @@ class CliError extends Error { } /***/ }), -/* 344 */ +/* 342 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return Project; }); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(134); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(132); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); /* 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__(115); +/* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(113); /* 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__(343); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(222); -/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(345); -/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(409); -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; } +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(341); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(220); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(343); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(407); +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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -30363,7 +30279,7 @@ function normalizePath(path) { } /***/ }), -/* 345 */ +/* 343 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30374,11 +30290,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isLinkDependency", function() { return isLinkDependency; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isBazelPackageDependency", function() { return isBazelPackageDependency; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "transformDependencies", function() { return transformDependencies; }); -/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(346); +/* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(344); /* harmony import */ var read_pkg__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(read_pkg__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(398); +/* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(396); /* harmony import */ var write_pkg__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(write_pkg__WEBPACK_IMPORTED_MODULE_1__); -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 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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -30444,15 +30360,15 @@ function transformDependencies(dependencies = {}) { } /***/ }), -/* 346 */ +/* 344 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {promisify} = __webpack_require__(115); -const fs = __webpack_require__(134); +const {promisify} = __webpack_require__(113); +const fs = __webpack_require__(132); const path = __webpack_require__(4); -const parseJson = __webpack_require__(347); +const parseJson = __webpack_require__(345); const readFileAsync = promisify(fs.readFile); @@ -30467,7 +30383,7 @@ module.exports = async options => { const json = parseJson(await readFileAsync(filePath, 'utf8')); if (options.normalize) { - __webpack_require__(368)(json); + __webpack_require__(366)(json); } return json; @@ -30484,7 +30400,7 @@ module.exports.sync = options => { const json = parseJson(fs.readFileSync(filePath, 'utf8')); if (options.normalize) { - __webpack_require__(368)(json); + __webpack_require__(366)(json); } return json; @@ -30492,15 +30408,15 @@ module.exports.sync = options => { /***/ }), -/* 347 */ +/* 345 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const errorEx = __webpack_require__(348); -const fallback = __webpack_require__(350); -const {default: LinesAndColumns} = __webpack_require__(351); -const {codeFrameColumns} = __webpack_require__(352); +const errorEx = __webpack_require__(346); +const fallback = __webpack_require__(348); +const {default: LinesAndColumns} = __webpack_require__(349); +const {codeFrameColumns} = __webpack_require__(350); const JSONError = errorEx('JSONError', { fileName: errorEx.append('in %s'), @@ -30549,14 +30465,14 @@ module.exports = (string, reviver, filename) => { /***/ }), -/* 348 */ +/* 346 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var util = __webpack_require__(115); -var isArrayish = __webpack_require__(349); +var util = __webpack_require__(113); +var isArrayish = __webpack_require__(347); var errorEx = function errorEx(name, properties) { if (!name || name.constructor !== String) { @@ -30689,7 +30605,7 @@ module.exports = errorEx; /***/ }), -/* 349 */ +/* 347 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -30706,7 +30622,7 @@ module.exports = function isArrayish(obj) { /***/ }), -/* 350 */ +/* 348 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -30751,7 +30667,7 @@ function parseJson (txt, reviver, context) { /***/ }), -/* 351 */ +/* 349 */ /***/ (function(__webpack_module__, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30815,7 +30731,7 @@ var LinesAndColumns = (function () { /***/ }), -/* 352 */ +/* 350 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -30827,7 +30743,7 @@ Object.defineProperty(exports, "__esModule", { exports.codeFrameColumns = codeFrameColumns; exports.default = _default; -var _highlight = _interopRequireWildcard(__webpack_require__(353)); +var _highlight = _interopRequireWildcard(__webpack_require__(351)); function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } @@ -30988,7 +30904,7 @@ function _default(rawLines, lineNumber, colNumber, opts = {}) { } /***/ }), -/* 353 */ +/* 351 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31001,11 +30917,11 @@ exports.shouldHighlight = shouldHighlight; exports.getChalk = getChalk; exports.default = highlight; -var jsTokensNs = _interopRequireWildcard(__webpack_require__(354)); +var jsTokensNs = _interopRequireWildcard(__webpack_require__(352)); -var _helperValidatorIdentifier = __webpack_require__(355); +var _helperValidatorIdentifier = __webpack_require__(353); -var _chalk = _interopRequireDefault(__webpack_require__(358)); +var _chalk = _interopRequireDefault(__webpack_require__(356)); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } @@ -31118,7 +31034,7 @@ function highlight(code, options = {}) { } /***/ }), -/* 354 */ +/* 352 */ /***/ (function(module, exports) { // Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell @@ -31147,7 +31063,7 @@ exports.matchToToken = function(match) { /***/ }), -/* 355 */ +/* 353 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31205,12 +31121,12 @@ Object.defineProperty(exports, "isKeyword", { } }); -var _identifier = __webpack_require__(356); +var _identifier = __webpack_require__(354); -var _keyword = __webpack_require__(357); +var _keyword = __webpack_require__(355); /***/ }), -/* 356 */ +/* 354 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31300,7 +31216,7 @@ function isIdentifierName(name) { } /***/ }), -/* 357 */ +/* 355 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31344,16 +31260,16 @@ function isKeyword(word) { } /***/ }), -/* 358 */ +/* 356 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const escapeStringRegexp = __webpack_require__(359); -const ansiStyles = __webpack_require__(360); -const stdoutColor = __webpack_require__(365).stdout; +const escapeStringRegexp = __webpack_require__(357); +const ansiStyles = __webpack_require__(358); +const stdoutColor = __webpack_require__(363).stdout; -const template = __webpack_require__(367); +const template = __webpack_require__(365); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -31579,7 +31495,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 359 */ +/* 357 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -31597,12 +31513,12 @@ module.exports = function (str) { /***/ }), -/* 360 */ +/* 358 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(module) { -const colorConvert = __webpack_require__(361); +const colorConvert = __webpack_require__(359); const wrapAnsi16 = (fn, offset) => function () { const code = fn.apply(colorConvert, arguments); @@ -31767,14 +31683,14 @@ Object.defineProperty(module, 'exports', { get: assembleStyles }); -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(118)(module))) +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(116)(module))) /***/ }), -/* 361 */ +/* 359 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(362); -var route = __webpack_require__(364); +var conversions = __webpack_require__(360); +var route = __webpack_require__(362); var convert = {}; @@ -31854,11 +31770,11 @@ module.exports = convert; /***/ }), -/* 362 */ +/* 360 */ /***/ (function(module, exports, __webpack_require__) { /* MIT license */ -var cssKeywords = __webpack_require__(363); +var cssKeywords = __webpack_require__(361); // NOTE: conversions should only return primitive values (i.e. arrays, or // values that give correct `typeof` results). @@ -32728,7 +32644,7 @@ convert.rgb.gray = function (rgb) { /***/ }), -/* 363 */ +/* 361 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -32887,10 +32803,10 @@ module.exports = { /***/ }), -/* 364 */ +/* 362 */ /***/ (function(module, exports, __webpack_require__) { -var conversions = __webpack_require__(362); +var conversions = __webpack_require__(360); /* this function routes a model to all other models. @@ -32990,13 +32906,13 @@ module.exports = function (fromModel) { /***/ }), -/* 365 */ +/* 363 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const os = __webpack_require__(124); -const hasFlag = __webpack_require__(366); +const os = __webpack_require__(122); +const hasFlag = __webpack_require__(364); const env = process.env; @@ -33128,7 +33044,7 @@ module.exports = { /***/ }), -/* 366 */ +/* 364 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -33143,7 +33059,7 @@ module.exports = (flag, argv) => { /***/ }), -/* 367 */ +/* 365 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -33278,15 +33194,15 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 368 */ +/* 366 */ /***/ (function(module, exports, __webpack_require__) { module.exports = normalize -var fixer = __webpack_require__(369) +var fixer = __webpack_require__(367) normalize.fixer = fixer -var makeWarning = __webpack_require__(396) +var makeWarning = __webpack_require__(394) var fieldsToFix = ['name','version','description','repository','modules','scripts' ,'files','bin','man','bugs','keywords','readme','homepage','license'] @@ -33323,17 +33239,17 @@ function ucFirst (string) { /***/ }), -/* 369 */ +/* 367 */ /***/ (function(module, exports, __webpack_require__) { -var semver = __webpack_require__(370) -var validateLicense = __webpack_require__(371); -var hostedGitInfo = __webpack_require__(376) -var isBuiltinModule = __webpack_require__(379).isCore +var semver = __webpack_require__(368) +var validateLicense = __webpack_require__(369); +var hostedGitInfo = __webpack_require__(374) +var isBuiltinModule = __webpack_require__(377).isCore var depTypes = ["dependencies","devDependencies","optionalDependencies"] -var extractDescription = __webpack_require__(394) -var url = __webpack_require__(205) -var typos = __webpack_require__(395) +var extractDescription = __webpack_require__(392) +var url = __webpack_require__(203) +var typos = __webpack_require__(393) var fixer = module.exports = { // default warning function @@ -33747,7 +33663,7 @@ function bugsTypos(bugs, warn) { /***/ }), -/* 370 */ +/* 368 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -35236,11 +35152,11 @@ function coerce (version) { /***/ }), -/* 371 */ +/* 369 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(372); -var correct = __webpack_require__(374); +var parse = __webpack_require__(370); +var correct = __webpack_require__(372); var genericWarning = ( 'license should be ' + @@ -35326,10 +35242,10 @@ module.exports = function(argument) { /***/ }), -/* 372 */ +/* 370 */ /***/ (function(module, exports, __webpack_require__) { -var parser = __webpack_require__(373).parser +var parser = __webpack_require__(371).parser module.exports = function (argument) { return parser.parse(argument) @@ -35337,7 +35253,7 @@ module.exports = function (argument) { /***/ }), -/* 373 */ +/* 371 */ /***/ (function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module) {/* parser generated by jison 0.4.17 */ @@ -36690,7 +36606,7 @@ exports.main = function commonjsMain(args) { console.log('Usage: '+args[0]+' FILE'); process.exit(1); } - var source = __webpack_require__(134).readFileSync(__webpack_require__(4).normalize(args[1]), "utf8"); + var source = __webpack_require__(132).readFileSync(__webpack_require__(4).normalize(args[1]), "utf8"); return exports.parser.parse(source); }; if ( true && __webpack_require__.c[__webpack_require__.s] === module) { @@ -36698,13 +36614,13 @@ if ( true && __webpack_require__.c[__webpack_require__.s] === module) { } } -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(118)(module))) +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(116)(module))) /***/ }), -/* 374 */ +/* 372 */ /***/ (function(module, exports, __webpack_require__) { -var licenseIDs = __webpack_require__(375); +var licenseIDs = __webpack_require__(373); function valid(string) { return licenseIDs.indexOf(string) > -1; @@ -36944,20 +36860,20 @@ module.exports = function(identifier) { /***/ }), -/* 375 */ +/* 373 */ /***/ (function(module) { module.exports = JSON.parse("[\"Glide\",\"Abstyles\",\"AFL-1.1\",\"AFL-1.2\",\"AFL-2.0\",\"AFL-2.1\",\"AFL-3.0\",\"AMPAS\",\"APL-1.0\",\"Adobe-Glyph\",\"APAFML\",\"Adobe-2006\",\"AGPL-1.0\",\"Afmparse\",\"Aladdin\",\"ADSL\",\"AMDPLPA\",\"ANTLR-PD\",\"Apache-1.0\",\"Apache-1.1\",\"Apache-2.0\",\"AML\",\"APSL-1.0\",\"APSL-1.1\",\"APSL-1.2\",\"APSL-2.0\",\"Artistic-1.0\",\"Artistic-1.0-Perl\",\"Artistic-1.0-cl8\",\"Artistic-2.0\",\"AAL\",\"Bahyph\",\"Barr\",\"Beerware\",\"BitTorrent-1.0\",\"BitTorrent-1.1\",\"BSL-1.0\",\"Borceux\",\"BSD-2-Clause\",\"BSD-2-Clause-FreeBSD\",\"BSD-2-Clause-NetBSD\",\"BSD-3-Clause\",\"BSD-3-Clause-Clear\",\"BSD-4-Clause\",\"BSD-Protection\",\"BSD-Source-Code\",\"BSD-3-Clause-Attribution\",\"0BSD\",\"BSD-4-Clause-UC\",\"bzip2-1.0.5\",\"bzip2-1.0.6\",\"Caldera\",\"CECILL-1.0\",\"CECILL-1.1\",\"CECILL-2.0\",\"CECILL-2.1\",\"CECILL-B\",\"CECILL-C\",\"ClArtistic\",\"MIT-CMU\",\"CNRI-Jython\",\"CNRI-Python\",\"CNRI-Python-GPL-Compatible\",\"CPOL-1.02\",\"CDDL-1.0\",\"CDDL-1.1\",\"CPAL-1.0\",\"CPL-1.0\",\"CATOSL-1.1\",\"Condor-1.1\",\"CC-BY-1.0\",\"CC-BY-2.0\",\"CC-BY-2.5\",\"CC-BY-3.0\",\"CC-BY-4.0\",\"CC-BY-ND-1.0\",\"CC-BY-ND-2.0\",\"CC-BY-ND-2.5\",\"CC-BY-ND-3.0\",\"CC-BY-ND-4.0\",\"CC-BY-NC-1.0\",\"CC-BY-NC-2.0\",\"CC-BY-NC-2.5\",\"CC-BY-NC-3.0\",\"CC-BY-NC-4.0\",\"CC-BY-NC-ND-1.0\",\"CC-BY-NC-ND-2.0\",\"CC-BY-NC-ND-2.5\",\"CC-BY-NC-ND-3.0\",\"CC-BY-NC-ND-4.0\",\"CC-BY-NC-SA-1.0\",\"CC-BY-NC-SA-2.0\",\"CC-BY-NC-SA-2.5\",\"CC-BY-NC-SA-3.0\",\"CC-BY-NC-SA-4.0\",\"CC-BY-SA-1.0\",\"CC-BY-SA-2.0\",\"CC-BY-SA-2.5\",\"CC-BY-SA-3.0\",\"CC-BY-SA-4.0\",\"CC0-1.0\",\"Crossword\",\"CrystalStacker\",\"CUA-OPL-1.0\",\"Cube\",\"curl\",\"D-FSL-1.0\",\"diffmark\",\"WTFPL\",\"DOC\",\"Dotseqn\",\"DSDP\",\"dvipdfm\",\"EPL-1.0\",\"ECL-1.0\",\"ECL-2.0\",\"eGenix\",\"EFL-1.0\",\"EFL-2.0\",\"MIT-advertising\",\"MIT-enna\",\"Entessa\",\"ErlPL-1.1\",\"EUDatagrid\",\"EUPL-1.0\",\"EUPL-1.1\",\"Eurosym\",\"Fair\",\"MIT-feh\",\"Frameworx-1.0\",\"FreeImage\",\"FTL\",\"FSFAP\",\"FSFUL\",\"FSFULLR\",\"Giftware\",\"GL2PS\",\"Glulxe\",\"AGPL-3.0\",\"GFDL-1.1\",\"GFDL-1.2\",\"GFDL-1.3\",\"GPL-1.0\",\"GPL-2.0\",\"GPL-3.0\",\"LGPL-2.1\",\"LGPL-3.0\",\"LGPL-2.0\",\"gnuplot\",\"gSOAP-1.3b\",\"HaskellReport\",\"HPND\",\"IBM-pibs\",\"IPL-1.0\",\"ICU\",\"ImageMagick\",\"iMatix\",\"Imlib2\",\"IJG\",\"Info-ZIP\",\"Intel-ACPI\",\"Intel\",\"Interbase-1.0\",\"IPA\",\"ISC\",\"JasPer-2.0\",\"JSON\",\"LPPL-1.0\",\"LPPL-1.1\",\"LPPL-1.2\",\"LPPL-1.3a\",\"LPPL-1.3c\",\"Latex2e\",\"BSD-3-Clause-LBNL\",\"Leptonica\",\"LGPLLR\",\"Libpng\",\"libtiff\",\"LAL-1.2\",\"LAL-1.3\",\"LiLiQ-P-1.1\",\"LiLiQ-Rplus-1.1\",\"LiLiQ-R-1.1\",\"LPL-1.02\",\"LPL-1.0\",\"MakeIndex\",\"MTLL\",\"MS-PL\",\"MS-RL\",\"MirOS\",\"MITNFA\",\"MIT\",\"Motosoto\",\"MPL-1.0\",\"MPL-1.1\",\"MPL-2.0\",\"MPL-2.0-no-copyleft-exception\",\"mpich2\",\"Multics\",\"Mup\",\"NASA-1.3\",\"Naumen\",\"NBPL-1.0\",\"NetCDF\",\"NGPL\",\"NOSL\",\"NPL-1.0\",\"NPL-1.1\",\"Newsletr\",\"NLPL\",\"Nokia\",\"NPOSL-3.0\",\"NLOD-1.0\",\"Noweb\",\"NRL\",\"NTP\",\"Nunit\",\"OCLC-2.0\",\"ODbL-1.0\",\"PDDL-1.0\",\"OCCT-PL\",\"OGTSL\",\"OLDAP-2.2.2\",\"OLDAP-1.1\",\"OLDAP-1.2\",\"OLDAP-1.3\",\"OLDAP-1.4\",\"OLDAP-2.0\",\"OLDAP-2.0.1\",\"OLDAP-2.1\",\"OLDAP-2.2\",\"OLDAP-2.2.1\",\"OLDAP-2.3\",\"OLDAP-2.4\",\"OLDAP-2.5\",\"OLDAP-2.6\",\"OLDAP-2.7\",\"OLDAP-2.8\",\"OML\",\"OPL-1.0\",\"OSL-1.0\",\"OSL-1.1\",\"OSL-2.0\",\"OSL-2.1\",\"OSL-3.0\",\"OpenSSL\",\"OSET-PL-2.1\",\"PHP-3.0\",\"PHP-3.01\",\"Plexus\",\"PostgreSQL\",\"psfrag\",\"psutils\",\"Python-2.0\",\"QPL-1.0\",\"Qhull\",\"Rdisc\",\"RPSL-1.0\",\"RPL-1.1\",\"RPL-1.5\",\"RHeCos-1.1\",\"RSCPL\",\"RSA-MD\",\"Ruby\",\"SAX-PD\",\"Saxpath\",\"SCEA\",\"SWL\",\"SMPPL\",\"Sendmail\",\"SGI-B-1.0\",\"SGI-B-1.1\",\"SGI-B-2.0\",\"OFL-1.0\",\"OFL-1.1\",\"SimPL-2.0\",\"Sleepycat\",\"SNIA\",\"Spencer-86\",\"Spencer-94\",\"Spencer-99\",\"SMLNJ\",\"SugarCRM-1.1.3\",\"SISSL\",\"SISSL-1.2\",\"SPL-1.0\",\"Watcom-1.0\",\"TCL\",\"Unlicense\",\"TMate\",\"TORQUE-1.1\",\"TOSL\",\"Unicode-TOU\",\"UPL-1.0\",\"NCSA\",\"Vim\",\"VOSTROM\",\"VSL-1.0\",\"W3C-19980720\",\"W3C\",\"Wsuipa\",\"Xnet\",\"X11\",\"Xerox\",\"XFree86-1.1\",\"xinetd\",\"xpp\",\"XSkat\",\"YPL-1.0\",\"YPL-1.1\",\"Zed\",\"Zend-2.0\",\"Zimbra-1.3\",\"Zimbra-1.4\",\"Zlib\",\"zlib-acknowledgement\",\"ZPL-1.1\",\"ZPL-2.0\",\"ZPL-2.1\",\"BSD-3-Clause-No-Nuclear-License\",\"BSD-3-Clause-No-Nuclear-Warranty\",\"BSD-3-Clause-No-Nuclear-License-2014\",\"eCos-2.0\",\"GPL-2.0-with-autoconf-exception\",\"GPL-2.0-with-bison-exception\",\"GPL-2.0-with-classpath-exception\",\"GPL-2.0-with-font-exception\",\"GPL-2.0-with-GCC-exception\",\"GPL-3.0-with-autoconf-exception\",\"GPL-3.0-with-GCC-exception\",\"StandardML-NJ\",\"WXwindows\"]"); /***/ }), -/* 376 */ +/* 374 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var url = __webpack_require__(205) -var gitHosts = __webpack_require__(377) -var GitHost = module.exports = __webpack_require__(378) +var url = __webpack_require__(203) +var gitHosts = __webpack_require__(375) +var GitHost = module.exports = __webpack_require__(376) var protocolToRepresentationMap = { 'git+ssh:': 'sshurl', @@ -37105,7 +37021,7 @@ function parseGitUrl (giturl) { /***/ }), -/* 377 */ +/* 375 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -37191,12 +37107,12 @@ function formatHashFragment (fragment) { /***/ }), -/* 378 */ +/* 376 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var gitHosts = __webpack_require__(377) +var gitHosts = __webpack_require__(375) /* eslint-disable node/no-deprecated-api */ // copy-pasta util._extend from node's source, to avoid pulling @@ -37354,27 +37270,27 @@ GitHost.prototype.toString = function (opts) { /***/ }), -/* 379 */ +/* 377 */ /***/ (function(module, exports, __webpack_require__) { -var async = __webpack_require__(380); -async.core = __webpack_require__(390); -async.isCore = __webpack_require__(392); -async.sync = __webpack_require__(393); +var async = __webpack_require__(378); +async.core = __webpack_require__(388); +async.isCore = __webpack_require__(390); +async.sync = __webpack_require__(391); module.exports = async; /***/ }), -/* 380 */ +/* 378 */ /***/ (function(module, exports, __webpack_require__) { -var fs = __webpack_require__(134); +var fs = __webpack_require__(132); var path = __webpack_require__(4); -var caller = __webpack_require__(381); -var nodeModulesPaths = __webpack_require__(382); -var normalizeOptions = __webpack_require__(384); -var isCore = __webpack_require__(385); +var caller = __webpack_require__(379); +var nodeModulesPaths = __webpack_require__(380); +var normalizeOptions = __webpack_require__(382); +var isCore = __webpack_require__(383); var realpathFS = fs.realpath && typeof fs.realpath.native === 'function' ? fs.realpath.native : fs.realpath; @@ -37671,7 +37587,7 @@ module.exports = function resolve(x, options, callback) { /***/ }), -/* 381 */ +/* 379 */ /***/ (function(module, exports) { module.exports = function () { @@ -37685,11 +37601,11 @@ module.exports = function () { /***/ }), -/* 382 */ +/* 380 */ /***/ (function(module, exports, __webpack_require__) { var path = __webpack_require__(4); -var parse = path.parse || __webpack_require__(383); +var parse = path.parse || __webpack_require__(381); var getNodeModulesDirs = function getNodeModulesDirs(absoluteStart, modules) { var prefix = '/'; @@ -37733,7 +37649,7 @@ module.exports = function nodeModulesPaths(start, opts, request) { /***/ }), -/* 383 */ +/* 381 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -37815,7 +37731,7 @@ module.exports.win32 = win32.parse; /***/ }), -/* 384 */ +/* 382 */ /***/ (function(module, exports) { module.exports = function (x, opts) { @@ -37831,13 +37747,13 @@ module.exports = function (x, opts) { /***/ }), -/* 385 */ +/* 383 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var has = __webpack_require__(386); +var has = __webpack_require__(384); function specifierIncluded(current, specifier) { var nodeParts = current.split('.'); @@ -37899,7 +37815,7 @@ function versionIncluded(nodeVersion, specifierValue) { return matchesRange(current, specifierValue); } -var data = __webpack_require__(389); +var data = __webpack_require__(387); module.exports = function isCore(x, nodeVersion) { return has(data, x) && versionIncluded(nodeVersion, data[x]); @@ -37907,31 +37823,31 @@ module.exports = function isCore(x, nodeVersion) { /***/ }), -/* 386 */ +/* 384 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var bind = __webpack_require__(387); +var bind = __webpack_require__(385); module.exports = bind.call(Function.call, Object.prototype.hasOwnProperty); /***/ }), -/* 387 */ +/* 385 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var implementation = __webpack_require__(388); +var implementation = __webpack_require__(386); module.exports = Function.prototype.bind || implementation; /***/ }), -/* 388 */ +/* 386 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -37990,13 +37906,13 @@ module.exports = function bind(that) { /***/ }), -/* 389 */ +/* 387 */ /***/ (function(module) { module.exports = JSON.parse("{\"assert\":true,\"assert/strict\":\">= 15\",\"async_hooks\":\">= 8\",\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"child_process\":true,\"cluster\":true,\"console\":true,\"constants\":true,\"crypto\":true,\"_debug_agent\":\">= 1 && < 8\",\"_debugger\":\"< 8\",\"dgram\":true,\"diagnostics_channel\":\">= 15.1\",\"dns\":true,\"dns/promises\":\">= 15\",\"domain\":\">= 0.7.12\",\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":[\">= 10 && < 10.1\",\">= 14\"],\"_http_agent\":\">= 0.11.1\",\"_http_client\":\">= 0.11.1\",\"_http_common\":\">= 0.11.1\",\"_http_incoming\":\">= 0.11.1\",\"_http_outgoing\":\">= 0.11.1\",\"_http_server\":\">= 0.11.1\",\"http\":true,\"http2\":\">= 8.8\",\"https\":true,\"inspector\":\">= 8.0.0\",\"_linklist\":\"< 8\",\"module\":true,\"net\":true,\"node-inspect/lib/_inspect\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0 && < 12\",\"os\":true,\"path\":true,\"perf_hooks\":\">= 8.5\",\"process\":\">= 1\",\"punycode\":true,\"querystring\":true,\"readline\":true,\"repl\":true,\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"_stream_transform\":\">= 0.9.4\",\"_stream_wrap\":\">= 1.4.1\",\"_stream_passthrough\":\">= 0.9.4\",\"_stream_readable\":\">= 0.9.4\",\"_stream_writable\":\">= 0.9.4\",\"stream\":true,\"stream/promises\":\">= 15\",\"string_decoder\":true,\"sys\":[\">= 0.6 && < 0.7\",\">= 0.8\"],\"timers\":true,\"timers/promises\":\">= 15\",\"_tls_common\":\">= 0.11.13\",\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"tls\":true,\"trace_events\":\">= 10\",\"tty\":true,\"url\":true,\"util\":true,\"v8/tools/arguments\":\">= 10 && < 12\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8\":\">= 1\",\"vm\":true,\"wasi\":\">= 13.4 && < 13.5\",\"worker_threads\":\">= 11.7\",\"zlib\":true}"); /***/ }), -/* 390 */ +/* 388 */ /***/ (function(module, exports, __webpack_require__) { var current = (process.versions && process.versions.node && process.versions.node.split('.')) || []; @@ -38043,7 +37959,7 @@ function versionIncluded(specifierValue) { return matchesRange(specifierValue); } -var data = __webpack_require__(391); +var data = __webpack_require__(389); var core = {}; for (var mod in data) { // eslint-disable-line no-restricted-syntax @@ -38055,16 +37971,16 @@ module.exports = core; /***/ }), -/* 391 */ +/* 389 */ /***/ (function(module) { module.exports = JSON.parse("{\"assert\":true,\"assert/strict\":\">= 15\",\"async_hooks\":\">= 8\",\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"child_process\":true,\"cluster\":true,\"console\":true,\"constants\":true,\"crypto\":true,\"_debug_agent\":\">= 1 && < 8\",\"_debugger\":\"< 8\",\"dgram\":true,\"diagnostics_channel\":\">= 15.1\",\"dns\":true,\"dns/promises\":\">= 15\",\"domain\":\">= 0.7.12\",\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":[\">= 10 && < 10.1\",\">= 14\"],\"_http_agent\":\">= 0.11.1\",\"_http_client\":\">= 0.11.1\",\"_http_common\":\">= 0.11.1\",\"_http_incoming\":\">= 0.11.1\",\"_http_outgoing\":\">= 0.11.1\",\"_http_server\":\">= 0.11.1\",\"http\":true,\"http2\":\">= 8.8\",\"https\":true,\"inspector\":\">= 8.0.0\",\"_linklist\":\"< 8\",\"module\":true,\"net\":true,\"node-inspect/lib/_inspect\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0 && < 12\",\"os\":true,\"path\":true,\"perf_hooks\":\">= 8.5\",\"process\":\">= 1\",\"punycode\":true,\"querystring\":true,\"readline\":true,\"repl\":true,\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"_stream_transform\":\">= 0.9.4\",\"_stream_wrap\":\">= 1.4.1\",\"_stream_passthrough\":\">= 0.9.4\",\"_stream_readable\":\">= 0.9.4\",\"_stream_writable\":\">= 0.9.4\",\"stream\":true,\"stream/promises\":\">= 15\",\"string_decoder\":true,\"sys\":[\">= 0.6 && < 0.7\",\">= 0.8\"],\"timers\":true,\"timers/promises\":\">= 15\",\"_tls_common\":\">= 0.11.13\",\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"tls\":true,\"trace_events\":\">= 10\",\"tty\":true,\"url\":true,\"util\":true,\"v8/tools/arguments\":\">= 10 && < 12\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8\":\">= 1\",\"vm\":true,\"wasi\":\">= 13.4 && < 13.5\",\"worker_threads\":\">= 11.7\",\"zlib\":true}"); /***/ }), -/* 392 */ +/* 390 */ /***/ (function(module, exports, __webpack_require__) { -var isCoreModule = __webpack_require__(385); +var isCoreModule = __webpack_require__(383); module.exports = function isCore(x) { return isCoreModule(x); @@ -38072,15 +37988,15 @@ module.exports = function isCore(x) { /***/ }), -/* 393 */ +/* 391 */ /***/ (function(module, exports, __webpack_require__) { -var isCore = __webpack_require__(385); -var fs = __webpack_require__(134); +var isCore = __webpack_require__(383); +var fs = __webpack_require__(132); var path = __webpack_require__(4); -var caller = __webpack_require__(381); -var nodeModulesPaths = __webpack_require__(382); -var normalizeOptions = __webpack_require__(384); +var caller = __webpack_require__(379); +var nodeModulesPaths = __webpack_require__(380); +var normalizeOptions = __webpack_require__(382); var realpathFS = fs.realpathSync && typeof fs.realpathSync.native === 'function' ? fs.realpathSync.native : fs.realpathSync; @@ -38270,7 +38186,7 @@ module.exports = function resolveSync(x, options) { /***/ }), -/* 394 */ +/* 392 */ /***/ (function(module, exports) { module.exports = extractDescription @@ -38290,17 +38206,17 @@ function extractDescription (d) { /***/ }), -/* 395 */ +/* 393 */ /***/ (function(module) { module.exports = JSON.parse("{\"topLevel\":{\"dependancies\":\"dependencies\",\"dependecies\":\"dependencies\",\"depdenencies\":\"dependencies\",\"devEependencies\":\"devDependencies\",\"depends\":\"dependencies\",\"dev-dependencies\":\"devDependencies\",\"devDependences\":\"devDependencies\",\"devDepenencies\":\"devDependencies\",\"devdependencies\":\"devDependencies\",\"repostitory\":\"repository\",\"repo\":\"repository\",\"prefereGlobal\":\"preferGlobal\",\"hompage\":\"homepage\",\"hampage\":\"homepage\",\"autohr\":\"author\",\"autor\":\"author\",\"contributers\":\"contributors\",\"publicationConfig\":\"publishConfig\",\"script\":\"scripts\"},\"bugs\":{\"web\":\"url\",\"name\":\"url\"},\"script\":{\"server\":\"start\",\"tests\":\"test\"}}"); /***/ }), -/* 396 */ +/* 394 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(115) -var messages = __webpack_require__(397) +var util = __webpack_require__(113) +var messages = __webpack_require__(395) module.exports = function() { var args = Array.prototype.slice.call(arguments, 0) @@ -38325,20 +38241,20 @@ function makeTypoWarning (providedName, probableName, field) { /***/ }), -/* 397 */ +/* 395 */ /***/ (function(module) { module.exports = JSON.parse("{\"repositories\":\"'repositories' (plural) Not supported. Please pick one as the 'repository' field\",\"missingRepository\":\"No repository field.\",\"brokenGitUrl\":\"Probably broken git url: %s\",\"nonObjectScripts\":\"scripts must be an object\",\"nonStringScript\":\"script values must be string commands\",\"nonArrayFiles\":\"Invalid 'files' member\",\"invalidFilename\":\"Invalid filename in 'files' list: %s\",\"nonArrayBundleDependencies\":\"Invalid 'bundleDependencies' list. Must be array of package names\",\"nonStringBundleDependency\":\"Invalid bundleDependencies member: %s\",\"nonDependencyBundleDependency\":\"Non-dependency in bundleDependencies: %s\",\"nonObjectDependencies\":\"%s field must be an object\",\"nonStringDependency\":\"Invalid dependency: %s %s\",\"deprecatedArrayDependencies\":\"specifying %s as array is deprecated\",\"deprecatedModules\":\"modules field is deprecated\",\"nonArrayKeywords\":\"keywords should be an array of strings\",\"nonStringKeyword\":\"keywords should be an array of strings\",\"conflictingName\":\"%s is also the name of a node core module.\",\"nonStringDescription\":\"'description' field should be a string\",\"missingDescription\":\"No description\",\"missingReadme\":\"No README data\",\"missingLicense\":\"No license field.\",\"nonEmailUrlBugsString\":\"Bug string field must be url, email, or {email,url}\",\"nonUrlBugsUrlField\":\"bugs.url field must be a string url. Deleted.\",\"nonEmailBugsEmailField\":\"bugs.email field must be a string email. Deleted.\",\"emptyNormalizedBugs\":\"Normalized value of bugs field is an empty object. Deleted.\",\"nonUrlHomepage\":\"homepage field must be a string url. Deleted.\",\"invalidLicense\":\"license should be a valid SPDX license expression\",\"typo\":\"%s should probably be %s.\"}"); /***/ }), -/* 398 */ +/* 396 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const writeJsonFile = __webpack_require__(399); -const sortKeys = __webpack_require__(403); +const writeJsonFile = __webpack_require__(397); +const sortKeys = __webpack_require__(401); const dependencyKeys = new Set([ 'dependencies', @@ -38403,18 +38319,18 @@ module.exports.sync = (filePath, data, options) => { /***/ }), -/* 399 */ +/* 397 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const fs = __webpack_require__(235); -const writeFileAtomic = __webpack_require__(400); -const sortKeys = __webpack_require__(403); -const makeDir = __webpack_require__(405); -const pify = __webpack_require__(406); -const detectIndent = __webpack_require__(408); +const fs = __webpack_require__(233); +const writeFileAtomic = __webpack_require__(398); +const sortKeys = __webpack_require__(401); +const makeDir = __webpack_require__(403); +const pify = __webpack_require__(404); +const detectIndent = __webpack_require__(406); const init = (fn, filePath, data, options) => { if (!filePath) { @@ -38486,7 +38402,7 @@ module.exports.sync = (filePath, data, options) => { /***/ }), -/* 400 */ +/* 398 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38496,9 +38412,9 @@ module.exports.sync = writeFileSync module.exports._getTmpname = getTmpname // for testing module.exports._cleanupOnExit = cleanupOnExit -var fs = __webpack_require__(235) -var MurmurHash3 = __webpack_require__(401) -var onExit = __webpack_require__(163) +var fs = __webpack_require__(233) +var MurmurHash3 = __webpack_require__(399) +var onExit = __webpack_require__(161) var path = __webpack_require__(4) var activeFiles = {} @@ -38506,7 +38422,7 @@ var activeFiles = {} /* istanbul ignore next */ var threadId = (function getId () { try { - var workerThreads = __webpack_require__(402) + var workerThreads = __webpack_require__(400) /// if we are in main thread, this is set to `0` return workerThreads.threadId @@ -38731,7 +38647,7 @@ function writeFileSync (filename, data, options) { /***/ }), -/* 401 */ +/* 399 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -38873,18 +38789,18 @@ function writeFileSync (filename, data, options) { /***/ }), -/* 402 */ +/* 400 */ /***/ (function(module, exports) { module.exports = require(undefined); /***/ }), -/* 403 */ +/* 401 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const isPlainObj = __webpack_require__(404); +const isPlainObj = __webpack_require__(402); module.exports = (obj, opts) => { if (!isPlainObj(obj)) { @@ -38941,7 +38857,7 @@ module.exports = (obj, opts) => { /***/ }), -/* 404 */ +/* 402 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38955,15 +38871,15 @@ module.exports = function (x) { /***/ }), -/* 405 */ +/* 403 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); +const fs = __webpack_require__(132); const path = __webpack_require__(4); -const pify = __webpack_require__(406); -const semver = __webpack_require__(407); +const pify = __webpack_require__(404); +const semver = __webpack_require__(405); const defaults = { mode: 0o777 & (~process.umask()), @@ -39101,7 +39017,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 406 */ +/* 404 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39176,7 +39092,7 @@ module.exports = (input, options) => { /***/ }), -/* 407 */ +/* 405 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -40665,7 +40581,7 @@ function coerce (version) { /***/ }), -/* 408 */ +/* 406 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40794,7 +40710,7 @@ module.exports = str => { /***/ }), -/* 409 */ +/* 407 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -40802,7 +40718,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "installInDir", function() { return installInDir; }); /* 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 import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(223); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(221); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -40854,16 +40770,16 @@ function runScriptInPackageStreaming({ } /***/ }), -/* 410 */ +/* 408 */ /***/ (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 export (binding) */ __webpack_require__.d(__webpack_exports__, "resolveDepsForProject", function() { return resolveDepsForProject; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(411); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(409); /* 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__(233); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(231); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -40963,7 +40879,7 @@ function resolveDepsForProject({ } /***/ }), -/* 411 */ +/* 409 */ /***/ (function(module, exports, __webpack_require__) { module.exports = @@ -41089,13 +41005,13 @@ exports.default = function (fn) { /* 2 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(115); +module.exports = __webpack_require__(113); /***/ }), /* 3 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(134); +module.exports = __webpack_require__(132); /***/ }), /* 4 */ @@ -42522,7 +42438,7 @@ module.exports = invariant; /* 9 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(135); +module.exports = __webpack_require__(133); /***/ }), /* 10 */, @@ -42948,7 +42864,7 @@ exports.default = Lockfile; /* 17 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(175); +module.exports = __webpack_require__(173); /***/ }), /* 18 */, @@ -43000,7 +42916,7 @@ function nullify(obj = {}) { /* 22 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(164); +module.exports = __webpack_require__(162); /***/ }), /* 23 */ @@ -43187,7 +43103,7 @@ module.exports = {}; /* 36 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(124); +module.exports = __webpack_require__(122); /***/ }), /* 37 */, @@ -43472,7 +43388,7 @@ exports.f = __webpack_require__(33) ? Object.defineProperty : function definePro /* 54 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(166); +module.exports = __webpack_require__(164); /***/ }), /* 55 */ @@ -44846,7 +44762,7 @@ function onceStrict (fn) { /* 63 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(412); +module.exports = __webpack_require__(410); /***/ }), /* 64 */, @@ -45784,7 +45700,7 @@ module.exports.win32 = win32; /* 79 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(125); +module.exports = __webpack_require__(123); /***/ }), /* 80 */, @@ -51241,30 +51157,30 @@ module.exports = process && support(supportLevel); /******/ ]); /***/ }), -/* 412 */ +/* 410 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 413 */ +/* 411 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validateDependencies", function() { return validateDependencies; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(411); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(409); /* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(116); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(114); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(233); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(222); -/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(345); -/* harmony import */ var _projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(414); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(231); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(220); +/* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(343); +/* harmony import */ var _projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(412); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -51445,14 +51361,14 @@ function getDevOnlyProductionDepsTree(kbn, projectName) { } /***/ }), -/* 414 */ +/* 412 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renderProjectsTree", function() { return renderProjectsTree; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "treeToString", function() { return treeToString; }); -/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(116); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(114); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); @@ -51587,27 +51503,27 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 415 */ +/* 413 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _yarn_integrity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(416); +/* harmony import */ var _yarn_integrity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(414); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "yarnIntegrityFileExists", function() { return _yarn_integrity__WEBPACK_IMPORTED_MODULE_0__["yarnIntegrityFileExists"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ensureYarnIntegrityFileExists", function() { return _yarn_integrity__WEBPACK_IMPORTED_MODULE_0__["ensureYarnIntegrityFileExists"]; }); -/* harmony import */ var _get_cache_folders__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(417); +/* harmony import */ var _get_cache_folders__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(415); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getBazelDiskCacheFolder", function() { return _get_cache_folders__WEBPACK_IMPORTED_MODULE_1__["getBazelDiskCacheFolder"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getBazelRepositoryCacheFolder", function() { return _get_cache_folders__WEBPACK_IMPORTED_MODULE_1__["getBazelRepositoryCacheFolder"]; }); -/* harmony import */ var _install_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(418); +/* harmony import */ var _install_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(416); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isBazelBinAvailable", function() { return _install_tools__WEBPACK_IMPORTED_MODULE_2__["isBazelBinAvailable"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "installBazelTools", function() { return _install_tools__WEBPACK_IMPORTED_MODULE_2__["installBazelTools"]; }); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(419); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(417); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "runBazel", function() { return _run__WEBPACK_IMPORTED_MODULE_3__["runBazel"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "runIBazel", function() { return _run__WEBPACK_IMPORTED_MODULE_3__["runIBazel"]; }); @@ -51625,7 +51541,7 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 416 */ +/* 414 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -51634,7 +51550,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ensureYarnIntegrityFileExists", function() { return ensureYarnIntegrityFileExists; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(231); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -51672,7 +51588,7 @@ async function ensureYarnIntegrityFileExists(nodeModulesPath) { } /***/ }), -/* 417 */ +/* 415 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -51681,7 +51597,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBazelRepositoryCacheFolder", function() { return getBazelRepositoryCacheFolder; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(221); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -51709,7 +51625,7 @@ async function getBazelRepositoryCacheFolder() { } /***/ }), -/* 418 */ +/* 416 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -51720,9 +51636,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(223); -/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(233); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(222); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(221); +/* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(231); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(220); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -51828,23 +51744,23 @@ async function installBazelTools(repoRootPath) { } /***/ }), -/* 419 */ +/* 417 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runBazel", function() { return runBazel; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runIBazel", function() { return runIBazel; }); -/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(116); +/* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(114); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); -/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(420); -/* harmony import */ var _kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(518); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(418); +/* harmony import */ var _kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(516); /* harmony import */ var _kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(223); -/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(222); -/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(343); -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; } +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(221); +/* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(220); +/* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(341); +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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -51905,320 +51821,320 @@ async function runIBazel(bazelArgs, offline = false, runOpts = {}) { } /***/ }), -/* 420 */ +/* 418 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(421); +/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(419); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__["audit"]; }); -/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(422); +/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(420); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__["auditTime"]; }); -/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(423); +/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(421); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__["buffer"]; }); -/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(424); +/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(422); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__["bufferCount"]; }); -/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(425); +/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(423); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__["bufferTime"]; }); -/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(426); +/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(424); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__["bufferToggle"]; }); -/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(427); +/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(425); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__["bufferWhen"]; }); -/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(428); +/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(426); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__["catchError"]; }); -/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(429); +/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(427); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__["combineAll"]; }); -/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(430); +/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(428); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__["combineLatest"]; }); -/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(431); +/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(429); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__["concat"]; }); -/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(83); +/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(81); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__["concatAll"]; }); -/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(432); +/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(430); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__["concatMap"]; }); -/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(433); +/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(431); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__["concatMapTo"]; }); -/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(434); +/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(432); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "count", function() { return _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__["count"]; }); -/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(435); +/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(433); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__["debounce"]; }); -/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(436); +/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(434); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__["debounceTime"]; }); -/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(437); +/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(435); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__["defaultIfEmpty"]; }); -/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(438); +/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(436); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__["delay"]; }); -/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(440); +/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(438); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__["delayWhen"]; }); -/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(441); +/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(439); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__["dematerialize"]; }); -/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(442); +/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(440); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__["distinct"]; }); -/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(443); +/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(441); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__["distinctUntilChanged"]; }); -/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(444); +/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(442); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__["distinctUntilKeyChanged"]; }); -/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(445); +/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(443); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__["elementAt"]; }); -/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(448); +/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(446); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__["endWith"]; }); -/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(449); +/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(447); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "every", function() { return _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__["every"]; }); -/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(450); +/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(448); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__["exhaust"]; }); -/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(451); +/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(449); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__["exhaustMap"]; }); -/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(452); +/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(450); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__["expand"]; }); -/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(108); +/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(106); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__["filter"]; }); -/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(453); +/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(451); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__["finalize"]; }); -/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(454); +/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(452); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "find", function() { return _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__["find"]; }); -/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(455); +/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(453); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__["findIndex"]; }); -/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(456); +/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(454); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "first", function() { return _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__["first"]; }); -/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(34); +/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(32); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__["groupBy"]; }); -/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(457); +/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(455); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__["ignoreElements"]; }); -/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(458); +/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(456); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__["isEmpty"]; }); -/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(459); +/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(457); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "last", function() { return _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__["last"]; }); -/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(69); +/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(67); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "map", function() { return _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__["map"]; }); -/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(461); +/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(459); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__["mapTo"]; }); -/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(462); +/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(460); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__["materialize"]; }); -/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(463); +/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(461); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "max", function() { return _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__["max"]; }); -/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(466); +/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(464); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__["merge"]; }); -/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(84); +/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(82); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__["mergeAll"]; }); -/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(85); +/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(83); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["flatMap"]; }); -/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(467); +/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(465); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__["mergeMapTo"]; }); -/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(468); +/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(466); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__["mergeScan"]; }); -/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(469); +/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(467); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "min", function() { return _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__["min"]; }); -/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(470); +/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(468); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__["multicast"]; }); -/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(44); +/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(42); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observeOn", function() { return _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__["observeOn"]; }); -/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(471); +/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(469); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(472); +/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(470); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__["pairwise"]; }); -/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(473); +/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(471); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__["partition"]; }); -/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(474); +/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(472); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__["pluck"]; }); -/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(475); +/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(473); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__["publish"]; }); -/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(476); +/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(474); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__["publishBehavior"]; }); -/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(477); +/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(475); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__["publishLast"]; }); -/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(478); +/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(476); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__["publishReplay"]; }); -/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(479); +/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(477); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__["race"]; }); -/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(464); +/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(462); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__["reduce"]; }); -/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(480); +/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(478); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__["repeat"]; }); -/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(481); +/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(479); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__["repeatWhen"]; }); -/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(482); +/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(480); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__["retry"]; }); -/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(483); +/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(481); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__["retryWhen"]; }); -/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(33); +/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(31); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__["refCount"]; }); -/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(484); +/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(482); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__["sample"]; }); -/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(485); +/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(483); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__["sampleTime"]; }); -/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(465); +/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(463); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__["scan"]; }); -/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(486); +/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(484); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__["sequenceEqual"]; }); -/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(487); +/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(485); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "share", function() { return _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__["share"]; }); -/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(488); +/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(486); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__["shareReplay"]; }); -/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(489); +/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(487); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "single", function() { return _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__["single"]; }); -/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(490); +/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(488); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__["skip"]; }); -/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(491); +/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(489); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__["skipLast"]; }); -/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(492); +/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(490); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__["skipUntil"]; }); -/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(493); +/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(491); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__["skipWhile"]; }); -/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(494); +/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(492); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__["startWith"]; }); -/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(495); +/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(493); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__["subscribeOn"]; }); -/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(497); +/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(495); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__["switchAll"]; }); -/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(498); +/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(496); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__["switchMap"]; }); -/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(499); +/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(497); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__["switchMapTo"]; }); -/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(447); +/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(445); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "take", function() { return _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__["take"]; }); -/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(460); +/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(458); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__["takeLast"]; }); -/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(500); +/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(498); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__["takeUntil"]; }); -/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(501); +/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(499); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__["takeWhile"]; }); -/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(502); +/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(500); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__["tap"]; }); -/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(503); +/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(501); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__["throttle"]; }); -/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(504); +/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(502); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__["throttleTime"]; }); -/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(446); +/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(444); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__["throwIfEmpty"]; }); -/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(505); +/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(503); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__["timeInterval"]; }); -/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(506); +/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(504); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__["timeout"]; }); -/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(507); +/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(505); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__["timeoutWith"]; }); -/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(508); +/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(506); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__["timestamp"]; }); -/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(509); +/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(507); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__["toArray"]; }); -/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(510); +/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(508); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "window", function() { return _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__["window"]; }); -/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(511); +/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(509); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__["windowCount"]; }); -/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(512); +/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(510); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__["windowTime"]; }); -/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(513); +/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(511); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__["windowToggle"]; }); -/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(514); +/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(512); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__["windowWhen"]; }); -/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(515); +/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(513); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__["withLatestFrom"]; }); -/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(516); +/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(514); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__["zip"]; }); -/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(517); +/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(515); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__["zipAll"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -52329,14 +52245,14 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 421 */ +/* 419 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return audit; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -52408,15 +52324,15 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 422 */ +/* 420 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return auditTime; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(58); -/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(421); -/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(111); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(56); +/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(419); +/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(109); /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */ @@ -52431,14 +52347,14 @@ function auditTime(duration, scheduler) { /***/ }), -/* 423 */ +/* 421 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return buffer; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -52478,14 +52394,14 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 424 */ +/* 422 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return bufferCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -52579,16 +52495,16 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 425 */ +/* 423 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return bufferTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(58); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(48); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(56); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(46); /** PURE_IMPORTS_START tslib,_scheduler_async,_Subscriber,_util_isScheduler PURE_IMPORTS_END */ @@ -52740,16 +52656,16 @@ function dispatchBufferClose(arg) { /***/ }), -/* 426 */ +/* 424 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return bufferToggle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(73); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(72); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(71); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); /** PURE_IMPORTS_START tslib,_Subscription,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */ @@ -52859,15 +52775,15 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 427 */ +/* 425 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return bufferWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_Subscription,_innerSubscribe PURE_IMPORTS_END */ @@ -52952,14 +52868,14 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 428 */ +/* 426 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return catchError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -53012,13 +52928,13 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 429 */ +/* 427 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return combineAll; }); -/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(71); +/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(69); /** PURE_IMPORTS_START _observable_combineLatest PURE_IMPORTS_END */ function combineAll(project) { @@ -53028,15 +52944,15 @@ function combineAll(project) { /***/ }), -/* 430 */ +/* 428 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21); -/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(71); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(86); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19); +/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(84); /** PURE_IMPORTS_START _util_isArray,_observable_combineLatest,_observable_from PURE_IMPORTS_END */ @@ -53060,13 +52976,13 @@ function combineLatest() { /***/ }), -/* 431 */ +/* 429 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; }); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(82); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(80); /** PURE_IMPORTS_START _observable_concat PURE_IMPORTS_END */ function concat() { @@ -53080,13 +52996,13 @@ function concat() { /***/ }), -/* 432 */ +/* 430 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return concatMap; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(85); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(83); /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */ function concatMap(project, resultSelector) { @@ -53096,13 +53012,13 @@ function concatMap(project, resultSelector) { /***/ }), -/* 433 */ +/* 431 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return concatMapTo; }); -/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(432); +/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(430); /** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */ function concatMapTo(innerObservable, resultSelector) { @@ -53112,14 +53028,14 @@ function concatMapTo(innerObservable, resultSelector) { /***/ }), -/* 434 */ +/* 432 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "count", function() { return count; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -53177,14 +53093,14 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 435 */ +/* 433 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return debounce; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -53262,15 +53178,15 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 436 */ +/* 434 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return debounceTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(58); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(56); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */ @@ -53338,14 +53254,14 @@ function dispatchNext(subscriber) { /***/ }), -/* 437 */ +/* 435 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return defaultIfEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -53388,17 +53304,17 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 438 */ +/* 436 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return delay; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(58); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(439); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(14); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(45); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(56); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(437); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(43); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -53495,7 +53411,7 @@ var DelayMessage = /*@__PURE__*/ (function () { /***/ }), -/* 439 */ +/* 437 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53509,17 +53425,17 @@ function isDate(value) { /***/ }), -/* 440 */ +/* 438 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return delayWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(72); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(73); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(71); /** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -53655,14 +53571,14 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 441 */ +/* 439 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return dematerialize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -53693,15 +53609,15 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 442 */ +/* 440 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return distinct; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DistinctSubscriber", function() { return DistinctSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -53769,14 +53685,14 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 443 */ +/* 441 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return distinctUntilChanged; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -53840,13 +53756,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 444 */ +/* 442 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return distinctUntilKeyChanged; }); -/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(443); +/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(441); /** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */ function distinctUntilKeyChanged(key, compare) { @@ -53856,17 +53772,17 @@ function distinctUntilKeyChanged(key, compare) { /***/ }), -/* 445 */ +/* 443 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return elementAt; }); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(65); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(108); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(446); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(437); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(447); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(63); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(106); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(444); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(435); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(445); /** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */ @@ -53888,15 +53804,15 @@ function elementAt(index, defaultValue) { /***/ }), -/* 446 */ +/* 444 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return throwIfEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(66); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(64); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_util_EmptyError,_Subscriber PURE_IMPORTS_END */ @@ -53954,16 +53870,16 @@ function defaultErrorFactory() { /***/ }), -/* 447 */ +/* 445 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "take", function() { return take; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(65); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(46); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(63); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(44); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */ @@ -54016,14 +53932,14 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 448 */ +/* 446 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return endWith; }); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(82); -/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(47); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(80); +/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(45); /** PURE_IMPORTS_START _observable_concat,_observable_of PURE_IMPORTS_END */ @@ -54038,14 +53954,14 @@ function endWith() { /***/ }), -/* 449 */ +/* 447 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "every", function() { return every; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -54100,14 +54016,14 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 450 */ +/* 448 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return exhaust; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -54154,16 +54070,16 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 451 */ +/* 449 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return exhaustMap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(86); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(67); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(84); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */ @@ -54248,7 +54164,7 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 452 */ +/* 450 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54256,8 +54172,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return expand; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandOperator", function() { return ExpandOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandSubscriber", function() { return ExpandSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -54360,15 +54276,15 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 453 */ +/* 451 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return finalize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(18); /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription PURE_IMPORTS_END */ @@ -54398,7 +54314,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 454 */ +/* 452 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54406,8 +54322,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "find", function() { return find; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FindValueOperator", function() { return FindValueOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FindValueSubscriber", function() { return FindValueSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -54470,13 +54386,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 455 */ +/* 453 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return findIndex; }); -/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(454); +/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(452); /** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */ function findIndex(predicate, thisArg) { @@ -54486,18 +54402,18 @@ function findIndex(predicate, thisArg) { /***/ }), -/* 456 */ +/* 454 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "first", function() { return first; }); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(66); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(108); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(447); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(437); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(446); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(28); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(64); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(106); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(445); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(435); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(444); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(26); /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -54513,14 +54429,14 @@ function first(predicate, defaultValue) { /***/ }), -/* 457 */ +/* 455 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return ignoreElements; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -54550,14 +54466,14 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 458 */ +/* 456 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return isEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -54594,18 +54510,18 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 459 */ +/* 457 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "last", function() { return last; }); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(66); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(108); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(460); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(446); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(437); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(28); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(64); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(106); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(458); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(444); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(435); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(26); /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -54621,16 +54537,16 @@ function last(predicate, defaultValue) { /***/ }), -/* 460 */ +/* 458 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return takeLast; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(65); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(46); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(63); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(44); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */ @@ -54698,14 +54614,14 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 461 */ +/* 459 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return mapTo; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -54737,15 +54653,15 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 462 */ +/* 460 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return materialize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(45); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(43); /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -54787,13 +54703,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 463 */ +/* 461 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "max", function() { return max; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(464); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(462); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function max(comparer) { @@ -54806,16 +54722,16 @@ function max(comparer) { /***/ }), -/* 464 */ +/* 462 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return reduce; }); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(465); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(460); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(437); -/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(27); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(463); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(458); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(435); +/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(25); /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */ @@ -54835,14 +54751,14 @@ function reduce(accumulator, seed) { /***/ }), -/* 465 */ +/* 463 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return scan; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -54917,13 +54833,13 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 466 */ +/* 464 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; }); -/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(102); +/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(100); /** PURE_IMPORTS_START _observable_merge PURE_IMPORTS_END */ function merge() { @@ -54937,13 +54853,13 @@ function merge() { /***/ }), -/* 467 */ +/* 465 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return mergeMapTo; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(85); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(83); /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */ function mergeMapTo(innerObservable, resultSelector, concurrent) { @@ -54962,7 +54878,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) { /***/ }), -/* 468 */ +/* 466 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54970,8 +54886,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return mergeScan; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanOperator", function() { return MergeScanOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanSubscriber", function() { return MergeScanSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -55071,13 +54987,13 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 469 */ +/* 467 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "min", function() { return min; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(464); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(462); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function min(comparer) { @@ -55090,14 +55006,14 @@ function min(comparer) { /***/ }), -/* 470 */ +/* 468 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return multicast; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MulticastOperator", function() { return MulticastOperator; }); -/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(29); +/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(27); /** PURE_IMPORTS_START _observable_ConnectableObservable PURE_IMPORTS_END */ function multicast(subjectOrSubjectFactory, selector) { @@ -55139,17 +55055,17 @@ var MulticastOperator = /*@__PURE__*/ (function () { /***/ }), -/* 471 */ +/* 469 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNextStatic", function() { return onErrorResumeNextStatic; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(86); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(84); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(19); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_observable_from,_util_isArray,_innerSubscribe PURE_IMPORTS_END */ @@ -55229,14 +55145,14 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 472 */ +/* 470 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return pairwise; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -55277,14 +55193,14 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 473 */ +/* 471 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return partition; }); -/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(107); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(108); +/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(105); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(106); /** PURE_IMPORTS_START _util_not,_filter PURE_IMPORTS_END */ @@ -55300,13 +55216,13 @@ function partition(predicate, thisArg) { /***/ }), -/* 474 */ +/* 472 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return pluck; }); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(69); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(67); /** PURE_IMPORTS_START _map PURE_IMPORTS_END */ function pluck() { @@ -55340,14 +55256,14 @@ function plucker(props, length) { /***/ }), -/* 475 */ +/* 473 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return publish; }); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(30); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(470); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(28); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(468); /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */ @@ -55360,14 +55276,14 @@ function publish(selector) { /***/ }), -/* 476 */ +/* 474 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return publishBehavior; }); -/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(35); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(470); +/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(33); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(468); /** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */ @@ -55378,14 +55294,14 @@ function publishBehavior(value) { /***/ }), -/* 477 */ +/* 475 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return publishLast; }); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(53); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(470); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(51); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(468); /** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */ @@ -55396,14 +55312,14 @@ function publishLast() { /***/ }), -/* 478 */ +/* 476 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return publishReplay; }); -/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(470); +/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(34); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(468); /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */ @@ -55419,14 +55335,14 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) { /***/ }), -/* 479 */ +/* 477 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21); -/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(109); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19); +/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(107); /** PURE_IMPORTS_START _util_isArray,_observable_race PURE_IMPORTS_END */ @@ -55446,15 +55362,15 @@ function race() { /***/ }), -/* 480 */ +/* 478 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return repeat; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(46); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(44); /** PURE_IMPORTS_START tslib,_Subscriber,_observable_empty PURE_IMPORTS_END */ @@ -55511,15 +55427,15 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 481 */ +/* 479 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return repeatWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_Subject,_innerSubscribe PURE_IMPORTS_END */ @@ -55605,14 +55521,14 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 482 */ +/* 480 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return retry; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -55658,15 +55574,15 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 483 */ +/* 481 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return retryWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_Subject,_innerSubscribe PURE_IMPORTS_END */ @@ -55744,14 +55660,14 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 484 */ +/* 482 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return sample; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -55799,15 +55715,15 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 485 */ +/* 483 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return sampleTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(58); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(56); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */ @@ -55859,7 +55775,7 @@ function dispatchNotification(state) { /***/ }), -/* 486 */ +/* 484 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55867,8 +55783,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return sequenceEqual; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualOperator", function() { return SequenceEqualOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualSubscriber", function() { return SequenceEqualSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -55982,15 +55898,15 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 487 */ +/* 485 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "share", function() { return share; }); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(470); -/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(33); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(30); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(468); +/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(31); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(28); /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */ @@ -56005,13 +55921,13 @@ function share() { /***/ }), -/* 488 */ +/* 486 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return shareReplay; }); -/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(36); +/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(34); /** PURE_IMPORTS_START _ReplaySubject PURE_IMPORTS_END */ function shareReplay(configOrBufferSize, windowTime, scheduler) { @@ -56074,15 +55990,15 @@ function shareReplayOperator(_a) { /***/ }), -/* 489 */ +/* 487 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "single", function() { return single; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(66); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(64); /** PURE_IMPORTS_START tslib,_Subscriber,_util_EmptyError PURE_IMPORTS_END */ @@ -56154,14 +56070,14 @@ var SingleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 490 */ +/* 488 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return skip; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -56196,15 +56112,15 @@ var SkipSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 491 */ +/* 489 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return skipLast; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(65); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(63); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError PURE_IMPORTS_END */ @@ -56258,14 +56174,14 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 492 */ +/* 490 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return skipUntil; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -56315,14 +56231,14 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 493 */ +/* 491 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return skipWhile; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -56371,14 +56287,14 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 494 */ +/* 492 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return startWith; }); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(82); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(48); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(80); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(46); /** PURE_IMPORTS_START _observable_concat,_util_isScheduler PURE_IMPORTS_END */ @@ -56400,13 +56316,13 @@ function startWith() { /***/ }), -/* 495 */ +/* 493 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return subscribeOn; }); -/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(496); +/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(494); /** PURE_IMPORTS_START _observable_SubscribeOnObservable PURE_IMPORTS_END */ function subscribeOn(scheduler, delay) { @@ -56431,16 +56347,16 @@ var SubscribeOnOperator = /*@__PURE__*/ (function () { /***/ }), -/* 496 */ +/* 494 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubscribeOnObservable", function() { return SubscribeOnObservable; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); -/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(54); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(101); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10); +/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(52); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(99); /** PURE_IMPORTS_START tslib,_Observable,_scheduler_asap,_util_isNumeric PURE_IMPORTS_END */ @@ -56495,14 +56411,14 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) { /***/ }), -/* 497 */ +/* 495 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return switchAll; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(498); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(496); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(26); /** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */ @@ -56513,16 +56429,16 @@ function switchAll() { /***/ }), -/* 498 */ +/* 496 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return switchMap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(86); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(67); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(84); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_map,_observable_from,_innerSubscribe PURE_IMPORTS_END */ @@ -56601,13 +56517,13 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 499 */ +/* 497 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return switchMapTo; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(498); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(496); /** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */ function switchMapTo(innerObservable, resultSelector) { @@ -56617,14 +56533,14 @@ function switchMapTo(innerObservable, resultSelector) { /***/ }), -/* 500 */ +/* 498 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return takeUntil; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -56665,14 +56581,14 @@ var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 501 */ +/* 499 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return takeWhile; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -56733,16 +56649,16 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 502 */ +/* 500 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return tap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(63); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(61); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(14); /** PURE_IMPORTS_START tslib,_Subscriber,_util_noop,_util_isFunction PURE_IMPORTS_END */ @@ -56821,15 +56737,15 @@ var TapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 503 */ +/* 501 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultThrottleConfig", function() { return defaultThrottleConfig; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return throttle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_innerSubscribe PURE_IMPORTS_END */ @@ -56923,16 +56839,16 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 504 */ +/* 502 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return throttleTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(58); -/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(503); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(56); +/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(501); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */ @@ -57021,17 +56937,17 @@ function dispatchNext(arg) { /***/ }), -/* 505 */ +/* 503 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return timeInterval; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeInterval", function() { return TimeInterval; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(58); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(465); -/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(94); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(69); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(56); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(463); +/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(92); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(67); /** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */ @@ -57065,16 +56981,16 @@ var TimeInterval = /*@__PURE__*/ (function () { /***/ }), -/* 506 */ +/* 504 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return timeout; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(58); -/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(67); -/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(507); -/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(52); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(56); +/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(65); +/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(505); +/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(50); /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */ @@ -57090,16 +57006,16 @@ function timeout(due, scheduler) { /***/ }), -/* 507 */ +/* 505 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return timeoutWith; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(58); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(439); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(56); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(437); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_innerSubscribe PURE_IMPORTS_END */ @@ -57169,15 +57085,15 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 508 */ +/* 506 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return timestamp; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Timestamp", function() { return Timestamp; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(58); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(56); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(67); /** PURE_IMPORTS_START _scheduler_async,_map PURE_IMPORTS_END */ @@ -57199,13 +57115,13 @@ var Timestamp = /*@__PURE__*/ (function () { /***/ }), -/* 509 */ +/* 507 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return toArray; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(464); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(462); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function toArrayReducer(arr, item, index) { @@ -57222,15 +57138,15 @@ function toArray() { /***/ }), -/* 510 */ +/* 508 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "window", function() { return window; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(93); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_Subject,_innerSubscribe PURE_IMPORTS_END */ @@ -57300,15 +57216,15 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 511 */ +/* 509 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return windowCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(30); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(28); /** PURE_IMPORTS_START tslib,_Subscriber,_Subject PURE_IMPORTS_END */ @@ -57390,18 +57306,18 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 512 */ +/* 510 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return windowTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(58); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(14); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(101); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(48); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(56); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(99); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(46); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_async,_Subscriber,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -57560,17 +57476,17 @@ function dispatchWindowClose(state) { /***/ }), -/* 513 */ +/* 511 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return windowToggle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(72); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(73); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(18); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(70); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(71); /** PURE_IMPORTS_START tslib,_Subject,_Subscription,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -57703,16 +57619,16 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 514 */ +/* 512 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return windowWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(30); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(72); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(73); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(28); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(70); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(71); /** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -57800,15 +57716,15 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 515 */ +/* 513 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return withLatestFrom; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(72); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(73); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(70); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(71); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -57895,13 +57811,13 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 516 */ +/* 514 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; }); -/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(113); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(111); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zip() { @@ -57917,13 +57833,13 @@ function zip() { /***/ }), -/* 517 */ +/* 515 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return zipAll; }); -/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(113); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(111); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zipAll(project) { @@ -57933,7 +57849,7 @@ function zipAll(project) { /***/ }), -/* 518 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57943,7 +57859,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -var _observe_lines = __webpack_require__(519); +var _observe_lines = __webpack_require__(517); Object.keys(_observe_lines).forEach(function (key) { if (key === "default" || key === "__esModule") return; @@ -57956,7 +57872,7 @@ Object.keys(_observe_lines).forEach(function (key) { }); }); -var _observe_readable = __webpack_require__(520); +var _observe_readable = __webpack_require__(518); Object.keys(_observe_readable).forEach(function (key) { if (key === "default" || key === "__esModule") return; @@ -57970,24 +57886,26 @@ Object.keys(_observe_readable).forEach(function (key) { }); /***/ }), -/* 519 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var _interopRequireWildcard = __webpack_require__(7); - Object.defineProperty(exports, "__esModule", { value: true }); exports.observeLines = observeLines; -var Rx = _interopRequireWildcard(__webpack_require__(11)); +var Rx = _interopRequireWildcard(__webpack_require__(9)); + +var _operators = __webpack_require__(418); + +var _observe_readable = __webpack_require__(518); -var _operators = __webpack_require__(420); +function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } -var _observe_readable = __webpack_require__(520); +function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -58046,22 +57964,24 @@ function observeLines(readable) { } /***/ }), -/* 520 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var _interopRequireWildcard = __webpack_require__(7); - Object.defineProperty(exports, "__esModule", { value: true }); exports.observeReadable = observeReadable; -var Rx = _interopRequireWildcard(__webpack_require__(11)); +var Rx = _interopRequireWildcard(__webpack_require__(9)); + +var _operators = __webpack_require__(418); + +function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } -var _operators = __webpack_require__(420); +function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -58081,13 +58001,13 @@ function observeReadable(readable) { } /***/ }), -/* 521 */ +/* 519 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuildCommand", function() { return BuildCommand; }); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(415); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(413); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -58115,7 +58035,7 @@ const BuildCommand = { }; /***/ }), -/* 522 */ +/* 520 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58123,15 +58043,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); /* 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__(523); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(521); /* 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__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(415); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(233); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(222); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(413); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(231); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -58232,20 +58152,20 @@ const CleanCommand = { }; /***/ }), -/* 523 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readline = __webpack_require__(524); -const chalk = __webpack_require__(525); -const cliCursor = __webpack_require__(528); -const cliSpinners = __webpack_require__(530); -const logSymbols = __webpack_require__(532); -const stripAnsi = __webpack_require__(538); -const wcwidth = __webpack_require__(540); -const isInteractive = __webpack_require__(544); -const MuteStream = __webpack_require__(545); +const readline = __webpack_require__(522); +const chalk = __webpack_require__(523); +const cliCursor = __webpack_require__(526); +const cliSpinners = __webpack_require__(528); +const logSymbols = __webpack_require__(530); +const stripAnsi = __webpack_require__(536); +const wcwidth = __webpack_require__(538); +const isInteractive = __webpack_require__(542); +const MuteStream = __webpack_require__(543); const TEXT = Symbol('text'); const PREFIX_TEXT = Symbol('prefixText'); @@ -58598,23 +58518,23 @@ module.exports.promise = (action, options) => { /***/ }), -/* 524 */ +/* 522 */ /***/ (function(module, exports) { module.exports = require("readline"); /***/ }), -/* 525 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiStyles = __webpack_require__(117); -const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(123); +const ansiStyles = __webpack_require__(115); +const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(121); const { stringReplaceAll, stringEncaseCRLFWithFirstIndex -} = __webpack_require__(526); +} = __webpack_require__(524); // `supportsColor.level` → `ansiStyles.color[name]` mapping const levelMapping = [ @@ -58815,7 +58735,7 @@ const chalkTag = (chalk, ...strings) => { } if (template === undefined) { - template = __webpack_require__(527); + template = __webpack_require__(525); } return template(chalk, parts.join('')); @@ -58844,7 +58764,7 @@ module.exports = chalk; /***/ }), -/* 526 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58890,7 +58810,7 @@ module.exports = { /***/ }), -/* 527 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59031,12 +58951,12 @@ module.exports = (chalk, temporary) => { /***/ }), -/* 528 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(529); +const restoreCursor = __webpack_require__(527); let isHidden = false; @@ -59073,13 +58993,13 @@ exports.toggle = (force, writableStream) => { /***/ }), -/* 529 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(154); -const signalExit = __webpack_require__(163); +const onetime = __webpack_require__(152); +const signalExit = __webpack_require__(161); module.exports = onetime(() => { signalExit(() => { @@ -59089,13 +59009,13 @@ module.exports = onetime(() => { /***/ }), -/* 530 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const spinners = Object.assign({}, __webpack_require__(531)); +const spinners = Object.assign({}, __webpack_require__(529)); const spinnersList = Object.keys(spinners); @@ -59113,18 +59033,18 @@ module.exports.default = spinners; /***/ }), -/* 531 */ +/* 529 */ /***/ (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\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"dots8Bit\":{\"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\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"material\":{\"interval\":17,\"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\":[\"🌲\",\"🎄\"]},\"grenade\":{\"interval\":80,\"frames\":[\"، \",\"′ \",\" ´ \",\" ‾ \",\" ⸌\",\" ⸊\",\" |\",\" ⁎\",\" ⁕\",\" ෴ \",\" ⁓\",\" \",\" \",\" \"]},\"point\":{\"interval\":125,\"frames\":[\"∙∙∙\",\"●∙∙\",\"∙●∙\",\"∙∙●\",\"∙∙∙\"]},\"layer\":{\"interval\":150,\"frames\":[\"-\",\"=\",\"≡\"]},\"betaWave\":{\"interval\":80,\"frames\":[\"ρββββββ\",\"βρβββββ\",\"ββρββββ\",\"βββρβββ\",\"ββββρββ\",\"βββββρβ\",\"ββββββρ\"]},\"aesthetic\":{\"interval\":80,\"frames\":[\"▰▱▱▱▱▱▱\",\"▰▰▱▱▱▱▱\",\"▰▰▰▱▱▱▱\",\"▰▰▰▰▱▱▱\",\"▰▰▰▰▰▱▱\",\"▰▰▰▰▰▰▱\",\"▰▰▰▰▰▰▰\",\"▰▱▱▱▱▱▱\"]}}"); /***/ }), -/* 532 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(533); +const chalk = __webpack_require__(531); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -59146,16 +59066,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 533 */ +/* 531 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const escapeStringRegexp = __webpack_require__(359); -const ansiStyles = __webpack_require__(534); -const stdoutColor = __webpack_require__(535).stdout; +const escapeStringRegexp = __webpack_require__(357); +const ansiStyles = __webpack_require__(532); +const stdoutColor = __webpack_require__(533).stdout; -const template = __webpack_require__(537); +const template = __webpack_require__(535); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -59381,12 +59301,12 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 534 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(module) { -const colorConvert = __webpack_require__(361); +const colorConvert = __webpack_require__(359); const wrapAnsi16 = (fn, offset) => function () { const code = fn.apply(colorConvert, arguments); @@ -59551,16 +59471,16 @@ Object.defineProperty(module, 'exports', { get: assembleStyles }); -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(118)(module))) +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(116)(module))) /***/ }), -/* 535 */ +/* 533 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const os = __webpack_require__(124); -const hasFlag = __webpack_require__(536); +const os = __webpack_require__(122); +const hasFlag = __webpack_require__(534); const env = process.env; @@ -59692,7 +59612,7 @@ module.exports = { /***/ }), -/* 536 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59707,7 +59627,7 @@ module.exports = (flag, argv) => { /***/ }), -/* 537 */ +/* 535 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59842,18 +59762,18 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 538 */ +/* 536 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(539); +const ansiRegex = __webpack_require__(537); module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string; /***/ }), -/* 539 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59870,14 +59790,14 @@ module.exports = ({onlyFirst = false} = {}) => { /***/ }), -/* 540 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var defaults = __webpack_require__(541) -var combining = __webpack_require__(543) +var defaults = __webpack_require__(539) +var combining = __webpack_require__(541) var DEFAULTS = { nul: 0, @@ -59976,10 +59896,10 @@ function bisearch(ucs) { /***/ }), -/* 541 */ +/* 539 */ /***/ (function(module, exports, __webpack_require__) { -var clone = __webpack_require__(542); +var clone = __webpack_require__(540); module.exports = function(options, defaults) { options = options || {}; @@ -59994,7 +59914,7 @@ module.exports = function(options, defaults) { }; /***/ }), -/* 542 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { var clone = (function() { @@ -60166,7 +60086,7 @@ if ( true && module.exports) { /***/ }), -/* 543 */ +/* 541 */ /***/ (function(module, exports) { module.exports = [ @@ -60222,7 +60142,7 @@ module.exports = [ /***/ }), -/* 544 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60238,10 +60158,10 @@ module.exports = ({stream = process.stdout} = {}) => { /***/ }), -/* 545 */ +/* 543 */ /***/ (function(module, exports, __webpack_require__) { -var Stream = __webpack_require__(175) +var Stream = __webpack_require__(173) module.exports = MuteStream @@ -60389,7 +60309,7 @@ MuteStream.prototype.close = proxy('close') /***/ }), -/* 546 */ +/* 544 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60397,15 +60317,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ResetCommand", function() { return ResetCommand; }); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); /* 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__(523); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(521); /* 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__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(415); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(233); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(222); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(413); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(231); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -60512,7 +60432,7 @@ const ResetCommand = { }; /***/ }), -/* 547 */ +/* 545 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60520,10 +60440,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RunCommand", function() { return RunCommand; }); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(343); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(222); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(548); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(342); +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(341); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(220); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(546); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(340); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -60581,7 +60501,7 @@ const RunCommand = { }; /***/ }), -/* 548 */ +/* 546 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60636,13 +60556,13 @@ async function parallelize(items, fn, concurrency = 4) { } /***/ }), -/* 549 */ +/* 547 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchCommand", function() { return WatchCommand; }); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(415); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(413); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -60673,20 +60593,20 @@ const WatchCommand = { }; /***/ }), -/* 550 */ +/* 548 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); -/* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(133); +/* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(131); /* harmony import */ var _kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_ci_stats_reporter__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(343); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(222); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(342); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(414); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(551); -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; } +/* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(341); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(220); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(340); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(412); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(549); +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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -60803,7 +60723,7 @@ function toArray(value) { } /***/ }), -/* 551 */ +/* 549 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60811,16 +60731,16 @@ __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__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(134); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(132); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(552); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(550); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(335); +/* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(333); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(410); -/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(342); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(555); -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; } +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(408); +/* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(340); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(553); +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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -60983,15 +60903,15 @@ class Kibana { } /***/ }), -/* 552 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const minimatch = __webpack_require__(249); -const arrayUnion = __webpack_require__(244); -const arrayDiffer = __webpack_require__(553); -const arrify = __webpack_require__(554); +const minimatch = __webpack_require__(247); +const arrayUnion = __webpack_require__(242); +const arrayDiffer = __webpack_require__(551); +const arrify = __webpack_require__(552); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -61015,7 +60935,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 553 */ +/* 551 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61030,7 +60950,7 @@ module.exports = arrayDiffer; /***/ }), -/* 554 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61060,7 +60980,7 @@ module.exports = arrify; /***/ }), -/* 555 */ +/* 553 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -61120,15 +61040,15 @@ function getProjectPaths({ } /***/ }), -/* 556 */ +/* 554 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(557); +/* harmony import */ var _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(555); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildBazelProductionProjects"]; }); -/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(800); +/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(797); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__["buildNonBazelProductionProjects"]; }); /* @@ -61142,24 +61062,24 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 557 */ +/* 555 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return buildBazelProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(558); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(556); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(772); +/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(769); /* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(globby__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(800); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(415); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(233); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(222); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(345); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(342); +/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(797); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(413); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(231); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(343); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(340); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -61249,22 +61169,22 @@ async function applyCorrectPermissions(project, kibanaRoot, buildRoot) { } /***/ }), -/* 558 */ +/* 556 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const EventEmitter = __webpack_require__(166); +const EventEmitter = __webpack_require__(164); const path = __webpack_require__(4); -const os = __webpack_require__(124); -const pMap = __webpack_require__(559); -const arrify = __webpack_require__(554); -const globby = __webpack_require__(562); -const hasGlob = __webpack_require__(756); -const cpFile = __webpack_require__(758); -const junk = __webpack_require__(768); -const pFilter = __webpack_require__(769); -const CpyError = __webpack_require__(771); +const os = __webpack_require__(122); +const pMap = __webpack_require__(557); +const arrify = __webpack_require__(552); +const globby = __webpack_require__(560); +const hasGlob = __webpack_require__(753); +const cpFile = __webpack_require__(755); +const junk = __webpack_require__(765); +const pFilter = __webpack_require__(766); +const CpyError = __webpack_require__(768); const defaultOptions = { ignoreJunk: true @@ -61415,12 +61335,12 @@ module.exports = (source, destination, { /***/ }), -/* 559 */ +/* 557 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const AggregateError = __webpack_require__(560); +const AggregateError = __webpack_require__(558); module.exports = async ( iterable, @@ -61503,13 +61423,13 @@ module.exports = async ( /***/ }), -/* 560 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const indentString = __webpack_require__(561); -const cleanStack = __webpack_require__(340); +const indentString = __webpack_require__(559); +const cleanStack = __webpack_require__(338); const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); @@ -61557,7 +61477,7 @@ module.exports = AggregateError; /***/ }), -/* 561 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61599,17 +61519,17 @@ module.exports = (string, count = 1, options) => { /***/ }), -/* 562 */ +/* 560 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); -const arrayUnion = __webpack_require__(563); -const glob = __webpack_require__(246); -const fastGlob = __webpack_require__(565); -const dirGlob = __webpack_require__(749); -const gitignore = __webpack_require__(752); +const fs = __webpack_require__(132); +const arrayUnion = __webpack_require__(561); +const glob = __webpack_require__(244); +const fastGlob = __webpack_require__(563); +const dirGlob = __webpack_require__(746); +const gitignore = __webpack_require__(749); const DEFAULT_FILTER = () => false; @@ -61754,12 +61674,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 563 */ +/* 561 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(564); +var arrayUniq = __webpack_require__(562); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -61767,7 +61687,7 @@ module.exports = function () { /***/ }), -/* 564 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61836,10 +61756,10 @@ if ('Set' in global) { /***/ }), -/* 565 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(566); +const pkg = __webpack_require__(564); module.exports = pkg.async; module.exports.default = pkg.async; @@ -61852,19 +61772,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 566 */ +/* 564 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(567); -var taskManager = __webpack_require__(568); -var reader_async_1 = __webpack_require__(720); -var reader_stream_1 = __webpack_require__(744); -var reader_sync_1 = __webpack_require__(745); -var arrayUtils = __webpack_require__(747); -var streamUtils = __webpack_require__(748); +var optionsManager = __webpack_require__(565); +var taskManager = __webpack_require__(566); +var reader_async_1 = __webpack_require__(717); +var reader_stream_1 = __webpack_require__(741); +var reader_sync_1 = __webpack_require__(742); +var arrayUtils = __webpack_require__(744); +var streamUtils = __webpack_require__(745); /** * Synchronous API. */ @@ -61930,7 +61850,7 @@ function isString(source) { /***/ }), -/* 567 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61968,13 +61888,13 @@ exports.prepare = prepare; /***/ }), -/* 568 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(569); +var patternUtils = __webpack_require__(567); /** * Generate tasks based on parent directory of each pattern. */ @@ -62065,16 +61985,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 569 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var globParent = __webpack_require__(570); -var isGlob = __webpack_require__(268); -var micromatch = __webpack_require__(573); +var globParent = __webpack_require__(568); +var isGlob = __webpack_require__(266); +var micromatch = __webpack_require__(571); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -62220,16 +62140,16 @@ exports.matchAny = matchAny; /***/ }), -/* 570 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(4); -var isglob = __webpack_require__(571); -var pathDirname = __webpack_require__(572); -var isWin32 = __webpack_require__(124).platform() === 'win32'; +var isglob = __webpack_require__(569); +var pathDirname = __webpack_require__(570); +var isWin32 = __webpack_require__(122).platform() === 'win32'; module.exports = function globParent(str) { // flip windows path separators @@ -62251,7 +62171,7 @@ module.exports = function globParent(str) { /***/ }), -/* 571 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -62261,7 +62181,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(269); +var isExtglob = __webpack_require__(267); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -62282,14 +62202,14 @@ module.exports = function isGlob(str) { /***/ }), -/* 572 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(4); -var inspect = __webpack_require__(115).inspect; +var inspect = __webpack_require__(113).inspect; function assertPath(path) { if (typeof path !== 'string') { @@ -62432,7 +62352,7 @@ module.exports.win32 = win32; /***/ }), -/* 573 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62442,19 +62362,19 @@ module.exports.win32 = win32; * Module dependencies */ -var util = __webpack_require__(115); -var braces = __webpack_require__(574); -var toRegex = __webpack_require__(575); -var extend = __webpack_require__(686); +var util = __webpack_require__(113); +var braces = __webpack_require__(572); +var toRegex = __webpack_require__(573); +var extend = __webpack_require__(685); /** * Local dependencies */ -var compilers = __webpack_require__(688); -var parsers = __webpack_require__(715); -var cache = __webpack_require__(716); -var utils = __webpack_require__(717); +var compilers = __webpack_require__(687); +var parsers = __webpack_require__(713); +var cache = __webpack_require__(714); +var utils = __webpack_require__(715); var MAX_LENGTH = 1024 * 64; /** @@ -63316,7 +63236,7 @@ module.exports = micromatch; /***/ }), -/* 574 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63326,18 +63246,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(575); -var unique = __webpack_require__(597); -var extend = __webpack_require__(598); +var toRegex = __webpack_require__(573); +var unique = __webpack_require__(593); +var extend = __webpack_require__(594); /** * Local dependencies */ -var compilers = __webpack_require__(600); -var parsers = __webpack_require__(615); -var Braces = __webpack_require__(619); -var utils = __webpack_require__(601); +var compilers = __webpack_require__(596); +var parsers = __webpack_require__(611); +var Braces = __webpack_require__(616); +var utils = __webpack_require__(597); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -63641,16 +63561,16 @@ module.exports = braces; /***/ }), -/* 575 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(576); -var define = __webpack_require__(582); -var extend = __webpack_require__(590); -var not = __webpack_require__(594); +var safe = __webpack_require__(574); +var define = __webpack_require__(580); +var extend = __webpack_require__(586); +var not = __webpack_require__(590); var MAX_LENGTH = 1024 * 64; /** @@ -63803,10 +63723,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 576 */ +/* 574 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(577); +var parse = __webpack_require__(575); var types = parse.types; module.exports = function (re, opts) { @@ -63852,13 +63772,13 @@ function isRegExp (x) { /***/ }), -/* 577 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(578); -var types = __webpack_require__(579); -var sets = __webpack_require__(580); -var positions = __webpack_require__(581); +var util = __webpack_require__(576); +var types = __webpack_require__(577); +var sets = __webpack_require__(578); +var positions = __webpack_require__(579); module.exports = function(regexpStr) { @@ -64140,11 +64060,11 @@ module.exports.types = types; /***/ }), -/* 578 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(579); -var sets = __webpack_require__(580); +var types = __webpack_require__(577); +var sets = __webpack_require__(578); // All of these are private and only used by randexp. @@ -64257,7 +64177,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 579 */ +/* 577 */ /***/ (function(module, exports) { module.exports = { @@ -64273,10 +64193,10 @@ module.exports = { /***/ }), -/* 580 */ +/* 578 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(579); +var types = __webpack_require__(577); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -64361,10 +64281,10 @@ exports.anyChar = function() { /***/ }), -/* 581 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(579); +var types = __webpack_require__(577); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -64384,7 +64304,7 @@ exports.end = function() { /***/ }), -/* 582 */ +/* 580 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64397,8 +64317,8 @@ exports.end = function() { -var isobject = __webpack_require__(583); -var isDescriptor = __webpack_require__(584); +var isobject = __webpack_require__(581); +var isDescriptor = __webpack_require__(582); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -64429,7 +64349,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 583 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64448,7 +64368,7 @@ module.exports = function isObject(val) { /***/ }), -/* 584 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64461,9 +64381,9 @@ module.exports = function isObject(val) { -var typeOf = __webpack_require__(585); -var isAccessor = __webpack_require__(586); -var isData = __webpack_require__(588); +var typeOf = __webpack_require__(583); +var isAccessor = __webpack_require__(584); +var isData = __webpack_require__(585); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -64477,7 +64397,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 585 */ +/* 583 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -64612,7 +64532,7 @@ function isBuffer(val) { /***/ }), -/* 586 */ +/* 584 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64625,7 +64545,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(587); +var typeOf = __webpack_require__(583); // accessor descriptor properties var accessor = { @@ -64688,142 +64608,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 587 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 588 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64836,7 +64621,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(589); +var typeOf = __webpack_require__(583); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -64879,149 +64664,14 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 589 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 590 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(591); -var assignSymbols = __webpack_require__(593); +var isExtendable = __webpack_require__(587); +var assignSymbols = __webpack_require__(589); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -65081,7 +64731,7 @@ function isEnum(obj, key) { /***/ }), -/* 591 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65094,7 +64744,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(592); +var isPlainObject = __webpack_require__(588); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -65102,7 +64752,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 592 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65115,7 +64765,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(583); +var isObject = __webpack_require__(581); function isObjectObject(o) { return isObject(o) === true @@ -65146,7 +64796,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 593 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65193,14 +64843,14 @@ module.exports = function(receiver, objects) { /***/ }), -/* 594 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(595); -var safe = __webpack_require__(576); +var extend = __webpack_require__(591); +var safe = __webpack_require__(574); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -65272,14 +64922,14 @@ module.exports = toRegex; /***/ }), -/* 595 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(596); -var assignSymbols = __webpack_require__(593); +var isExtendable = __webpack_require__(592); +var assignSymbols = __webpack_require__(589); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -65339,7 +64989,7 @@ function isEnum(obj, key) { /***/ }), -/* 596 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65352,7 +65002,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(592); +var isPlainObject = __webpack_require__(588); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -65360,7 +65010,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 597 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65410,13 +65060,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 598 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(599); +var isObject = __webpack_require__(595); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -65450,7 +65100,7 @@ function hasOwn(obj, key) { /***/ }), -/* 599 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65470,13 +65120,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 600 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(601); +var utils = __webpack_require__(597); module.exports = function(braces, options) { braces.compiler @@ -65759,25 +65409,25 @@ function hasQueue(node) { /***/ }), -/* 601 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(602); +var splitString = __webpack_require__(598); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(598); -utils.flatten = __webpack_require__(605); -utils.isObject = __webpack_require__(583); -utils.fillRange = __webpack_require__(606); -utils.repeat = __webpack_require__(614); -utils.unique = __webpack_require__(597); +utils.extend = __webpack_require__(594); +utils.flatten = __webpack_require__(601); +utils.isObject = __webpack_require__(581); +utils.fillRange = __webpack_require__(602); +utils.repeat = __webpack_require__(610); +utils.unique = __webpack_require__(593); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -66109,7 +65759,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 602 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66122,7 +65772,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(603); +var extend = __webpack_require__(599); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -66287,14 +65937,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 603 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(604); -var assignSymbols = __webpack_require__(593); +var isExtendable = __webpack_require__(600); +var assignSymbols = __webpack_require__(589); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -66354,7 +66004,7 @@ function isEnum(obj, key) { /***/ }), -/* 604 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66367,7 +66017,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(592); +var isPlainObject = __webpack_require__(588); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -66375,7 +66025,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 605 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66404,7 +66054,7 @@ function flat(arr, res) { /***/ }), -/* 606 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66417,11 +66067,11 @@ function flat(arr, res) { -var util = __webpack_require__(115); -var isNumber = __webpack_require__(607); -var extend = __webpack_require__(610); -var repeat = __webpack_require__(612); -var toRegex = __webpack_require__(613); +var util = __webpack_require__(113); +var isNumber = __webpack_require__(603); +var extend = __webpack_require__(606); +var repeat = __webpack_require__(608); +var toRegex = __webpack_require__(609); /** * Return a range of numbers or letters. @@ -66619,7 +66269,7 @@ module.exports = fillRange; /***/ }), -/* 607 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66632,7 +66282,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(608); +var typeOf = __webpack_require__(604); module.exports = function isNumber(num) { var type = typeOf(num); @@ -66648,10 +66298,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 608 */ +/* 604 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(609); +var isBuffer = __webpack_require__(605); var toString = Object.prototype.toString; /** @@ -66770,7 +66420,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 609 */ +/* 605 */ /***/ (function(module, exports) { /*! @@ -66797,13 +66447,13 @@ function isSlowBuffer (obj) { /***/ }), -/* 610 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(611); +var isObject = __webpack_require__(607); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -66837,7 +66487,7 @@ function hasOwn(obj, key) { /***/ }), -/* 611 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66857,7 +66507,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 612 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66934,7 +66584,7 @@ function repeat(str, num) { /***/ }), -/* 613 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66947,8 +66597,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(612); -var isNumber = __webpack_require__(607); +var repeat = __webpack_require__(608); +var isNumber = __webpack_require__(603); var cache = {}; function toRegexRange(min, max, options) { @@ -67235,7 +66885,7 @@ module.exports = toRegexRange; /***/ }), -/* 614 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67260,14 +66910,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 615 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(616); -var utils = __webpack_require__(601); +var Node = __webpack_require__(612); +var utils = __webpack_require__(597); /** * Braces parsers @@ -67627,15 +67277,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 616 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(583); -var define = __webpack_require__(617); -var utils = __webpack_require__(618); +var isObject = __webpack_require__(581); +var define = __webpack_require__(613); +var utils = __webpack_require__(614); var ownNames; /** @@ -68126,7 +67776,7 @@ exports = module.exports = Node; /***/ }), -/* 617 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68139,7 +67789,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(584); +var isDescriptor = __webpack_require__(582); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -68164,13 +67814,13 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 618 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(608); +var typeOf = __webpack_require__(615); var utils = module.exports; /** @@ -69190,17 +68840,139 @@ function assert(val, message) { /***/ }), -/* 619 */ +/* 615 */ +/***/ (function(module, exports, __webpack_require__) { + +var isBuffer = __webpack_require__(605); +var toString = Object.prototype.toString; + +/** + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type + */ + +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } + + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } + + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } + + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } + + // other objects + var type = toString.call(val); + + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } + + // buffer + if (isBuffer(val)) { + return 'buffer'; + } + + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } + + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } + + // must be a plain object + return 'object'; +}; + + +/***/ }), +/* 616 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(598); -var Snapdragon = __webpack_require__(620); -var compilers = __webpack_require__(600); -var parsers = __webpack_require__(615); -var utils = __webpack_require__(601); +var extend = __webpack_require__(594); +var Snapdragon = __webpack_require__(617); +var compilers = __webpack_require__(596); +var parsers = __webpack_require__(611); +var utils = __webpack_require__(597); /** * Customize Snapdragon parser and renderer @@ -69301,17 +69073,17 @@ module.exports = Braces; /***/ }), -/* 620 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(621); -var define = __webpack_require__(650); -var Compiler = __webpack_require__(660); -var Parser = __webpack_require__(683); -var utils = __webpack_require__(663); +var Base = __webpack_require__(618); +var define = __webpack_require__(648); +var Compiler = __webpack_require__(659); +var Parser = __webpack_require__(682); +var utils = __webpack_require__(662); var regexCache = {}; var cache = {}; @@ -69482,20 +69254,20 @@ module.exports.Parser = Parser; /***/ }), -/* 621 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var util = __webpack_require__(115); -var define = __webpack_require__(622); -var CacheBase = __webpack_require__(623); -var Emitter = __webpack_require__(624); -var isObject = __webpack_require__(583); -var merge = __webpack_require__(644); -var pascal = __webpack_require__(647); -var cu = __webpack_require__(648); +var util = __webpack_require__(113); +var define = __webpack_require__(619); +var CacheBase = __webpack_require__(620); +var Emitter = __webpack_require__(621); +var isObject = __webpack_require__(581); +var merge = __webpack_require__(642); +var pascal = __webpack_require__(645); +var cu = __webpack_require__(646); /** * Optionally define a custom `cache` namespace to use. @@ -69924,7 +69696,7 @@ module.exports.namespace = namespace; /***/ }), -/* 622 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69937,7 +69709,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(584); +var isDescriptor = __webpack_require__(582); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -69962,21 +69734,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 623 */ +/* 620 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(583); -var Emitter = __webpack_require__(624); -var visit = __webpack_require__(625); -var toPath = __webpack_require__(628); -var union = __webpack_require__(629); -var del = __webpack_require__(635); -var get = __webpack_require__(632); -var has = __webpack_require__(640); -var set = __webpack_require__(643); +var isObject = __webpack_require__(581); +var Emitter = __webpack_require__(621); +var visit = __webpack_require__(622); +var toPath = __webpack_require__(625); +var union = __webpack_require__(627); +var del = __webpack_require__(633); +var get = __webpack_require__(630); +var has = __webpack_require__(638); +var set = __webpack_require__(641); /** * Create a `Cache` constructor that when instantiated will @@ -70230,7 +70002,7 @@ module.exports.namespace = namespace; /***/ }), -/* 624 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { @@ -70399,7 +70171,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 625 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70412,8 +70184,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(626); -var mapVisit = __webpack_require__(627); +var visit = __webpack_require__(623); +var mapVisit = __webpack_require__(624); module.exports = function(collection, method, val) { var result; @@ -70436,7 +70208,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 626 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70449,7 +70221,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(583); +var isObject = __webpack_require__(581); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -70476,14 +70248,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 627 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var util = __webpack_require__(115); -var visit = __webpack_require__(626); +var util = __webpack_require__(113); +var visit = __webpack_require__(623); /** * Map `visit` over an array of objects. @@ -70520,7 +70292,7 @@ function isObject(val) { /***/ }), -/* 628 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70533,7 +70305,7 @@ function isObject(val) { -var typeOf = __webpack_require__(608); +var typeOf = __webpack_require__(626); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -70560,16 +70332,138 @@ function filter(arr) { /***/ }), -/* 629 */ +/* 626 */ +/***/ (function(module, exports, __webpack_require__) { + +var isBuffer = __webpack_require__(605); +var toString = Object.prototype.toString; + +/** + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type + */ + +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } + + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } + + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } + + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } + + // other objects + var type = toString.call(val); + + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } + + // buffer + if (isBuffer(val)) { + return 'buffer'; + } + + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } + + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } + + // must be a plain object + return 'object'; +}; + + +/***/ }), +/* 627 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(630); -var union = __webpack_require__(631); -var get = __webpack_require__(632); -var set = __webpack_require__(633); +var isObject = __webpack_require__(628); +var union = __webpack_require__(629); +var get = __webpack_require__(630); +var set = __webpack_require__(631); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -70597,7 +70491,7 @@ function arrayify(val) { /***/ }), -/* 630 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70617,7 +70511,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 631 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70653,7 +70547,7 @@ module.exports = function union(init) { /***/ }), -/* 632 */ +/* 630 */ /***/ (function(module, exports) { /*! @@ -70709,7 +70603,7 @@ function toString(val) { /***/ }), -/* 633 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70722,10 +70616,10 @@ function toString(val) { -var split = __webpack_require__(602); -var extend = __webpack_require__(634); -var isPlainObject = __webpack_require__(592); -var isObject = __webpack_require__(630); +var split = __webpack_require__(598); +var extend = __webpack_require__(632); +var isPlainObject = __webpack_require__(588); +var isObject = __webpack_require__(628); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -70771,13 +70665,13 @@ function isValidKey(key) { /***/ }), -/* 634 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(630); +var isObject = __webpack_require__(628); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -70811,7 +70705,7 @@ function hasOwn(obj, key) { /***/ }), -/* 635 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70824,8 +70718,8 @@ function hasOwn(obj, key) { -var isObject = __webpack_require__(583); -var has = __webpack_require__(636); +var isObject = __webpack_require__(581); +var has = __webpack_require__(634); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -70850,7 +70744,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 636 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70863,9 +70757,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(637); -var hasValues = __webpack_require__(639); -var get = __webpack_require__(632); +var isObject = __webpack_require__(635); +var hasValues = __webpack_require__(637); +var get = __webpack_require__(630); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -70876,7 +70770,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 637 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70889,7 +70783,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(638); +var isArray = __webpack_require__(636); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -70897,7 +70791,7 @@ module.exports = function isObject(val) { /***/ }), -/* 638 */ +/* 636 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -70908,7 +70802,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 639 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70951,7 +70845,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 640 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70964,9 +70858,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(583); -var hasValues = __webpack_require__(641); -var get = __webpack_require__(632); +var isObject = __webpack_require__(581); +var hasValues = __webpack_require__(639); +var get = __webpack_require__(630); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -70974,7 +70868,7 @@ module.exports = function(val, prop) { /***/ }), -/* 641 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70987,8 +70881,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(642); -var isNumber = __webpack_require__(607); +var typeOf = __webpack_require__(640); +var isNumber = __webpack_require__(603); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -71041,10 +70935,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 642 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(609); +var isBuffer = __webpack_require__(605); var toString = Object.prototype.toString; /** @@ -71166,7 +71060,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 643 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71179,10 +71073,10 @@ module.exports = function kindOf(val) { -var split = __webpack_require__(602); -var extend = __webpack_require__(634); -var isPlainObject = __webpack_require__(592); -var isObject = __webpack_require__(630); +var split = __webpack_require__(598); +var extend = __webpack_require__(632); +var isPlainObject = __webpack_require__(588); +var isObject = __webpack_require__(628); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -71228,14 +71122,14 @@ function isValidKey(key) { /***/ }), -/* 644 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(645); -var forIn = __webpack_require__(646); +var isExtendable = __webpack_require__(643); +var forIn = __webpack_require__(644); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -71299,7 +71193,7 @@ module.exports = mixinDeep; /***/ }), -/* 645 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71312,7 +71206,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(592); +var isPlainObject = __webpack_require__(588); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -71320,7 +71214,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 646 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71343,7 +71237,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 647 */ +/* 645 */ /***/ (function(module, exports) { /*! @@ -71370,14 +71264,14 @@ module.exports = pascalcase; /***/ }), -/* 648 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var util = __webpack_require__(115); -var utils = __webpack_require__(649); +var util = __webpack_require__(113); +var utils = __webpack_require__(647); /** * Expose class utils @@ -71742,7 +71636,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 649 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71756,10 +71650,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(631); -utils.define = __webpack_require__(650); -utils.isObj = __webpack_require__(583); -utils.staticExtend = __webpack_require__(657); +utils.union = __webpack_require__(629); +utils.define = __webpack_require__(648); +utils.isObj = __webpack_require__(581); +utils.staticExtend = __webpack_require__(655); /** @@ -71770,7 +71664,7 @@ module.exports = utils; /***/ }), -/* 650 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71783,7 +71677,7 @@ module.exports = utils; -var isDescriptor = __webpack_require__(651); +var isDescriptor = __webpack_require__(649); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -71808,7 +71702,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 651 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71821,9 +71715,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(652); -var isAccessor = __webpack_require__(653); -var isData = __webpack_require__(655); +var typeOf = __webpack_require__(650); +var isAccessor = __webpack_require__(651); +var isData = __webpack_require__(653); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -71837,7 +71731,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 652 */ +/* 650 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -71990,7 +71884,7 @@ function isBuffer(val) { /***/ }), -/* 653 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72003,7 +71897,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(654); +var typeOf = __webpack_require__(652); // accessor descriptor properties var accessor = { @@ -72065,11 +71959,195 @@ function has(obj, key) { module.exports = isAccessorDescriptor; +/***/ }), +/* 652 */ +/***/ (function(module, exports, __webpack_require__) { + +var isBuffer = __webpack_require__(605); +var toString = Object.prototype.toString; + +/** + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type + */ + +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } + + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } + + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } + + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } + + // other objects + var type = toString.call(val); + + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } + + // buffer + if (isBuffer(val)) { + return 'buffer'; + } + + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } + + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } + + // must be a plain object + return 'object'; +}; + + +/***/ }), +/* 653 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-data-descriptor + * + * Copyright (c) 2015, Jon Schlinkert. + * Licensed under the MIT License. + */ + + + +var typeOf = __webpack_require__(654); + +// data descriptor properties +var data = { + configurable: 'boolean', + enumerable: 'boolean', + writable: 'boolean' +}; + +function isDataDescriptor(obj, prop) { + if (typeOf(obj) !== 'object') { + return false; + } + + if (typeof prop === 'string') { + var val = Object.getOwnPropertyDescriptor(obj, prop); + return typeof val !== 'undefined'; + } + + if (!('value' in obj) && !('writable' in obj)) { + return false; + } + + for (var key in obj) { + if (key === 'value') continue; + + if (!data.hasOwnProperty(key)) { + continue; + } + + if (typeOf(obj[key]) === data[key]) { + continue; + } + + if (typeof obj[key] !== 'undefined') { + return false; + } + } + return true; +} + +/** + * Expose `isDataDescriptor` + */ + +module.exports = isDataDescriptor; + + /***/ }), /* 654 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(609); +var isBuffer = __webpack_require__(605); var toString = Object.prototype.toString; /** @@ -72191,190 +72269,6 @@ module.exports = function kindOf(val) { /* 655 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; -/*! - * is-data-descriptor - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -var typeOf = __webpack_require__(656); - -// data descriptor properties -var data = { - configurable: 'boolean', - enumerable: 'boolean', - writable: 'boolean' -}; - -function isDataDescriptor(obj, prop) { - if (typeOf(obj) !== 'object') { - return false; - } - - if (typeof prop === 'string') { - var val = Object.getOwnPropertyDescriptor(obj, prop); - return typeof val !== 'undefined'; - } - - if (!('value' in obj) && !('writable' in obj)) { - return false; - } - - for (var key in obj) { - if (key === 'value') continue; - - if (!data.hasOwnProperty(key)) { - continue; - } - - if (typeOf(obj[key]) === data[key]) { - continue; - } - - if (typeof obj[key] !== 'undefined') { - return false; - } - } - return true; -} - -/** - * Expose `isDataDescriptor` - */ - -module.exports = isDataDescriptor; - - -/***/ }), -/* 656 */ -/***/ (function(module, exports, __webpack_require__) { - -var isBuffer = __webpack_require__(609); -var toString = Object.prototype.toString; - -/** - * Get the native `typeof` a value. - * - * @param {*} `val` - * @return {*} Native javascript type - */ - -module.exports = function kindOf(val) { - // primitivies - if (typeof val === 'undefined') { - return 'undefined'; - } - if (val === null) { - return 'null'; - } - if (val === true || val === false || val instanceof Boolean) { - return 'boolean'; - } - if (typeof val === 'string' || val instanceof String) { - return 'string'; - } - if (typeof val === 'number' || val instanceof Number) { - return 'number'; - } - - // functions - if (typeof val === 'function' || val instanceof Function) { - return 'function'; - } - - // array - if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { - return 'array'; - } - - // check for instances of RegExp and Date before calling `toString` - if (val instanceof RegExp) { - return 'regexp'; - } - if (val instanceof Date) { - return 'date'; - } - - // other objects - var type = toString.call(val); - - if (type === '[object RegExp]') { - return 'regexp'; - } - if (type === '[object Date]') { - return 'date'; - } - if (type === '[object Arguments]') { - return 'arguments'; - } - if (type === '[object Error]') { - return 'error'; - } - - // buffer - if (isBuffer(val)) { - return 'buffer'; - } - - // es6: Map, WeakMap, Set, WeakSet - if (type === '[object Set]') { - return 'set'; - } - if (type === '[object WeakSet]') { - return 'weakset'; - } - if (type === '[object Map]') { - return 'map'; - } - if (type === '[object WeakMap]') { - return 'weakmap'; - } - if (type === '[object Symbol]') { - return 'symbol'; - } - - // typed arrays - if (type === '[object Int8Array]') { - return 'int8array'; - } - if (type === '[object Uint8Array]') { - return 'uint8array'; - } - if (type === '[object Uint8ClampedArray]') { - return 'uint8clampedarray'; - } - if (type === '[object Int16Array]') { - return 'int16array'; - } - if (type === '[object Uint16Array]') { - return 'uint16array'; - } - if (type === '[object Int32Array]') { - return 'int32array'; - } - if (type === '[object Uint32Array]') { - return 'uint32array'; - } - if (type === '[object Float32Array]') { - return 'float32array'; - } - if (type === '[object Float64Array]') { - return 'float64array'; - } - - // must be a plain object - return 'object'; -}; - - -/***/ }), -/* 657 */ -/***/ (function(module, exports, __webpack_require__) { - "use strict"; /*! * static-extend @@ -72385,9 +72279,9 @@ module.exports = function kindOf(val) { -var copy = __webpack_require__(658); -var define = __webpack_require__(650); -var util = __webpack_require__(115); +var copy = __webpack_require__(656); +var define = __webpack_require__(648); +var util = __webpack_require__(113); /** * Returns a function for extending the static properties, @@ -72469,15 +72363,15 @@ module.exports = extend; /***/ }), -/* 658 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(608); -var copyDescriptor = __webpack_require__(659); -var define = __webpack_require__(650); +var typeOf = __webpack_require__(657); +var copyDescriptor = __webpack_require__(658); +var define = __webpack_require__(648); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -72650,7 +72544,129 @@ module.exports.has = has; /***/ }), -/* 659 */ +/* 657 */ +/***/ (function(module, exports, __webpack_require__) { + +var isBuffer = __webpack_require__(605); +var toString = Object.prototype.toString; + +/** + * Get the native `typeof` a value. + * + * @param {*} `val` + * @return {*} Native javascript type + */ + +module.exports = function kindOf(val) { + // primitivies + if (typeof val === 'undefined') { + return 'undefined'; + } + if (val === null) { + return 'null'; + } + if (val === true || val === false || val instanceof Boolean) { + return 'boolean'; + } + if (typeof val === 'string' || val instanceof String) { + return 'string'; + } + if (typeof val === 'number' || val instanceof Number) { + return 'number'; + } + + // functions + if (typeof val === 'function' || val instanceof Function) { + return 'function'; + } + + // array + if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { + return 'array'; + } + + // check for instances of RegExp and Date before calling `toString` + if (val instanceof RegExp) { + return 'regexp'; + } + if (val instanceof Date) { + return 'date'; + } + + // other objects + var type = toString.call(val); + + if (type === '[object RegExp]') { + return 'regexp'; + } + if (type === '[object Date]') { + return 'date'; + } + if (type === '[object Arguments]') { + return 'arguments'; + } + if (type === '[object Error]') { + return 'error'; + } + + // buffer + if (isBuffer(val)) { + return 'buffer'; + } + + // es6: Map, WeakMap, Set, WeakSet + if (type === '[object Set]') { + return 'set'; + } + if (type === '[object WeakSet]') { + return 'weakset'; + } + if (type === '[object Map]') { + return 'map'; + } + if (type === '[object WeakMap]') { + return 'weakmap'; + } + if (type === '[object Symbol]') { + return 'symbol'; + } + + // typed arrays + if (type === '[object Int8Array]') { + return 'int8array'; + } + if (type === '[object Uint8Array]') { + return 'uint8array'; + } + if (type === '[object Uint8ClampedArray]') { + return 'uint8clampedarray'; + } + if (type === '[object Int16Array]') { + return 'int16array'; + } + if (type === '[object Uint16Array]') { + return 'uint16array'; + } + if (type === '[object Int32Array]') { + return 'int32array'; + } + if (type === '[object Uint32Array]') { + return 'uint32array'; + } + if (type === '[object Float32Array]') { + return 'float32array'; + } + if (type === '[object Float64Array]') { + return 'float64array'; + } + + // must be a plain object + return 'object'; +}; + + +/***/ }), +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72738,16 +72754,16 @@ function isObject(val) { /***/ }), -/* 660 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(661); -var define = __webpack_require__(650); -var debug = __webpack_require__(207)('snapdragon:compiler'); -var utils = __webpack_require__(663); +var use = __webpack_require__(660); +var define = __webpack_require__(648); +var debug = __webpack_require__(205)('snapdragon:compiler'); +var utils = __webpack_require__(662); /** * Create a new `Compiler` with the given `options`. @@ -72901,7 +72917,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(682); + var sourcemaps = __webpack_require__(681); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -72922,7 +72938,7 @@ module.exports = Compiler; /***/ }), -/* 661 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72935,7 +72951,7 @@ module.exports = Compiler; -var utils = __webpack_require__(662); +var utils = __webpack_require__(661); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -73050,7 +73066,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 662 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73064,8 +73080,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(650); -utils.isObject = __webpack_require__(583); +utils.define = __webpack_require__(648); +utils.isObject = __webpack_require__(581); utils.isString = function(val) { @@ -73080,7 +73096,7 @@ module.exports = utils; /***/ }), -/* 663 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73090,9 +73106,9 @@ module.exports = utils; * Module dependencies */ -exports.extend = __webpack_require__(634); -exports.SourceMap = __webpack_require__(664); -exports.sourceMapResolve = __webpack_require__(675); +exports.extend = __webpack_require__(632); +exports.SourceMap = __webpack_require__(663); +exports.sourceMapResolve = __webpack_require__(674); /** * Convert backslash in the given string to forward slashes @@ -73135,7 +73151,7 @@ exports.last = function(arr, n) { /***/ }), -/* 664 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -73143,13 +73159,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__(665).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(671).SourceMapConsumer; -exports.SourceNode = __webpack_require__(674).SourceNode; +exports.SourceMapGenerator = __webpack_require__(664).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(670).SourceMapConsumer; +exports.SourceNode = __webpack_require__(673).SourceNode; /***/ }), -/* 665 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73159,10 +73175,10 @@ exports.SourceNode = __webpack_require__(674).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(666); -var util = __webpack_require__(668); -var ArraySet = __webpack_require__(669).ArraySet; -var MappingList = __webpack_require__(670).MappingList; +var base64VLQ = __webpack_require__(665); +var util = __webpack_require__(667); +var ArraySet = __webpack_require__(668).ArraySet; +var MappingList = __webpack_require__(669).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -73571,7 +73587,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 666 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73611,7 +73627,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(667); +var base64 = __webpack_require__(666); // 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, @@ -73717,7 +73733,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 667 */ +/* 666 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73790,7 +73806,7 @@ exports.decode = function (charCode) { /***/ }), -/* 668 */ +/* 667 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74213,7 +74229,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 669 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74223,7 +74239,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(668); +var util = __webpack_require__(667); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -74340,7 +74356,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 670 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74350,7 +74366,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(668); +var util = __webpack_require__(667); /** * Determine whether mappingB is after mappingA with respect to generated @@ -74425,7 +74441,7 @@ exports.MappingList = MappingList; /***/ }), -/* 671 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74435,11 +74451,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(668); -var binarySearch = __webpack_require__(672); -var ArraySet = __webpack_require__(669).ArraySet; -var base64VLQ = __webpack_require__(666); -var quickSort = __webpack_require__(673).quickSort; +var util = __webpack_require__(667); +var binarySearch = __webpack_require__(671); +var ArraySet = __webpack_require__(668).ArraySet; +var base64VLQ = __webpack_require__(665); +var quickSort = __webpack_require__(672).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -75513,7 +75529,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 672 */ +/* 671 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -75630,7 +75646,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 673 */ +/* 672 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -75750,7 +75766,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 674 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -75760,8 +75776,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(665).SourceMapGenerator; -var util = __webpack_require__(668); +var SourceMapGenerator = __webpack_require__(664).SourceMapGenerator; +var util = __webpack_require__(667); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -76169,17 +76185,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 675 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(676) -var resolveUrl = __webpack_require__(677) -var decodeUriComponent = __webpack_require__(678) -var urix = __webpack_require__(680) -var atob = __webpack_require__(681) +var sourceMappingURL = __webpack_require__(675) +var resolveUrl = __webpack_require__(676) +var decodeUriComponent = __webpack_require__(677) +var urix = __webpack_require__(679) +var atob = __webpack_require__(680) @@ -76477,7 +76493,7 @@ module.exports = { /***/ }), -/* 676 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -76540,13 +76556,13 @@ void (function(root, factory) { /***/ }), -/* 677 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var url = __webpack_require__(205) +var url = __webpack_require__(203) function resolveUrl(/* ...urls */) { return Array.prototype.reduce.call(arguments, function(resolved, nextUrl) { @@ -76558,13 +76574,13 @@ module.exports = resolveUrl /***/ }), -/* 678 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(679) +var decodeUriComponent = __webpack_require__(678) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -76575,7 +76591,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 679 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76676,7 +76692,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 680 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -76699,7 +76715,7 @@ module.exports = urix /***/ }), -/* 681 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76713,16 +76729,16 @@ module.exports = atob.atob = atob; /***/ }), -/* 682 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var fs = __webpack_require__(134); +var fs = __webpack_require__(132); var path = __webpack_require__(4); -var define = __webpack_require__(650); -var utils = __webpack_require__(663); +var define = __webpack_require__(648); +var utils = __webpack_require__(662); /** * Expose `mixin()`. @@ -76865,19 +76881,19 @@ exports.comment = function(node) { /***/ }), -/* 683 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(661); -var util = __webpack_require__(115); -var Cache = __webpack_require__(684); -var define = __webpack_require__(650); -var debug = __webpack_require__(207)('snapdragon:parser'); -var Position = __webpack_require__(685); -var utils = __webpack_require__(663); +var use = __webpack_require__(660); +var util = __webpack_require__(113); +var Cache = __webpack_require__(683); +var define = __webpack_require__(648); +var debug = __webpack_require__(205)('snapdragon:parser'); +var Position = __webpack_require__(684); +var utils = __webpack_require__(662); /** * Create a new `Parser` with the given `input` and `options`. @@ -77405,7 +77421,7 @@ module.exports = Parser; /***/ }), -/* 684 */ +/* 683 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77512,13 +77528,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 685 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(650); +var define = __webpack_require__(648); /** * Store position for a node @@ -77533,14 +77549,14 @@ module.exports = function Position(start, parser) { /***/ }), -/* 686 */ +/* 685 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(687); -var assignSymbols = __webpack_require__(593); +var isExtendable = __webpack_require__(686); +var assignSymbols = __webpack_require__(589); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -77600,7 +77616,7 @@ function isEnum(obj, key) { /***/ }), -/* 687 */ +/* 686 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77613,7 +77629,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(592); +var isPlainObject = __webpack_require__(588); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -77621,14 +77637,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 688 */ +/* 687 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(689); -var extglob = __webpack_require__(704); +var nanomatch = __webpack_require__(688); +var extglob = __webpack_require__(702); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -77705,7 +77721,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 689 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77715,18 +77731,18 @@ function escapeExtglobs(compiler) { * Module dependencies */ -var util = __webpack_require__(115); -var toRegex = __webpack_require__(575); -var extend = __webpack_require__(690); +var util = __webpack_require__(113); +var toRegex = __webpack_require__(573); +var extend = __webpack_require__(689); /** * Local dependencies */ -var compilers = __webpack_require__(692); -var parsers = __webpack_require__(693); -var cache = __webpack_require__(696); -var utils = __webpack_require__(698); +var compilers = __webpack_require__(691); +var parsers = __webpack_require__(692); +var cache = __webpack_require__(695); +var utils = __webpack_require__(697); var MAX_LENGTH = 1024 * 64; /** @@ -78550,14 +78566,14 @@ module.exports = nanomatch; /***/ }), -/* 690 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(691); -var assignSymbols = __webpack_require__(593); +var isExtendable = __webpack_require__(690); +var assignSymbols = __webpack_require__(589); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -78617,7 +78633,7 @@ function isEnum(obj, key) { /***/ }), -/* 691 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78630,7 +78646,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(592); +var isPlainObject = __webpack_require__(588); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -78638,7 +78654,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 692 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78984,15 +79000,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 693 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(594); -var toRegex = __webpack_require__(575); -var isOdd = __webpack_require__(694); +var regexNot = __webpack_require__(590); +var toRegex = __webpack_require__(573); +var isOdd = __webpack_require__(693); /** * Characters to use in negation regex (we want to "not" match @@ -79378,7 +79394,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 694 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79391,7 +79407,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(695); +var isNumber = __webpack_require__(694); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -79405,7 +79421,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 695 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79433,14 +79449,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 696 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(697))(); +module.exports = new (__webpack_require__(696))(); /***/ }), -/* 697 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79453,7 +79469,7 @@ module.exports = new (__webpack_require__(697))(); -var MapCache = __webpack_require__(684); +var MapCache = __webpack_require__(683); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -79575,7 +79591,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 698 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79588,14 +79604,14 @@ var path = __webpack_require__(4); * Module dependencies */ -var isWindows = __webpack_require__(699)(); -var Snapdragon = __webpack_require__(620); -utils.define = __webpack_require__(700); -utils.diff = __webpack_require__(701); -utils.extend = __webpack_require__(690); -utils.pick = __webpack_require__(702); -utils.typeOf = __webpack_require__(703); -utils.unique = __webpack_require__(597); +var isWindows = __webpack_require__(698)(); +var Snapdragon = __webpack_require__(617); +utils.define = __webpack_require__(699); +utils.diff = __webpack_require__(700); +utils.extend = __webpack_require__(689); +utils.pick = __webpack_require__(701); +utils.typeOf = __webpack_require__(583); +utils.unique = __webpack_require__(593); /** * Returns true if the given value is effectively an empty string @@ -79961,7 +79977,7 @@ utils.unixify = function(options) { /***/ }), -/* 699 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -79989,7 +80005,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 700 */ +/* 699 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80002,8 +80018,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(583); -var isDescriptor = __webpack_require__(584); +var isobject = __webpack_require__(581); +var isDescriptor = __webpack_require__(582); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -80034,7 +80050,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 701 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80088,7 +80104,7 @@ function diffArray(one, two) { /***/ }), -/* 702 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80101,7 +80117,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(583); +var isObject = __webpack_require__(581); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -80130,142 +80146,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 703 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 704 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80275,18 +80156,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(634); -var unique = __webpack_require__(597); -var toRegex = __webpack_require__(575); +var extend = __webpack_require__(632); +var unique = __webpack_require__(593); +var toRegex = __webpack_require__(573); /** * Local dependencies */ -var compilers = __webpack_require__(705); -var parsers = __webpack_require__(711); -var Extglob = __webpack_require__(714); -var utils = __webpack_require__(713); +var compilers = __webpack_require__(703); +var parsers = __webpack_require__(709); +var Extglob = __webpack_require__(712); +var utils = __webpack_require__(711); var MAX_LENGTH = 1024 * 64; /** @@ -80603,13 +80484,13 @@ module.exports = extglob; /***/ }), -/* 705 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(706); +var brackets = __webpack_require__(704); /** * Extglob compilers @@ -80779,7 +80660,7 @@ module.exports = function(extglob) { /***/ }), -/* 706 */ +/* 704 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80789,17 +80670,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(707); -var parsers = __webpack_require__(709); +var compilers = __webpack_require__(705); +var parsers = __webpack_require__(707); /** * Module dependencies */ -var debug = __webpack_require__(207)('expand-brackets'); -var extend = __webpack_require__(634); -var Snapdragon = __webpack_require__(620); -var toRegex = __webpack_require__(575); +var debug = __webpack_require__(205)('expand-brackets'); +var extend = __webpack_require__(632); +var Snapdragon = __webpack_require__(617); +var toRegex = __webpack_require__(573); /** * Parses the given POSIX character class `pattern` and returns a @@ -80997,13 +80878,13 @@ module.exports = brackets; /***/ }), -/* 707 */ +/* 705 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(708); +var posix = __webpack_require__(706); module.exports = function(brackets) { brackets.compiler @@ -81091,7 +80972,7 @@ module.exports = function(brackets) { /***/ }), -/* 708 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81120,14 +81001,14 @@ module.exports = { /***/ }), -/* 709 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(710); -var define = __webpack_require__(650); +var utils = __webpack_require__(708); +var define = __webpack_require__(648); /** * Text regex @@ -81346,14 +81227,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 710 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(575); -var regexNot = __webpack_require__(594); +var toRegex = __webpack_require__(573); +var regexNot = __webpack_require__(590); var cached; /** @@ -81387,15 +81268,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 711 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(706); -var define = __webpack_require__(712); -var utils = __webpack_require__(713); +var brackets = __webpack_require__(704); +var define = __webpack_require__(710); +var utils = __webpack_require__(711); /** * Characters to use in text regex (we want to "not" match @@ -81550,7 +81431,7 @@ module.exports = parsers; /***/ }), -/* 712 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81563,7 +81444,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(584); +var isDescriptor = __webpack_require__(582); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -81588,14 +81469,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 713 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(594); -var Cache = __webpack_require__(697); +var regex = __webpack_require__(590); +var Cache = __webpack_require__(696); /** * Utils @@ -81664,7 +81545,7 @@ utils.createRegex = function(str) { /***/ }), -/* 714 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81674,16 +81555,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(620); -var define = __webpack_require__(712); -var extend = __webpack_require__(634); +var Snapdragon = __webpack_require__(617); +var define = __webpack_require__(710); +var extend = __webpack_require__(632); /** * Local dependencies */ -var compilers = __webpack_require__(705); -var parsers = __webpack_require__(711); +var compilers = __webpack_require__(703); +var parsers = __webpack_require__(709); /** * Customize Snapdragon parser and renderer @@ -81749,16 +81630,16 @@ module.exports = Extglob; /***/ }), -/* 715 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(704); -var nanomatch = __webpack_require__(689); -var regexNot = __webpack_require__(594); -var toRegex = __webpack_require__(575); +var extglob = __webpack_require__(702); +var nanomatch = __webpack_require__(688); +var regexNot = __webpack_require__(590); +var toRegex = __webpack_require__(573); var not; /** @@ -81839,14 +81720,14 @@ function textRegex(pattern) { /***/ }), -/* 716 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(697))(); +module.exports = new (__webpack_require__(696))(); /***/ }), -/* 717 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81859,13 +81740,13 @@ var path = __webpack_require__(4); * Module dependencies */ -var Snapdragon = __webpack_require__(620); -utils.define = __webpack_require__(718); -utils.diff = __webpack_require__(701); -utils.extend = __webpack_require__(686); -utils.pick = __webpack_require__(702); -utils.typeOf = __webpack_require__(719); -utils.unique = __webpack_require__(597); +var Snapdragon = __webpack_require__(617); +utils.define = __webpack_require__(716); +utils.diff = __webpack_require__(700); +utils.extend = __webpack_require__(685); +utils.pick = __webpack_require__(701); +utils.typeOf = __webpack_require__(583); +utils.unique = __webpack_require__(593); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -82162,7 +82043,7 @@ utils.unixify = function(options) { /***/ }), -/* 718 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82175,8 +82056,8 @@ utils.unixify = function(options) { -var isobject = __webpack_require__(583); -var isDescriptor = __webpack_require__(584); +var isobject = __webpack_require__(581); +var isDescriptor = __webpack_require__(582); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -82207,142 +82088,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 719 */ -/***/ (function(module, exports) { - -var toString = Object.prototype.toString; - -module.exports = function kindOf(val) { - if (val === void 0) return 'undefined'; - if (val === null) return 'null'; - - var type = typeof val; - if (type === 'boolean') return 'boolean'; - if (type === 'string') return 'string'; - if (type === 'number') return 'number'; - if (type === 'symbol') return 'symbol'; - if (type === 'function') { - return isGeneratorFn(val) ? 'generatorfunction' : 'function'; - } - - if (isArray(val)) return 'array'; - if (isBuffer(val)) return 'buffer'; - if (isArguments(val)) return 'arguments'; - if (isDate(val)) return 'date'; - if (isError(val)) return 'error'; - if (isRegexp(val)) return 'regexp'; - - switch (ctorName(val)) { - case 'Symbol': return 'symbol'; - case 'Promise': return 'promise'; - - // Set, Map, WeakSet, WeakMap - case 'WeakMap': return 'weakmap'; - case 'WeakSet': return 'weakset'; - case 'Map': return 'map'; - case 'Set': return 'set'; - - // 8-bit typed arrays - case 'Int8Array': return 'int8array'; - case 'Uint8Array': return 'uint8array'; - case 'Uint8ClampedArray': return 'uint8clampedarray'; - - // 16-bit typed arrays - case 'Int16Array': return 'int16array'; - case 'Uint16Array': return 'uint16array'; - - // 32-bit typed arrays - case 'Int32Array': return 'int32array'; - case 'Uint32Array': return 'uint32array'; - case 'Float32Array': return 'float32array'; - case 'Float64Array': return 'float64array'; - } - - if (isGeneratorObj(val)) { - return 'generator'; - } - - // Non-plain objects - type = toString.call(val); - switch (type) { - case '[object Object]': return 'object'; - // iterators - case '[object Map Iterator]': return 'mapiterator'; - case '[object Set Iterator]': return 'setiterator'; - case '[object String Iterator]': return 'stringiterator'; - case '[object Array Iterator]': return 'arrayiterator'; - } - - // other - return type.slice(8, -1).toLowerCase().replace(/\s/g, ''); -}; - -function ctorName(val) { - return typeof val.constructor === 'function' ? val.constructor.name : null; -} - -function isArray(val) { - if (Array.isArray) return Array.isArray(val); - return val instanceof Array; -} - -function isError(val) { - return val instanceof Error || (typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number'); -} - -function isDate(val) { - if (val instanceof Date) return true; - return typeof val.toDateString === 'function' - && typeof val.getDate === 'function' - && typeof val.setDate === 'function'; -} - -function isRegexp(val) { - if (val instanceof RegExp) return true; - return typeof val.flags === 'string' - && typeof val.ignoreCase === 'boolean' - && typeof val.multiline === 'boolean' - && typeof val.global === 'boolean'; -} - -function isGeneratorFn(name, val) { - return ctorName(name) === 'GeneratorFunction'; -} - -function isGeneratorObj(val) { - return typeof val.throw === 'function' - && typeof val.return === 'function' - && typeof val.next === 'function'; -} - -function isArguments(val) { - try { - if (typeof val.length === 'number' && typeof val.callee === 'function') { - return true; - } - } catch (err) { - if (err.message.indexOf('callee') !== -1) { - return true; - } - } - return false; -} - -/** - * If you need to support Safari 5-7 (8-10 yr-old browser), - * take a look at https://github.com/feross/is-buffer - */ - -function isBuffer(val) { - if (val.constructor && typeof val.constructor.isBuffer === 'function') { - return val.constructor.isBuffer(val); - } - return false; -} - - -/***/ }), -/* 720 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82361,9 +82107,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(721); -var reader_1 = __webpack_require__(734); -var fs_stream_1 = __webpack_require__(738); +var readdir = __webpack_require__(718); +var reader_1 = __webpack_require__(731); +var fs_stream_1 = __webpack_require__(735); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -82424,15 +82170,15 @@ exports.default = ReaderAsync; /***/ }), -/* 721 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(722); -const readdirAsync = __webpack_require__(730); -const readdirStream = __webpack_require__(733); +const readdirSync = __webpack_require__(719); +const readdirAsync = __webpack_require__(727); +const readdirStream = __webpack_require__(730); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -82516,7 +82262,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 722 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82524,11 +82270,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(723); +const DirectoryReader = __webpack_require__(720); let syncFacade = { - fs: __webpack_require__(728), - forEach: __webpack_require__(729), + fs: __webpack_require__(725), + forEach: __webpack_require__(726), sync: true }; @@ -82557,18 +82303,18 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 723 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const Readable = __webpack_require__(175).Readable; -const EventEmitter = __webpack_require__(166).EventEmitter; +const Readable = __webpack_require__(173).Readable; +const EventEmitter = __webpack_require__(164).EventEmitter; const path = __webpack_require__(4); -const normalizeOptions = __webpack_require__(724); -const stat = __webpack_require__(726); -const call = __webpack_require__(727); +const normalizeOptions = __webpack_require__(721); +const stat = __webpack_require__(723); +const call = __webpack_require__(724); /** * Asynchronously reads the contents of a directory and streams the results @@ -82944,14 +82690,14 @@ module.exports = DirectoryReader; /***/ }), -/* 724 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const globToRegExp = __webpack_require__(725); +const globToRegExp = __webpack_require__(722); module.exports = normalizeOptions; @@ -83128,7 +82874,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 725 */ +/* 722 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -83265,13 +83011,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 726 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(727); +const call = __webpack_require__(724); module.exports = stat; @@ -83346,7 +83092,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 727 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83407,14 +83153,14 @@ function callOnce (fn) { /***/ }), -/* 728 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); -const call = __webpack_require__(727); +const fs = __webpack_require__(132); +const call = __webpack_require__(724); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -83478,7 +83224,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 729 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83507,7 +83253,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 730 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83515,12 +83261,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(731); -const DirectoryReader = __webpack_require__(723); +const maybe = __webpack_require__(728); +const DirectoryReader = __webpack_require__(720); let asyncFacade = { - fs: __webpack_require__(134), - forEach: __webpack_require__(732), + fs: __webpack_require__(132), + forEach: __webpack_require__(729), async: true }; @@ -83562,7 +83308,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 731 */ +/* 728 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83589,7 +83335,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 732 */ +/* 729 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83625,7 +83371,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 733 */ +/* 730 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83633,11 +83379,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(723); +const DirectoryReader = __webpack_require__(720); let streamFacade = { - fs: __webpack_require__(134), - forEach: __webpack_require__(732), + fs: __webpack_require__(132), + forEach: __webpack_require__(729), async: true }; @@ -83657,16 +83403,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 734 */ +/* 731 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var deep_1 = __webpack_require__(735); -var entry_1 = __webpack_require__(737); -var pathUtil = __webpack_require__(736); +var deep_1 = __webpack_require__(732); +var entry_1 = __webpack_require__(734); +var pathUtil = __webpack_require__(733); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -83732,14 +83478,14 @@ exports.default = Reader; /***/ }), -/* 735 */ +/* 732 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(736); -var patternUtils = __webpack_require__(569); +var pathUtils = __webpack_require__(733); +var patternUtils = __webpack_require__(567); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -83822,7 +83568,7 @@ exports.default = DeepFilter; /***/ }), -/* 736 */ +/* 733 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83853,14 +83599,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 737 */ +/* 734 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(736); -var patternUtils = __webpack_require__(569); +var pathUtils = __webpack_require__(733); +var patternUtils = __webpack_require__(567); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -83945,7 +83691,7 @@ exports.default = EntryFilter; /***/ }), -/* 738 */ +/* 735 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83964,9 +83710,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var stream = __webpack_require__(175); -var fsStat = __webpack_require__(739); -var fs_1 = __webpack_require__(743); +var stream = __webpack_require__(173); +var fsStat = __webpack_require__(736); +var fs_1 = __webpack_require__(740); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -84016,14 +83762,14 @@ exports.default = FileSystemStream; /***/ }), -/* 739 */ +/* 736 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(740); -const statProvider = __webpack_require__(742); +const optionsManager = __webpack_require__(737); +const statProvider = __webpack_require__(739); /** * Asynchronous API. */ @@ -84054,13 +83800,13 @@ exports.statSync = statSync; /***/ }), -/* 740 */ +/* 737 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(741); +const fsAdapter = __webpack_require__(738); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -84073,13 +83819,13 @@ exports.prepare = prepare; /***/ }), -/* 741 */ +/* 738 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(134); +const fs = __webpack_require__(132); exports.FILE_SYSTEM_ADAPTER = { lstat: fs.lstat, stat: fs.stat, @@ -84096,7 +83842,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 742 */ +/* 739 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84148,7 +83894,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 743 */ +/* 740 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84179,7 +83925,7 @@ exports.default = FileSystem; /***/ }), -/* 744 */ +/* 741 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84198,10 +83944,10 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var stream = __webpack_require__(175); -var readdir = __webpack_require__(721); -var reader_1 = __webpack_require__(734); -var fs_stream_1 = __webpack_require__(738); +var stream = __webpack_require__(173); +var readdir = __webpack_require__(718); +var reader_1 = __webpack_require__(731); +var fs_stream_1 = __webpack_require__(735); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -84269,7 +84015,7 @@ exports.default = ReaderStream; /***/ }), -/* 745 */ +/* 742 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84288,9 +84034,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(721); -var reader_1 = __webpack_require__(734); -var fs_sync_1 = __webpack_require__(746); +var readdir = __webpack_require__(718); +var reader_1 = __webpack_require__(731); +var fs_sync_1 = __webpack_require__(743); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -84350,7 +84096,7 @@ exports.default = ReaderSync; /***/ }), -/* 746 */ +/* 743 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84369,8 +84115,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(739); -var fs_1 = __webpack_require__(743); +var fsStat = __webpack_require__(736); +var fs_1 = __webpack_require__(740); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -84416,7 +84162,7 @@ exports.default = FileSystemSync; /***/ }), -/* 747 */ +/* 744 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84432,13 +84178,13 @@ exports.flatten = flatten; /***/ }), -/* 748 */ +/* 745 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(245); +var merge2 = __webpack_require__(243); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -84453,13 +84199,13 @@ exports.merge = merge; /***/ }), -/* 749 */ +/* 746 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const pathType = __webpack_require__(750); +const pathType = __webpack_require__(747); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -84525,13 +84271,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 750 */ +/* 747 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); -const pify = __webpack_require__(751); +const fs = __webpack_require__(132); +const pify = __webpack_require__(748); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -84574,7 +84320,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 751 */ +/* 748 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84665,17 +84411,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 752 */ +/* 749 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); +const fs = __webpack_require__(132); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(565); -const gitIgnore = __webpack_require__(753); -const pify = __webpack_require__(754); -const slash = __webpack_require__(755); +const fastGlob = __webpack_require__(563); +const gitIgnore = __webpack_require__(750); +const pify = __webpack_require__(751); +const slash = __webpack_require__(752); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -84773,7 +84519,7 @@ module.exports.sync = options => { /***/ }), -/* 753 */ +/* 750 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -85242,7 +84988,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 754 */ +/* 751 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85317,7 +85063,7 @@ module.exports = (input, options) => { /***/ }), -/* 755 */ +/* 752 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85335,7 +85081,7 @@ module.exports = input => { /***/ }), -/* 756 */ +/* 753 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85348,7 +85094,7 @@ module.exports = input => { -var isGlob = __webpack_require__(757); +var isGlob = __webpack_require__(754); module.exports = function hasGlob(val) { if (val == null) return false; @@ -85368,7 +85114,7 @@ module.exports = function hasGlob(val) { /***/ }), -/* 757 */ +/* 754 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -85378,7 +85124,7 @@ module.exports = function hasGlob(val) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(269); +var isExtglob = __webpack_require__(267); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -85399,17 +85145,17 @@ module.exports = function isGlob(str) { /***/ }), -/* 758 */ +/* 755 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const {constants: fsConstants} = __webpack_require__(134); -const pEvent = __webpack_require__(759); -const CpFileError = __webpack_require__(762); -const fs = __webpack_require__(764); -const ProgressEmitter = __webpack_require__(767); +const {constants: fsConstants} = __webpack_require__(132); +const pEvent = __webpack_require__(756); +const CpFileError = __webpack_require__(759); +const fs = __webpack_require__(761); +const ProgressEmitter = __webpack_require__(764); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -85523,12 +85269,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 759 */ +/* 756 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(760); +const pTimeout = __webpack_require__(757); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -85819,12 +85565,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 760 */ +/* 757 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(761); +const pFinally = __webpack_require__(758); class TimeoutError extends Error { constructor(message) { @@ -85870,7 +85616,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 761 */ +/* 758 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85892,12 +85638,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 762 */ +/* 759 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(763); +const NestedError = __webpack_require__(760); class CpFileError extends NestedError { constructor(message, nested) { @@ -85911,10 +85657,10 @@ module.exports = CpFileError; /***/ }), -/* 763 */ +/* 760 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(115).inherits; +var inherits = __webpack_require__(113).inherits; var NestedError = function (message, nested) { this.nested = nested; @@ -85967,16 +85713,16 @@ module.exports = NestedError; /***/ }), -/* 764 */ +/* 761 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {promisify} = __webpack_require__(115); -const fs = __webpack_require__(235); -const makeDir = __webpack_require__(765); -const pEvent = __webpack_require__(759); -const CpFileError = __webpack_require__(762); +const {promisify} = __webpack_require__(113); +const fs = __webpack_require__(233); +const makeDir = __webpack_require__(762); +const pEvent = __webpack_require__(756); +const CpFileError = __webpack_require__(759); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -86073,15 +85819,15 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 765 */ +/* 762 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); +const fs = __webpack_require__(132); const path = __webpack_require__(4); -const {promisify} = __webpack_require__(115); -const semver = __webpack_require__(766); +const {promisify} = __webpack_require__(113); +const semver = __webpack_require__(763); const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0'); @@ -86236,7 +85982,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 766 */ +/* 763 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -87838,12 +87584,12 @@ function coerce (version, options) { /***/ }), -/* 767 */ +/* 764 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const EventEmitter = __webpack_require__(166); +const EventEmitter = __webpack_require__(164); const written = new WeakMap(); @@ -87879,7 +87625,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 768 */ +/* 765 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87925,12 +87671,12 @@ exports.default = module.exports; /***/ }), -/* 769 */ +/* 766 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(770); +const pMap = __webpack_require__(767); const pFilter = async (iterable, filterer, options) => { const values = await pMap( @@ -87947,7 +87693,7 @@ module.exports.default = pFilter; /***/ }), -/* 770 */ +/* 767 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88026,12 +87772,12 @@ module.exports.default = pMap; /***/ }), -/* 771 */ +/* 768 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(763); +const NestedError = __webpack_require__(760); class CpyError extends NestedError { constructor(message, nested) { @@ -88045,18 +87791,18 @@ module.exports = CpyError; /***/ }), -/* 772 */ +/* 769 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fs = __webpack_require__(134); -const arrayUnion = __webpack_require__(244); -const merge2 = __webpack_require__(245); -const fastGlob = __webpack_require__(773); -const dirGlob = __webpack_require__(328); -const gitignore = __webpack_require__(798); -const {FilterStream, UniqueStream} = __webpack_require__(799); +const fs = __webpack_require__(132); +const arrayUnion = __webpack_require__(242); +const merge2 = __webpack_require__(243); +const fastGlob = __webpack_require__(770); +const dirGlob = __webpack_require__(326); +const gitignore = __webpack_require__(795); +const {FilterStream, UniqueStream} = __webpack_require__(796); const DEFAULT_FILTER = () => false; @@ -88233,17 +87979,17 @@ module.exports.gitignore = gitignore; /***/ }), -/* 773 */ +/* 770 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const taskManager = __webpack_require__(774); -const async_1 = __webpack_require__(784); -const stream_1 = __webpack_require__(794); -const sync_1 = __webpack_require__(795); -const settings_1 = __webpack_require__(797); -const utils = __webpack_require__(775); +const taskManager = __webpack_require__(771); +const async_1 = __webpack_require__(781); +const stream_1 = __webpack_require__(791); +const sync_1 = __webpack_require__(792); +const settings_1 = __webpack_require__(794); +const utils = __webpack_require__(772); async function FastGlob(source, options) { assertPatternsInput(source); const works = getWorks(source, async_1.default, options); @@ -88307,14 +88053,14 @@ module.exports = FastGlob; /***/ }), -/* 774 */ +/* 771 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertPatternGroupToTask = exports.convertPatternGroupsToTasks = exports.groupPatternsByBaseDirectory = exports.getNegativePatternsAsPositive = exports.getPositivePatterns = exports.convertPatternsToTasks = exports.generate = void 0; -const utils = __webpack_require__(775); +const utils = __webpack_require__(772); function generate(patterns, settings) { const positivePatterns = getPositivePatterns(patterns); const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); @@ -88379,31 +88125,31 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 775 */ +/* 772 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.string = exports.stream = exports.pattern = exports.path = exports.fs = exports.errno = exports.array = void 0; -const array = __webpack_require__(776); +const array = __webpack_require__(773); exports.array = array; -const errno = __webpack_require__(777); +const errno = __webpack_require__(774); exports.errno = errno; -const fs = __webpack_require__(778); +const fs = __webpack_require__(775); exports.fs = fs; -const path = __webpack_require__(779); +const path = __webpack_require__(776); exports.path = path; -const pattern = __webpack_require__(780); +const pattern = __webpack_require__(777); exports.pattern = pattern; -const stream = __webpack_require__(782); +const stream = __webpack_require__(779); exports.stream = stream; -const string = __webpack_require__(783); +const string = __webpack_require__(780); exports.string = string; /***/ }), -/* 776 */ +/* 773 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88432,7 +88178,7 @@ exports.splitWhen = splitWhen; /***/ }), -/* 777 */ +/* 774 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88446,7 +88192,7 @@ exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 778 */ +/* 775 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88472,7 +88218,7 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 779 */ +/* 776 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88512,7 +88258,7 @@ exports.removeLeadingDotSegment = removeLeadingDotSegment; /***/ }), -/* 780 */ +/* 777 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88520,9 +88266,9 @@ exports.removeLeadingDotSegment = removeLeadingDotSegment; Object.defineProperty(exports, "__esModule", { value: true }); exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = void 0; const path = __webpack_require__(4); -const globParent = __webpack_require__(267); -const micromatch = __webpack_require__(781); -const picomatch = __webpack_require__(281); +const globParent = __webpack_require__(265); +const micromatch = __webpack_require__(778); +const picomatch = __webpack_require__(279); const GLOBSTAR = '**'; const ESCAPE_SYMBOL = '\\'; const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/; @@ -88651,16 +88397,16 @@ exports.matchAny = matchAny; /***/ }), -/* 781 */ +/* 778 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const util = __webpack_require__(115); -const braces = __webpack_require__(271); -const picomatch = __webpack_require__(281); -const utils = __webpack_require__(284); +const util = __webpack_require__(113); +const braces = __webpack_require__(269); +const picomatch = __webpack_require__(279); +const utils = __webpack_require__(282); const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); /** @@ -89125,14 +88871,14 @@ module.exports = micromatch; /***/ }), -/* 782 */ +/* 779 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.merge = void 0; -const merge2 = __webpack_require__(245); +const merge2 = __webpack_require__(243); function merge(streams) { const mergedStream = merge2(streams); streams.forEach((stream) => { @@ -89149,7 +88895,7 @@ function propagateCloseEventToSources(streams) { /***/ }), -/* 783 */ +/* 780 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89167,14 +88913,14 @@ exports.isEmpty = isEmpty; /***/ }), -/* 784 */ +/* 781 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(785); -const provider_1 = __webpack_require__(787); +const stream_1 = __webpack_require__(782); +const provider_1 = __webpack_require__(784); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -89202,16 +88948,16 @@ exports.default = ProviderAsync; /***/ }), -/* 785 */ +/* 782 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(175); -const fsStat = __webpack_require__(291); -const fsWalk = __webpack_require__(296); -const reader_1 = __webpack_require__(786); +const stream_1 = __webpack_require__(173); +const fsStat = __webpack_require__(289); +const fsWalk = __webpack_require__(294); +const reader_1 = __webpack_require__(783); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -89264,15 +89010,15 @@ exports.default = ReaderStream; /***/ }), -/* 786 */ +/* 783 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); -const fsStat = __webpack_require__(291); -const utils = __webpack_require__(775); +const fsStat = __webpack_require__(289); +const utils = __webpack_require__(772); class Reader { constructor(_settings) { this._settings = _settings; @@ -89304,17 +89050,17 @@ exports.default = Reader; /***/ }), -/* 787 */ +/* 784 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); -const deep_1 = __webpack_require__(788); -const entry_1 = __webpack_require__(791); -const error_1 = __webpack_require__(792); -const entry_2 = __webpack_require__(793); +const deep_1 = __webpack_require__(785); +const entry_1 = __webpack_require__(788); +const error_1 = __webpack_require__(789); +const entry_2 = __webpack_require__(790); class Provider { constructor(_settings) { this._settings = _settings; @@ -89359,14 +89105,14 @@ exports.default = Provider; /***/ }), -/* 788 */ +/* 785 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(775); -const partial_1 = __webpack_require__(789); +const utils = __webpack_require__(772); +const partial_1 = __webpack_require__(786); class DeepFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -89428,13 +89174,13 @@ exports.default = DeepFilter; /***/ }), -/* 789 */ +/* 786 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const matcher_1 = __webpack_require__(790); +const matcher_1 = __webpack_require__(787); class PartialMatcher extends matcher_1.default { match(filepath) { const parts = filepath.split('/'); @@ -89473,13 +89219,13 @@ exports.default = PartialMatcher; /***/ }), -/* 790 */ +/* 787 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(775); +const utils = __webpack_require__(772); class Matcher { constructor(_patterns, _settings, _micromatchOptions) { this._patterns = _patterns; @@ -89530,13 +89276,13 @@ exports.default = Matcher; /***/ }), -/* 791 */ +/* 788 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(775); +const utils = __webpack_require__(772); class EntryFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -89593,13 +89339,13 @@ exports.default = EntryFilter; /***/ }), -/* 792 */ +/* 789 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(775); +const utils = __webpack_require__(772); class ErrorFilter { constructor(_settings) { this._settings = _settings; @@ -89615,13 +89361,13 @@ exports.default = ErrorFilter; /***/ }), -/* 793 */ +/* 790 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(775); +const utils = __webpack_require__(772); class EntryTransformer { constructor(_settings) { this._settings = _settings; @@ -89648,15 +89394,15 @@ exports.default = EntryTransformer; /***/ }), -/* 794 */ +/* 791 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(175); -const stream_2 = __webpack_require__(785); -const provider_1 = __webpack_require__(787); +const stream_1 = __webpack_require__(173); +const stream_2 = __webpack_require__(782); +const provider_1 = __webpack_require__(784); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -89686,14 +89432,14 @@ exports.default = ProviderStream; /***/ }), -/* 795 */ +/* 792 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(796); -const provider_1 = __webpack_require__(787); +const sync_1 = __webpack_require__(793); +const provider_1 = __webpack_require__(784); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -89716,15 +89462,15 @@ exports.default = ProviderSync; /***/ }), -/* 796 */ +/* 793 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(291); -const fsWalk = __webpack_require__(296); -const reader_1 = __webpack_require__(786); +const fsStat = __webpack_require__(289); +const fsWalk = __webpack_require__(294); +const reader_1 = __webpack_require__(783); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -89766,15 +89512,15 @@ exports.default = ReaderSync; /***/ }), -/* 797 */ +/* 794 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DEFAULT_FILE_SYSTEM_ADAPTER = void 0; -const fs = __webpack_require__(134); -const os = __webpack_require__(124); +const fs = __webpack_require__(132); +const os = __webpack_require__(122); /** * The `os.cpus` method can return zero. We expect the number of cores to be greater than zero. * https://github.com/nodejs/node/blob/7faeddf23a98c53896f8b574a6e66589e8fb1eb8/lib/os.js#L106-L107 @@ -89830,17 +89576,17 @@ exports.default = Settings; /***/ }), -/* 798 */ +/* 795 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {promisify} = __webpack_require__(115); -const fs = __webpack_require__(134); +const {promisify} = __webpack_require__(113); +const fs = __webpack_require__(132); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(773); -const gitIgnore = __webpack_require__(331); -const slash = __webpack_require__(332); +const fastGlob = __webpack_require__(770); +const gitIgnore = __webpack_require__(329); +const slash = __webpack_require__(330); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -89957,12 +89703,12 @@ module.exports.sync = options => { /***/ }), -/* 799 */ +/* 796 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {Transform} = __webpack_require__(175); +const {Transform} = __webpack_require__(173); class ObjectTransform extends Transform { constructor() { @@ -90010,7 +89756,7 @@ module.exports = { /***/ }), -/* 800 */ +/* 797 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -90018,17 +89764,17 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return buildNonBazelProductionProjects; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProductionProjects", function() { return getProductionProjects; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProject", function() { return buildProject; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(558); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(556); /* 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__(242); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); /* 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__(4); /* 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__(555); -/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(233); -/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(222); -/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(345); -/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(342); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(553); +/* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(231); +/* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(220); +/* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(343); +/* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(340); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License diff --git a/packages/kbn-ui-shared-deps-npm/BUILD.bazel b/packages/kbn-ui-shared-deps-npm/BUILD.bazel index c1340926c3f67..ae3a6f05d456b 100644 --- a/packages/kbn-ui-shared-deps-npm/BUILD.bazel +++ b/packages/kbn-ui-shared-deps-npm/BUILD.bazel @@ -31,6 +31,7 @@ NPM_MODULE_EXTRA_FILES = [ RUNTIME_DEPS = [ "//packages/elastic-datemath", "//packages/kbn-utils", + "@npm//@babel/runtime", "@npm//@elastic/charts", "@npm//@elastic/eui", "@npm//@elastic/numeral", @@ -45,15 +46,15 @@ RUNTIME_DEPS = [ "@npm//jquery", "@npm//loader-utils", "@npm//mini-css-extract-plugin", - "@npm//moment", "@npm//moment-timezone", + "@npm//moment", "@npm//raw-loader", - "@npm//react", "@npm//react-dom", "@npm//react-intl", "@npm//react-is", - "@npm//react-router", "@npm//react-router-dom", + "@npm//react-router", + "@npm//react", "@npm//regenerator-runtime", "@npm//resize-observer-polyfill", "@npm//rison-node", @@ -62,7 +63,7 @@ RUNTIME_DEPS = [ "@npm//symbol-observable", "@npm//url-loader", "@npm//val-loader", - "@npm//whatwg-fetch" + "@npm//whatwg-fetch", ] WEBPACK_DEPS = [ diff --git a/src/dev/i18n/extractors/__snapshots__/html.test.js.snap b/src/dev/i18n/extractors/__snapshots__/html.test.js.snap index 60749c1e1eebc..f911674400d45 100644 --- a/src/dev/i18n/extractors/__snapshots__/html.test.js.snap +++ b/src/dev/i18n/extractors/__snapshots__/html.test.js.snap @@ -62,7 +62,7 @@ exports[`dev/i18n/extractors/html throws on i18n filter usage in complex angular Array [ Array [ [Error: Couldn't parse angular i18n expression: -Missing semicolon (1:5): +Missing semicolon. (1:5): mode as ('metricVis.colorModes.' + mode], ], ] diff --git a/yarn.lock b/yarn.lock index 4eceb4a18162e..c7435bb22ca27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,21 +2,20 @@ # yarn lockfile v1 -"@babel/cli@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.10.tgz#67a1015b1cd505bde1696196febf910c4c339a48" - integrity sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ== +"@babel/cli@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.15.7.tgz#62658abedb786d09c1f70229224b11a65440d7a1" + integrity sha512-YW5wOprO2LzMjoWZ5ZG6jfbY9JnkDxuHDwvnrThnuYtByorova/I0HNXJedrUfwuXFQfYOjcqDA4PU3qlZGZjg== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" fs-readdir-recursive "^1.1.0" glob "^7.0.0" - lodash "^4.17.19" make-dir "^2.1.0" slash "^2.0.0" source-map "^0.5.0" optionalDependencies: - "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents" + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" "@babel/code-frame@7.10.4": @@ -33,11 +32,23 @@ dependencies: "@babel/highlight" "^7.12.13" +"@babel/code-frame@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" + integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== + dependencies: + "@babel/highlight" "^7.14.5" + "@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" + integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== + "@babel/core@7.12.9": version "7.12.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" @@ -80,7 +91,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.12.1", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.7.5": +"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.12.1", "@babel/core@^7.12.3", "@babel/core@^7.7.5": version "7.12.10" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== @@ -101,7 +112,28 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.12.1", "@babel/generator@^7.12.10", "@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.13.0", "@babel/generator@^7.4.4": +"@babel/core@^7.15.5": + version "7.15.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.5.tgz#f8ed9ace730722544609f90c9bb49162dc3bf5b9" + integrity sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.4" + "@babel/helper-compilation-targets" "^7.15.4" + "@babel/helper-module-transforms" "^7.15.4" + "@babel/helpers" "^7.15.4" + "@babel/parser" "^7.15.5" + "@babel/template" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.4" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/generator@^7.12.1", "@babel/generator@^7.12.10", "@babel/generator@^7.12.5", "@babel/generator@^7.13.0", "@babel/generator@^7.4.4": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.5.tgz#848d7b9f031caca9d0cd0af01b063f226f52d785" integrity sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA== @@ -110,6 +142,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.4.tgz#85acb159a267ca6324f9793986991ee2022a05b0" + integrity sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw== + dependencies: + "@babel/types" "^7.15.4" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.10": version "7.12.10" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" @@ -117,6 +158,13 @@ dependencies: "@babel/types" "^7.12.10" +"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz#3d0e43b00c5e49fdb6c57e421601a7a658d5f835" + integrity sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" @@ -125,6 +173,14 @@ "@babel/helper-explode-assignable-expression" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz#21ad815f609b84ee0e3058676c33cf6d1670525f" + integrity sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/helper-compilation-targets@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" @@ -135,6 +191,16 @@ browserslist "^4.14.5" semver "^5.5.0" +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" + integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== + dependencies: + "@babel/compat-data" "^7.15.0" + "@babel/helper-validator-option" "^7.14.5" + browserslist "^4.16.6" + semver "^6.3.0" + "@babel/helper-create-class-features-plugin@^7.12.1", "@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.3.0": version "7.13.8" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.8.tgz#0367bd0a7505156ce018ca464f7ac91ba58c1a04" @@ -146,6 +212,18 @@ "@babel/helper-replace-supers" "^7.13.0" "@babel/helper-split-export-declaration" "^7.12.13" +"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz#7f977c17bd12a5fba363cb19bea090394bf37d2e" + integrity sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.15.4" + "@babel/helper-function-name" "^7.15.4" + "@babel/helper-member-expression-to-functions" "^7.15.4" + "@babel/helper-optimise-call-expression" "^7.15.4" + "@babel/helper-replace-supers" "^7.15.4" + "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-create-regexp-features-plugin@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz#18b1302d4677f9dc4740fe8c9ed96680e29d37e8" @@ -155,6 +233,14 @@ "@babel/helper-regex" "^7.10.4" regexpu-core "^4.7.1" +"@babel/helper-create-regexp-features-plugin@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz#c7d5ac5e9cf621c26057722fb7a8a4c5889358c4" + integrity sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.14.5" + regexpu-core "^4.7.1" + "@babel/helper-define-map@^7.10.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" @@ -164,6 +250,20 @@ "@babel/types" "^7.10.5" lodash "^4.17.19" +"@babel/helper-define-polyfill-provider@^0.2.2": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" + integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + "@babel/helper-explode-assignable-expression@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" @@ -172,6 +272,13 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-explode-assignable-expression@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz#f9aec9d219f271eaf92b9f561598ca6b2682600c" + integrity sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" @@ -181,6 +288,15 @@ "@babel/template" "^7.12.13" "@babel/types" "^7.12.13" +"@babel/helper-function-name@^7.14.5", "@babel/helper-function-name@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" + integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== + dependencies: + "@babel/helper-get-function-arity" "^7.15.4" + "@babel/template" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/helper-get-function-arity@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" @@ -188,6 +304,13 @@ dependencies: "@babel/types" "^7.12.13" +"@babel/helper-get-function-arity@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" + integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-hoist-variables@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" @@ -195,6 +318,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-hoist-variables@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" + integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-member-expression-to-functions@^7.13.0": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091" @@ -202,6 +332,13 @@ dependencies: "@babel/types" "^7.13.0" +"@babel/helper-member-expression-to-functions@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef" + integrity sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5", "@babel/helper-module-imports@^7.7.0": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" @@ -209,6 +346,13 @@ dependencies: "@babel/types" "^7.13.12" +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" + integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-module-transforms@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" @@ -224,6 +368,20 @@ "@babel/types" "^7.12.1" lodash "^4.17.19" +"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.4": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz#7da80c8cbc1f02655d83f8b79d25866afe50d226" + integrity sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw== + dependencies: + "@babel/helper-module-imports" "^7.15.4" + "@babel/helper-replace-supers" "^7.15.4" + "@babel/helper-simple-access" "^7.15.4" + "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-validator-identifier" "^7.15.7" + "@babel/template" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.6" + "@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" @@ -231,6 +389,13 @@ dependencies: "@babel/types" "^7.12.13" +"@babel/helper-optimise-call-expression@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171" + integrity sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-plugin-utils@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" @@ -241,6 +406,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== +"@babel/helper-plugin-utils@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" + integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== + "@babel/helper-regex@^7.10.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" @@ -257,6 +427,15 @@ "@babel/helper-wrap-function" "^7.10.4" "@babel/types" "^7.12.1" +"@babel/helper-remap-async-to-generator@^7.14.5", "@babel/helper-remap-async-to-generator@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz#2637c0731e4c90fbf58ac58b50b2b5a192fc970f" + integrity sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.15.4" + "@babel/helper-wrap-function" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/helper-replace-supers@^7.12.1", "@babel/helper-replace-supers@^7.13.0": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz#6034b7b51943094cb41627848cb219cb02be1d24" @@ -267,6 +446,16 @@ "@babel/traverse" "^7.13.0" "@babel/types" "^7.13.0" +"@babel/helper-replace-supers@^7.14.5", "@babel/helper-replace-supers@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a" + integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.15.4" + "@babel/helper-optimise-call-expression" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/helper-simple-access@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" @@ -274,6 +463,13 @@ dependencies: "@babel/types" "^7.12.1" +"@babel/helper-simple-access@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b" + integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-skip-transparent-expression-wrappers@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" @@ -281,6 +477,13 @@ dependencies: "@babel/types" "^7.12.1" +"@babel/helper-skip-transparent-expression-wrappers@^7.14.5", "@babel/helper-skip-transparent-expression-wrappers@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz#707dbdba1f4ad0fa34f9114fc8197aec7d5da2eb" + integrity sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" @@ -288,16 +491,33 @@ dependencies: "@babel/types" "^7.12.13" +"@babel/helper-split-export-declaration@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257" + integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw== + dependencies: + "@babel/types" "^7.15.4" + "@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== +"@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== + "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== +"@babel/helper-validator-option@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" + integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -308,6 +528,16 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-wrap-function@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz#6f754b2446cfaf3d612523e6ab8d79c27c3a3de7" + integrity sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw== + dependencies: + "@babel/helper-function-name" "^7.15.4" + "@babel/template" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/helpers@^7.12.5", "@babel/helpers@^7.4.4": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" @@ -317,6 +547,15 @@ "@babel/traverse" "^7.12.5" "@babel/types" "^7.12.5" +"@babel/helpers@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43" + integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ== + dependencies: + "@babel/template" "^7.15.4" + "@babel/traverse" "^7.15.4" + "@babel/types" "^7.15.4" + "@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": version "7.13.8" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.8.tgz#10b2dac78526424dfc1f47650d0e415dfd9dc481" @@ -326,11 +565,34 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.13", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7", "@babel/parser@^7.13.0", "@babel/parser@^7.4.5", "@babel/parser@^7.7.0": +"@babel/highlight@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" + integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== + dependencies: + "@babel/helper-validator-identifier" "^7.14.5" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.13", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7", "@babel/parser@^7.13.0", "@babel/parser@^7.4.5", "@babel/parser@^7.7.0": version "7.13.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.9.tgz#ca34cb95e1c2dd126863a84465ae8ef66114be99" integrity sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw== +"@babel/parser@^7.15.4", "@babel/parser@^7.15.5", "@babel/parser@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae" + integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g== + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz#dbdeabb1e80f622d9f0b583efb2999605e0a567e" + integrity sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" + "@babel/plugin-proposal-optional-chaining" "^7.14.5" + "@babel/plugin-proposal-async-generator-functions@^7.12.1", "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e" @@ -340,6 +602,15 @@ "@babel/helper-remap-async-to-generator" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" +"@babel/plugin-proposal-async-generator-functions@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.4.tgz#f82aabe96c135d2ceaa917feb9f5fca31635277e" + integrity sha512-2zt2g5vTXpMC3OmK6uyjvdXptbhBXfA77XGrd3gh93zwG8lZYBLOBImiGBEG0RANu3JqKEACCz5CGk73OJROBw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-remap-async-to-generator" "^7.15.4" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-proposal-class-properties@7.3.0": version "7.3.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz#272636bc0fa19a0bc46e601ec78136a173ea36cd" @@ -356,6 +627,23 @@ "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-proposal-class-properties@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz#40d1ee140c5b1e31a350f4f5eed945096559b42e" + integrity sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-proposal-class-static-block@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz#3e7ca6128453c089e8b477a99f970c63fc1cb8d7" + integrity sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-proposal-decorators@^7.12.1": version "7.13.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.13.5.tgz#d28071457a5ba8ee1394b23e38d5dcf32ea20ef7" @@ -373,6 +661,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" +"@babel/plugin-proposal-dynamic-import@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz#0c6617df461c0c1f8fff3b47cd59772360101d2c" + integrity sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-export-default-from@^7.12.1": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.12.13.tgz#f110284108a9b2b96f01b15b3be9e54c2610a989" @@ -389,6 +685,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" +"@babel/plugin-proposal-export-namespace-from@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz#dbad244310ce6ccd083072167d8cea83a52faf76" + integrity sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-proposal-json-strings@^7.12.1", "@babel/plugin-proposal-json-strings@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" @@ -397,6 +701,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" +"@babel/plugin-proposal-json-strings@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz#38de60db362e83a3d8c944ac858ddf9f0c2239eb" + integrity sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-proposal-logical-assignment-operators@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" @@ -405,6 +717,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" +"@babel/plugin-proposal-logical-assignment-operators@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz#6e6229c2a99b02ab2915f82571e0cc646a40c738" + integrity sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" @@ -413,6 +733,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" +"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz#ee38589ce00e2cc59b299ec3ea406fcd3a0fdaf6" + integrity sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator@^7.12.7": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" @@ -421,6 +749,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" +"@babel/plugin-proposal-numeric-separator@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz#83631bf33d9a51df184c2102a069ac0c58c05f18" + integrity sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread@7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" @@ -438,6 +774,17 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" +"@babel/plugin-proposal-object-rest-spread@^7.15.6": + version "7.15.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz#ef68050c8703d07b25af402cb96cf7f34a68ed11" + integrity sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg== + dependencies: + "@babel/compat-data" "^7.15.0" + "@babel/helper-compilation-targets" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.15.4" + "@babel/plugin-proposal-optional-catch-binding@^7.12.1", "@babel/plugin-proposal-optional-catch-binding@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" @@ -446,6 +793,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" +"@babel/plugin-proposal-optional-catch-binding@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz#939dd6eddeff3a67fdf7b3f044b5347262598c3c" + integrity sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.12.7": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" @@ -455,6 +810,15 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" "@babel/plugin-syntax-optional-chaining" "^7.8.0" +"@babel/plugin-proposal-optional-chaining@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603" + integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-private-methods@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" @@ -463,6 +827,24 @@ "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-proposal-private-methods@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz#37446495996b2945f30f5be5b60d5e2aa4f5792d" + integrity sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-proposal-private-property-in-object@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz#55c5e3b4d0261fd44fe637e3f624cfb0f484e3e5" + integrity sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.15.4" + "@babel/helper-create-class-features-plugin" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" @@ -471,6 +853,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-proposal-unicode-property-regex@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz#0f95ee0e757a5d647f378daa0eca7e93faa8bbe8" + integrity sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-async-generators@^7.2.0", "@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -492,6 +882,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-decorators@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.12.13.tgz#fac829bf3c7ef4a1bc916257b403e58c6bdaf648" @@ -555,6 +959,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" +"@babel/plugin-syntax-jsx@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201" + integrity sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" @@ -597,6 +1008,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-top-level-await@^7.12.1", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" @@ -604,6 +1022,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-typescript@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz#460ba9d77077653803c3dd2e673f76d66b4029e5" @@ -611,6 +1036,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-typescript@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" + integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-arrow-functions@^7.12.1", "@babel/plugin-transform-arrow-functions@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" @@ -618,6 +1050,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-arrow-functions@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz#f7187d9588a768dd080bf4c9ffe117ea62f7862a" + integrity sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-async-to-generator@^7.12.1", "@babel/plugin-transform-async-to-generator@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" @@ -627,6 +1066,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-remap-async-to-generator" "^7.12.1" +"@babel/plugin-transform-async-to-generator@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz#72c789084d8f2094acb945633943ef8443d39e67" + integrity sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA== + dependencies: + "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-remap-async-to-generator" "^7.14.5" + "@babel/plugin-transform-block-scoped-functions@^7.12.1", "@babel/plugin-transform-block-scoped-functions@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" @@ -634,6 +1082,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-block-scoped-functions@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz#e48641d999d4bc157a67ef336aeb54bc44fd3ad4" + integrity sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-block-scoping@^7.12.1", "@babel/plugin-transform-block-scoping@^7.12.11", "@babel/plugin-transform-block-scoping@^7.4.4": version "7.12.12" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" @@ -641,6 +1096,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-block-scoping@^7.15.3": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz#94c81a6e2fc230bcce6ef537ac96a1e4d2b3afaf" + integrity sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" @@ -655,6 +1117,19 @@ "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz#50aee17aaf7f332ae44e3bce4c2e10534d5d3bf1" + integrity sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.15.4" + "@babel/helper-function-name" "^7.15.4" + "@babel/helper-optimise-call-expression" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-replace-supers" "^7.15.4" + "@babel/helper-split-export-declaration" "^7.15.4" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.12.1", "@babel/plugin-transform-computed-properties@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" @@ -662,6 +1137,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-computed-properties@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz#1b9d78987420d11223d41195461cc43b974b204f" + integrity sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" @@ -669,6 +1151,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-destructuring@^7.14.7": + version "7.14.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz#0ad58ed37e23e22084d109f185260835e5557576" + integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" @@ -677,6 +1166,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-dotall-regex@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz#2f6bf76e46bdf8043b4e7e16cf24532629ba0c7a" + integrity sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-duplicate-keys@^7.12.1", "@babel/plugin-transform-duplicate-keys@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" @@ -684,6 +1181,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-duplicate-keys@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz#365a4844881bdf1501e3a9f0270e7f0f91177954" + integrity sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-exponentiation-operator@^7.12.1", "@babel/plugin-transform-exponentiation-operator@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" @@ -692,6 +1196,14 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-exponentiation-operator@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz#5154b8dd6a3dfe6d90923d61724bd3deeb90b493" + integrity sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-flow-strip-types@^7.12.13": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.13.0.tgz#58177a48c209971e8234e99906cb6bd1122addd3" @@ -707,6 +1219,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-for-of@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz#25c62cce2718cfb29715f416e75d5263fb36a8c2" + integrity sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-function-name@^7.12.1", "@babel/plugin-transform-function-name@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" @@ -715,6 +1234,14 @@ "@babel/helper-function-name" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-function-name@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz#e81c65ecb900746d7f31802f6bed1f52d915d6f2" + integrity sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ== + dependencies: + "@babel/helper-function-name" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-literals@^7.12.1", "@babel/plugin-transform-literals@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" @@ -722,6 +1249,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-literals@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz#41d06c7ff5d4d09e3cf4587bd3ecf3930c730f78" + integrity sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-member-expression-literals@^7.12.1", "@babel/plugin-transform-member-expression-literals@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" @@ -729,6 +1263,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-member-expression-literals@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz#b39cd5212a2bf235a617d320ec2b48bcc091b8a7" + integrity sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-modules-amd@^7.12.1", "@babel/plugin-transform-modules-amd@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" @@ -738,6 +1279,15 @@ "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-amd@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz#4fd9ce7e3411cb8b83848480b7041d83004858f7" + integrity sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g== + dependencies: + "@babel/helper-module-transforms" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@^7.12.1", "@babel/plugin-transform-modules-commonjs@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" @@ -748,6 +1298,16 @@ "@babel/helper-simple-access" "^7.12.1" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-commonjs@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz#8201101240eabb5a76c08ef61b2954f767b6b4c1" + integrity sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA== + dependencies: + "@babel/helper-module-transforms" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-simple-access" "^7.15.4" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-systemjs@^7.12.1", "@babel/plugin-transform-modules-systemjs@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" @@ -759,6 +1319,17 @@ "@babel/helper-validator-identifier" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-systemjs@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz#b42890c7349a78c827719f1d2d0cd38c7d268132" + integrity sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw== + dependencies: + "@babel/helper-hoist-variables" "^7.15.4" + "@babel/helper-module-transforms" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-validator-identifier" "^7.14.9" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-umd@^7.12.1", "@babel/plugin-transform-modules-umd@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" @@ -767,6 +1338,14 @@ "@babel/helper-module-transforms" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-modules-umd@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz#fb662dfee697cce274a7cda525190a79096aa6e0" + integrity sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA== + dependencies: + "@babel/helper-module-transforms" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-named-capturing-groups-regex@^7.12.1", "@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" @@ -774,6 +1353,13 @@ dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" +"@babel/plugin-transform-named-capturing-groups-regex@^7.14.9": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2" + integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/plugin-transform-new-target@^7.12.1", "@babel/plugin-transform-new-target@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" @@ -781,6 +1367,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-new-target@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz#31bdae8b925dc84076ebfcd2a9940143aed7dbf8" + integrity sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-object-super@^7.12.1", "@babel/plugin-transform-object-super@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" @@ -789,6 +1382,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-replace-supers" "^7.12.1" +"@babel/plugin-transform-object-super@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz#d0b5faeac9e98597a161a9cf78c527ed934cdc45" + integrity sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-replace-supers" "^7.14.5" + "@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" @@ -796,6 +1397,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-parameters@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz#5f2285cc3160bf48c8502432716b48504d29ed62" + integrity sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-property-literals@^7.12.1", "@babel/plugin-transform-property-literals@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" @@ -803,6 +1411,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-property-literals@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz#0ddbaa1f83db3606f1cdf4846fa1dfb473458b34" + integrity sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-react-display-name@^7.0.0", "@babel/plugin-transform-react-display-name@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" @@ -810,6 +1425,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-react-display-name@^7.14.5": + version "7.15.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz#6aaac6099f1fcf6589d35ae6be1b6e10c8c602b9" + integrity sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-react-jsx-development@^7.12.7": version "7.12.12" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" @@ -817,6 +1439,13 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.12.12" +"@babel/plugin-transform-react-jsx-development@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz#1a6c73e2f7ed2c42eebc3d2ad60b0c7494fcb9af" + integrity sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.14.5" + "@babel/plugin-transform-react-jsx-self@^7.0.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" @@ -844,6 +1473,17 @@ "@babel/plugin-syntax-jsx" "^7.12.1" "@babel/types" "^7.12.12" +"@babel/plugin-transform-react-jsx@^7.14.5": + version "7.14.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz#3314b2163033abac5200a869c4de242cd50a914c" + integrity sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-jsx" "^7.14.5" + "@babel/types" "^7.14.9" + "@babel/plugin-transform-react-pure-annotations@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" @@ -852,6 +1492,14 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-react-pure-annotations@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.14.5.tgz#18de612b84021e3a9802cbc212c9d9f46d0d11fc" + integrity sha512-3X4HpBJimNxW4rhUy/SONPyNQHp5YRr0HhJdT2OH1BRp0of7u3Dkirc7x9FRJMKMqTBI079VZ1hzv7Ouuz///g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-regenerator@^7.12.1", "@babel/plugin-transform-regenerator@^7.4.5": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" @@ -859,6 +1507,13 @@ dependencies: regenerator-transform "^0.14.2" +"@babel/plugin-transform-regenerator@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz#9676fd5707ed28f522727c5b3c0aa8544440b04f" + integrity sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg== + dependencies: + regenerator-transform "^0.14.2" + "@babel/plugin-transform-reserved-words@^7.12.1", "@babel/plugin-transform-reserved-words@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" @@ -866,6 +1521,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-reserved-words@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz#c44589b661cfdbef8d4300dcc7469dffa92f8304" + integrity sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-runtime@7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.2.0.tgz#566bc43f7d0aedc880eaddbd29168d0f248966ea" @@ -876,14 +1538,17 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-runtime@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz#af0fded4e846c4b37078e8e5d06deac6cd848562" - integrity sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA== - dependencies: - "@babel/helper-module-imports" "^7.12.5" - "@babel/helper-plugin-utils" "^7.10.4" - semver "^5.5.1" +"@babel/plugin-transform-runtime@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz#d3aa650d11678ca76ce294071fda53d7804183b3" + integrity sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw== + dependencies: + "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + babel-plugin-polyfill-corejs2 "^0.2.2" + babel-plugin-polyfill-corejs3 "^0.2.2" + babel-plugin-polyfill-regenerator "^0.2.2" + semver "^6.3.0" "@babel/plugin-transform-shorthand-properties@^7.12.1", "@babel/plugin-transform-shorthand-properties@^7.2.0": version "7.12.1" @@ -892,6 +1557,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-shorthand-properties@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz#97f13855f1409338d8cadcbaca670ad79e091a58" + integrity sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-spread@^7.12.1", "@babel/plugin-transform-spread@^7.2.0": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" @@ -900,6 +1572,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" +"@babel/plugin-transform-spread@^7.14.6": + version "7.14.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz#6bd40e57fe7de94aa904851963b5616652f73144" + integrity sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" + "@babel/plugin-transform-sticky-regex@^7.12.7", "@babel/plugin-transform-sticky-regex@^7.2.0": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" @@ -907,6 +1587,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-sticky-regex@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz#5b617542675e8b7761294381f3c28c633f40aeb9" + integrity sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-template-literals@^7.12.1", "@babel/plugin-transform-template-literals@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" @@ -914,6 +1601,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-template-literals@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz#a5f2bc233937d8453885dc736bdd8d9ffabf3d93" + integrity sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-typeof-symbol@^7.12.10", "@babel/plugin-transform-typeof-symbol@^7.2.0": version "7.12.10" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" @@ -921,6 +1615,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-typeof-symbol@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz#39af2739e989a2bd291bf6b53f16981423d457d4" + integrity sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-typescript@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz#d92cc0af504d510e26a754a7dbc2e5c8cd9c7ab4" @@ -930,6 +1631,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-typescript" "^7.12.1" +"@babel/plugin-transform-typescript@^7.15.0": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.4.tgz#db7a062dcf8be5fc096bc0eeb40a13fbfa1fa251" + integrity sha512-sM1/FEjwYjXvMwu1PJStH11kJ154zd/lpY56NQJ5qH2D0mabMv1CAy/kdvS9RP4Xgfj9fBBA3JiSLdDHgXdzOA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-syntax-typescript" "^7.14.5" + "@babel/plugin-transform-unicode-escapes@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" @@ -937,6 +1647,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-unicode-escapes@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz#9d4bd2a681e3c5d7acf4f57fa9e51175d91d0c6b" + integrity sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-unicode-regex@^7.12.1", "@babel/plugin-transform-unicode-regex@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" @@ -945,6 +1662,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-unicode-regex@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz#4cd09b6c8425dd81255c7ceb3fb1836e7414382e" + integrity sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/preset-env@7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.5.tgz#2fad7f62983d5af563b5f3139242755884998a58" @@ -999,7 +1724,7 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.12.11": +"@babel/preset-env@^7.12.1": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== @@ -1071,6 +1796,85 @@ core-js-compat "^3.8.0" semver "^5.5.0" +"@babel/preset-env@^7.15.6": + version "7.15.6" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.6.tgz#0f3898db9d63d320f21b17380d8462779de57659" + integrity sha512-L+6jcGn7EWu7zqaO2uoTDjjMBW+88FXzV8KvrBl2z6MtRNxlsmUNRlZPaNNPUTgqhyC5DHNFk/2Jmra+ublZWw== + dependencies: + "@babel/compat-data" "^7.15.0" + "@babel/helper-compilation-targets" "^7.15.4" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-validator-option" "^7.14.5" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.15.4" + "@babel/plugin-proposal-async-generator-functions" "^7.15.4" + "@babel/plugin-proposal-class-properties" "^7.14.5" + "@babel/plugin-proposal-class-static-block" "^7.15.4" + "@babel/plugin-proposal-dynamic-import" "^7.14.5" + "@babel/plugin-proposal-export-namespace-from" "^7.14.5" + "@babel/plugin-proposal-json-strings" "^7.14.5" + "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" + "@babel/plugin-proposal-numeric-separator" "^7.14.5" + "@babel/plugin-proposal-object-rest-spread" "^7.15.6" + "@babel/plugin-proposal-optional-catch-binding" "^7.14.5" + "@babel/plugin-proposal-optional-chaining" "^7.14.5" + "@babel/plugin-proposal-private-methods" "^7.14.5" + "@babel/plugin-proposal-private-property-in-object" "^7.15.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.14.5" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.14.5" + "@babel/plugin-transform-async-to-generator" "^7.14.5" + "@babel/plugin-transform-block-scoped-functions" "^7.14.5" + "@babel/plugin-transform-block-scoping" "^7.15.3" + "@babel/plugin-transform-classes" "^7.15.4" + "@babel/plugin-transform-computed-properties" "^7.14.5" + "@babel/plugin-transform-destructuring" "^7.14.7" + "@babel/plugin-transform-dotall-regex" "^7.14.5" + "@babel/plugin-transform-duplicate-keys" "^7.14.5" + "@babel/plugin-transform-exponentiation-operator" "^7.14.5" + "@babel/plugin-transform-for-of" "^7.15.4" + "@babel/plugin-transform-function-name" "^7.14.5" + "@babel/plugin-transform-literals" "^7.14.5" + "@babel/plugin-transform-member-expression-literals" "^7.14.5" + "@babel/plugin-transform-modules-amd" "^7.14.5" + "@babel/plugin-transform-modules-commonjs" "^7.15.4" + "@babel/plugin-transform-modules-systemjs" "^7.15.4" + "@babel/plugin-transform-modules-umd" "^7.14.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.9" + "@babel/plugin-transform-new-target" "^7.14.5" + "@babel/plugin-transform-object-super" "^7.14.5" + "@babel/plugin-transform-parameters" "^7.15.4" + "@babel/plugin-transform-property-literals" "^7.14.5" + "@babel/plugin-transform-regenerator" "^7.14.5" + "@babel/plugin-transform-reserved-words" "^7.14.5" + "@babel/plugin-transform-shorthand-properties" "^7.14.5" + "@babel/plugin-transform-spread" "^7.14.6" + "@babel/plugin-transform-sticky-regex" "^7.14.5" + "@babel/plugin-transform-template-literals" "^7.14.5" + "@babel/plugin-transform-typeof-symbol" "^7.14.5" + "@babel/plugin-transform-unicode-escapes" "^7.14.5" + "@babel/plugin-transform-unicode-regex" "^7.14.5" + "@babel/preset-modules" "^0.1.4" + "@babel/types" "^7.15.6" + babel-plugin-polyfill-corejs2 "^0.2.2" + babel-plugin-polyfill-corejs3 "^0.2.2" + babel-plugin-polyfill-regenerator "^0.2.2" + core-js-compat "^3.16.0" + semver "^6.3.0" + "@babel/preset-flow@^7.12.1": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.12.13.tgz#71ee7fe65a95b507ac12bcad65a4ced27d8dfc3e" @@ -1090,6 +1894,17 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" +"@babel/preset-modules@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + "@babel/preset-react@7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.0.0.tgz#e86b4b3d99433c7b3e9e91747e2653958bc6b3c0" @@ -1101,7 +1916,7 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" -"@babel/preset-react@^7.12.1", "@babel/preset-react@^7.12.10": +"@babel/preset-react@^7.12.1": version "7.12.10" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== @@ -1112,7 +1927,19 @@ "@babel/plugin-transform-react-jsx-development" "^7.12.7" "@babel/plugin-transform-react-pure-annotations" "^7.12.1" -"@babel/preset-typescript@^7.12.1", "@babel/preset-typescript@^7.12.7": +"@babel/preset-react@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.14.5.tgz#0fbb769513f899c2c56f3a882fa79673c2d4ab3c" + integrity sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-validator-option" "^7.14.5" + "@babel/plugin-transform-react-display-name" "^7.14.5" + "@babel/plugin-transform-react-jsx" "^7.14.5" + "@babel/plugin-transform-react-jsx-development" "^7.14.5" + "@babel/plugin-transform-react-pure-annotations" "^7.14.5" + +"@babel/preset-typescript@^7.12.1": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz#fc7df8199d6aae747896f1e6c61fc872056632a3" integrity sha512-nOoIqIqBmHBSEgBXWR4Dv/XBehtIFcw9PqZw6rFYuKrzsZmOQm3PR5siLBnKZFEsDb03IegG8nSjU/iXXXYRmw== @@ -1121,7 +1948,16 @@ "@babel/helper-validator-option" "^7.12.1" "@babel/plugin-transform-typescript" "^7.12.1" -"@babel/register@^7.12.1", "@babel/register@^7.12.10": +"@babel/preset-typescript@^7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz#e8fca638a1a0f64f14e1119f7fe4500277840945" + integrity sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-validator-option" "^7.14.5" + "@babel/plugin-transform-typescript" "^7.15.0" + +"@babel/register@^7.12.1": version "7.12.10" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.12.10.tgz#19b87143f17128af4dbe7af54c735663b3999f60" integrity sha512-EvX/BvMMJRAA3jZgILWgbsrHwBQvllC5T8B29McyME8DvkdOxk4ujESfrMvME8IHSDvWXrmMXxPvA/lx2gqPLQ== @@ -1132,6 +1968,17 @@ pirates "^4.0.0" source-map-support "^0.5.16" +"@babel/register@^7.15.3": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.15.3.tgz#6b40a549e06ec06c885b2ec42c3dd711f55fe752" + integrity sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw== + dependencies: + clone-deep "^4.0.1" + find-cache-dir "^2.0.0" + make-dir "^2.1.0" + pirates "^4.0.0" + source-map-support "^0.5.16" + "@babel/runtime-corejs3@^7.10.2": version "7.11.2" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz#02c3029743150188edeb66541195f54600278419" @@ -1161,6 +2008,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" + integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4", "@babel/template@^7.12.13", "@babel/template@^7.12.7", "@babel/template@^7.3.3", "@babel/template@^7.4.4": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" @@ -1170,7 +2024,16 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.12", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": +"@babel/template@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" + integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/parser" "^7.15.4" + "@babel/types" "^7.15.4" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== @@ -1185,12 +2048,27 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.14.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.5.tgz#3bb997ba829a2104cedb20689c4a5b8121d383ff" - integrity sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg== +"@babel/traverse@^7.15.4": + version "7.15.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" + integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== + dependencies: + "@babel/code-frame" "^7.14.5" + "@babel/generator" "^7.15.4" + "@babel/helper-function-name" "^7.15.4" + "@babel/helper-hoist-variables" "^7.15.4" + "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/parser" "^7.15.4" + "@babel/types" "^7.15.4" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.14.5", "@babel/types@^7.14.9", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": + version "7.15.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" + integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== dependencies: - "@babel/helper-validator-identifier" "^7.14.5" + "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" "@base2/pretty-print-object@1.0.0": @@ -3252,22 +4130,10 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": - version "2.1.8-no-fsevents" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b" - integrity sha512-+nb9vWloHNNMFHjGofEam3wopE3m1yuambrrd/fnPc+lFOMB9ROTqQlche9ByFWNkdNqfSgR/kkQtQ8DzEWt2w== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" +"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": + version "2.1.8-no-fsevents.3" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" + integrity sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ== "@nodelib/fs.scandir@2.1.3": version "2.1.3" @@ -4873,10 +5739,10 @@ "@types/babel__template" "*" "@types/babel__traverse" "*" -"@types/babel__core@^7.1.12": - version "7.1.12" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d" - integrity sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ== +"@types/babel__core@^7.1.16": + version "7.1.16" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702" + integrity sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -7655,11 +8521,6 @@ async-done@^1.2.0, async-done@^1.2.2: process-nextick-args "^2.0.0" stream-exhaust "^1.0.1" -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" @@ -8127,6 +8988,30 @@ babel-plugin-named-asset-import@^0.3.1: resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.3.tgz#9ba2f3ac4dc78b042651654f07e847adfe50667c" integrity sha512-1XDRysF4894BUdMChT+2HHbtJYiO7zx5Be7U6bT8dISy7OdyETMGIAQBMPQCsY1YRf0xcubwnKKaDr5bk15JTA== +babel-plugin-polyfill-corejs2@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" + integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.2.2" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.2.2: + version "0.2.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" + integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.2.2" + core-js-compat "^3.16.2" + +babel-plugin-polyfill-regenerator@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" + integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.2.2" + babel-plugin-react-docgen@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.2.1.tgz#7cc8e2f94e8dc057a06e953162f0810e4e72257b" @@ -8141,7 +9026,7 @@ babel-plugin-require-context-hook@^1.0.0: resolved "https://registry.yarnpkg.com/babel-plugin-require-context-hook-babel7/-/babel-plugin-require-context-hook-babel7-1.0.0.tgz#1273d4cee7e343d0860966653759a45d727e815d" integrity sha512-kez0BAN/cQoyO1Yu1nre1bQSYZEF93Fg7VQiBHFfMWuaZTy7vJSTT4FY68FwHTYG53Nyt0A7vpSObSVxwweQeQ== -"babel-plugin-styled-components@>= 1", babel-plugin-styled-components@^1.10.7: +"babel-plugin-styled-components@>= 1": version "1.10.7" resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.7.tgz#3494e77914e9989b33cc2d7b3b29527a949d635c" integrity sha512-MBMHGcIA22996n9hZRf/UJLVVgkEOITuR2SvjHLb5dSTUyR4ZRGn+ngITapes36FI3WLxZHfRhkA1ffHxihOrg== @@ -8151,6 +9036,16 @@ babel-plugin-require-context-hook@^1.0.0: babel-plugin-syntax-jsx "^6.18.0" lodash "^4.17.11" +babel-plugin-styled-components@^1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz#ebe0e6deff51d7f93fceda1819e9b96aeb88278d" + integrity sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-module-imports" "^7.0.0" + babel-plugin-syntax-jsx "^6.18.0" + lodash "^4.17.11" + babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -8484,11 +9379,6 @@ bin-build@^3.0.0: p-map-series "^1.0.0" tempfile "^2.0.0" -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - binary-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" @@ -8642,7 +9532,7 @@ brace@0.11.1, brace@^0.11.1: resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58" integrity sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg= -braces@^2.3.1, braces@^2.3.2: +braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -8953,6 +9843,17 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4 escalade "^3.1.1" node-releases "^1.1.70" +browserslist@^4.16.6, browserslist@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.1.tgz#a98d104f54af441290b7d592626dd541fa642eb9" + integrity sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ== + dependencies: + caniuse-lite "^1.0.30001259" + electron-to-chromium "^1.3.846" + escalade "^3.1.1" + nanocolors "^0.1.5" + node-releases "^1.1.76" + bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" @@ -9321,6 +10222,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001097, caniuse-lite@^1.0.30001109, can resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001258.tgz" integrity sha512-RBByOG6xWXUp0CR2/WU2amXz3stjKpSl5J1xU49F1n2OxD//uBZO4wCKUiG+QMGf7CHGfDDcqoKriomoGVxTeA== +caniuse-lite@^1.0.30001259: + version "1.0.30001261" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001261.tgz#96d89813c076ea061209a4e040d8dcf0c66a1d01" + integrity sha512-vM8D9Uvp7bHIN0fZ2KQ4wnmYFpJo/Etb4Vwsuc+ka0tfGDHvOPrFm6S/7CCNLSOkAUjenT2HnUPESdOIL91FaA== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -9793,6 +10699,15 @@ clone-buffer@^1.0.0: resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + clone-regexp@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f" @@ -10396,6 +11311,14 @@ core-js-compat@^3.1.1: browserslist "^4.8.5" semver "7.0.0" +core-js-compat@^3.16.0, core-js-compat@^3.16.2: + version "3.18.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.1.tgz#01942a0877caf9c6e5007c027183cf0bdae6a191" + integrity sha512-XJMYx58zo4W0kLPmIingVZA10+7TuKrMLPt83+EzDmxFJQUMcTVVmQ+n5JP4r6Z14qSzhQBRi3NSWoeVyKKXUg== + dependencies: + browserslist "^4.17.1" + semver "7.0.0" + core-js-compat@^3.8.0: version "3.8.3" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" @@ -12577,6 +13500,11 @@ electron-to-chromium@^1.3.649: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.690.tgz#54df63ec42fba6b8e9e05fe4be52caeeedb6e634" integrity sha512-zPbaSv1c8LUKqQ+scNxJKv01RYFkVVF1xli+b+3Ty8ONujHjAMg+t/COmdZqrtnS1gT+g4hbSodHillymt1Lww== +electron-to-chromium@^1.3.846: + version "1.3.853" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.853.tgz#f3ed1d31f092cb3a17af188bca6c6a3ec91c3e82" + integrity sha512-W4U8n+U8I5/SUaFcqZgbKRmYZwcyEIQVBDf+j5QQK6xChjXnQD+wj248eGR9X4u+dDmDR//8vIfbu4PrdBBIoQ== + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" @@ -14687,6 +15615,11 @@ gensync@^1.0.0-beta.1: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + geojson-flatten@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/geojson-flatten/-/geojson-flatten-1.0.4.tgz#cdfef2e9042996fcaa14fe658db6d88c99c20930" @@ -16622,13 +17555,6 @@ is-bigint@^1.0.1: resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.1.tgz#6923051dfcbc764278540b9ce0e6b3213aa5ebc2" integrity sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg== -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -16691,6 +17617,13 @@ is-core-module@^2.1.0: dependencies: has "^1.0.3" +is-core-module@^2.2.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3" + integrity sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -20403,6 +21336,11 @@ nano-time@1.0.0: dependencies: big-integer "^1.6.16" +nanocolors@^0.1.5: + version "0.1.12" + resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" + integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== + nanoid@3.1.12: version "3.1.12" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654" @@ -20745,6 +21683,11 @@ node-releases@^1.1.70: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== +node-releases@^1.1.76: + version "1.1.76" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.76.tgz#df245b062b0cafbd5282ab6792f7dccc2d97f36e" + integrity sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA== + node-sass@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-6.0.1.tgz#cad1ccd0ce63e35c7181f545d8b986f3a9a887fe" @@ -24247,15 +25190,6 @@ readdir-scoped-modules@^1.0.0: graceful-fs "^4.1.2" once "^1.3.0" -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - readdirp@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" @@ -25001,6 +25935,14 @@ resolve@^1.1.10, resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, is-core-module "^2.1.0" path-parse "^1.0.6" +resolve@^1.14.2: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + resolve@~1.10.1: version "1.10.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.1.tgz#664842ac960795bbe758221cdccda61fb64b5f18" @@ -25484,7 +26426,7 @@ semver@7.3.2, semver@^7.3.2, semver@~7.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -25661,6 +26603,13 @@ shallow-clone-shim@^2.0.0: resolved "https://registry.yarnpkg.com/shallow-clone-shim/-/shallow-clone-shim-2.0.0.tgz#b62bf55aed79f4c1430ea1dc4d293a193f52cf91" integrity sha512-YRNymdiL3KGOoS67d73TEmk4tdPTO9GSMCoiphQsTcC9EtC+AOmMPjkyBkRoCJfW9ASsaZw1craaiw1dPN2D3Q== +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + shallow-copy@~0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" @@ -28683,11 +29632,6 @@ untildify@^4.0.0: resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - update-notifier@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc" From f86e78f878b1305bdc0443930129e52e6fb9d312 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Fri, 1 Oct 2021 19:01:42 -0400 Subject: [PATCH 17/98] [Buildkite] Pull Request pipeline (#112029) --- .buildkite/pipelines/es_snapshots/verify.yml | 2 +- .buildkite/pipelines/hourly.yml | 2 +- .../pipelines/pull_request/apm_cypress.yml | 11 ++ .buildkite/pipelines/pull_request/base.yml | 155 ++++++++++++++++++ .../pipelines/pull_request/post_build.yml | 6 + .../pull_request/security_solution.yml | 11 ++ .buildkite/scripts/common/env.sh | 10 +- .buildkite/scripts/common/util.sh | 12 ++ .buildkite/scripts/lifecycle/post_build.sh | 9 + .../pipelines/pull_request/pipeline.js | 84 ++++++++++ .../pipelines/pull_request/pipeline.sh | 5 + .../scripts/steps/functional/apm_cypress.sh | 14 ++ .../steps/functional/security_solution.sh | 17 ++ .../steps/storybooks/build_and_upload.js | 6 + 14 files changed, 341 insertions(+), 3 deletions(-) create mode 100644 .buildkite/pipelines/pull_request/apm_cypress.yml create mode 100644 .buildkite/pipelines/pull_request/base.yml create mode 100644 .buildkite/pipelines/pull_request/post_build.yml create mode 100644 .buildkite/pipelines/pull_request/security_solution.yml create mode 100644 .buildkite/scripts/pipelines/pull_request/pipeline.js create mode 100755 .buildkite/scripts/pipelines/pull_request/pipeline.sh create mode 100755 .buildkite/scripts/steps/functional/apm_cypress.sh create mode 100755 .buildkite/scripts/steps/functional/security_solution.sh diff --git a/.buildkite/pipelines/es_snapshots/verify.yml b/.buildkite/pipelines/es_snapshots/verify.yml index 61212e1fcf0a8..b9aa0e0e3727a 100755 --- a/.buildkite/pipelines/es_snapshots/verify.yml +++ b/.buildkite/pipelines/es_snapshots/verify.yml @@ -19,7 +19,7 @@ steps: - command: .buildkite/scripts/steps/build_kibana.sh label: Build Kibana Distribution and Plugins agents: - queue: c2-8 + queue: c2-16 key: build if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''" diff --git a/.buildkite/pipelines/hourly.yml b/.buildkite/pipelines/hourly.yml index 279c8cf96bfe3..7aa8528dc3d9a 100644 --- a/.buildkite/pipelines/hourly.yml +++ b/.buildkite/pipelines/hourly.yml @@ -9,7 +9,7 @@ steps: - command: .buildkite/scripts/steps/build_kibana.sh label: Build Kibana Distribution and Plugins agents: - queue: c2-8 + queue: c2-16 key: build if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''" diff --git a/.buildkite/pipelines/pull_request/apm_cypress.yml b/.buildkite/pipelines/pull_request/apm_cypress.yml new file mode 100644 index 0000000000000..8dcdc6c4b5f39 --- /dev/null +++ b/.buildkite/pipelines/pull_request/apm_cypress.yml @@ -0,0 +1,11 @@ +steps: + - command: .buildkite/scripts/steps/functional/apm_cypress.sh + label: 'APM Cypress Tests' + agents: + queue: ci-group-6 + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 diff --git a/.buildkite/pipelines/pull_request/base.yml b/.buildkite/pipelines/pull_request/base.yml new file mode 100644 index 0000000000000..1da3f654b7253 --- /dev/null +++ b/.buildkite/pipelines/pull_request/base.yml @@ -0,0 +1,155 @@ +steps: + - command: .buildkite/scripts/lifecycle/pre_build.sh + label: Pre-Build + + - wait + + - command: .buildkite/scripts/steps/build_kibana.sh + label: Build Kibana Distribution and Plugins + agents: + queue: c2-16 + key: build + if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''" + + - command: .buildkite/scripts/steps/functional/xpack_cigroup.sh + label: 'Default CI Group' + parallelism: 13 + agents: + queue: ci-group-6 + depends_on: build + timeout_in_minutes: 120 + key: default-cigroup + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: CI_GROUP=Docker .buildkite/scripts/steps/functional/xpack_cigroup.sh + label: 'Docker CI Group' + agents: + queue: ci-group-6 + depends_on: build + timeout_in_minutes: 120 + key: default-cigroup-docker + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/oss_cigroup.sh + label: 'OSS CI Group' + parallelism: 11 + agents: + queue: ci-group-4d + depends_on: build + timeout_in_minutes: 120 + key: oss-cigroup + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/oss_accessibility.sh + label: 'OSS Accessibility Tests' + agents: + queue: ci-group-4d + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/xpack_accessibility.sh + label: 'Default Accessibility Tests' + agents: + queue: ci-group-6 + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/oss_firefox.sh + label: 'OSS Firefox Tests' + agents: + queue: ci-group-4d + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/xpack_firefox.sh + label: 'Default Firefox Tests' + agents: + queue: ci-group-6 + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/oss_misc.sh + label: 'OSS Misc Functional Tests' + agents: + queue: ci-group-4d + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh + label: 'Saved Object Field Metrics' + agents: + queue: ci-group-6 + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/test/jest_integration.sh + label: 'Jest Integration Tests' + agents: + queue: n2-4 + timeout_in_minutes: 120 + key: jest-integration + + - command: .buildkite/scripts/steps/test/api_integration.sh + label: 'API Integration Tests' + agents: + queue: n2-2 + timeout_in_minutes: 120 + key: api-integration + + - command: .buildkite/scripts/steps/test/jest.sh + label: 'Jest Tests' + agents: + queue: c2-16 + timeout_in_minutes: 120 + key: jest + + - command: .buildkite/scripts/steps/lint.sh + label: 'Linting' + agents: + queue: n2-2 + key: linting + + - command: .buildkite/scripts/steps/checks.sh + label: 'Checks' + agents: + queue: c2-4 + key: checks + + - command: .buildkite/scripts/steps/storybooks/build_and_upload.sh + label: 'Build Storybooks' + agents: + queue: c2-4 + key: storybooks diff --git a/.buildkite/pipelines/pull_request/post_build.yml b/.buildkite/pipelines/pull_request/post_build.yml new file mode 100644 index 0000000000000..4f252bf8abc11 --- /dev/null +++ b/.buildkite/pipelines/pull_request/post_build.yml @@ -0,0 +1,6 @@ +steps: + - wait: ~ + continue_on_failure: true + + - command: .buildkite/scripts/lifecycle/post_build.sh + label: Post-Build diff --git a/.buildkite/pipelines/pull_request/security_solution.yml b/.buildkite/pipelines/pull_request/security_solution.yml new file mode 100644 index 0000000000000..974469a700715 --- /dev/null +++ b/.buildkite/pipelines/pull_request/security_solution.yml @@ -0,0 +1,11 @@ +steps: + - command: .buildkite/scripts/steps/functional/security_solution.sh + label: 'Security Solution Tests' + agents: + queue: ci-group-6 + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '*' + limit: 1 diff --git a/.buildkite/scripts/common/env.sh b/.buildkite/scripts/common/env.sh index 282af74bbe18f..89121581c75d1 100755 --- a/.buildkite/scripts/common/env.sh +++ b/.buildkite/scripts/common/env.sh @@ -45,12 +45,20 @@ if is_pr; then export ghprbActualCommit="$BUILDKITE_COMMIT" export BUILD_URL="$BUILDKITE_BUILD_URL" - # set_git_merge_base # TODO for PRs + set_git_merge_base + + # For backwards compatibility + export PR_MERGE_BASE="$GITHUB_PR_MERGE_BASE" + export PR_TARGET_BRANCH="$GITHUB_PR_TARGET_BRANCH" else export ELASTIC_APM_ACTIVE=true export CHECKS_REPORTER_ACTIVE=false fi +# These are for backwards-compatibility +export GIT_COMMIT="$BUILDKITE_COMMIT" +export GIT_BRANCH="$BUILDKITE_BRANCH" + export FLEET_PACKAGE_REGISTRY_PORT=6104 export TEST_CORS_SERVER_PORT=6105 diff --git a/.buildkite/scripts/common/util.sh b/.buildkite/scripts/common/util.sh index d536f1a37acfd..a884a147577c9 100755 --- a/.buildkite/scripts/common/util.sh +++ b/.buildkite/scripts/common/util.sh @@ -74,3 +74,15 @@ retry() { fi done } + +set_git_merge_base() { + GITHUB_PR_MERGE_BASE="$(buildkite-agent meta-data get merge-base --default '')" + + if [[ ! "$GITHUB_PR_MERGE_BASE" ]]; then + git fetch origin "$GITHUB_PR_TARGET_BRANCH" + GITHUB_PR_MERGE_BASE="$(git merge-base HEAD FETCH_HEAD)" + buildkite-agent meta-data set merge-base "$GITHUB_PR_MERGE_BASE" + fi + + export GITHUB_PR_MERGE_BASE +} diff --git a/.buildkite/scripts/lifecycle/post_build.sh b/.buildkite/scripts/lifecycle/post_build.sh index 4577c1a9fcad4..6052814cc5f09 100755 --- a/.buildkite/scripts/lifecycle/post_build.sh +++ b/.buildkite/scripts/lifecycle/post_build.sh @@ -8,3 +8,12 @@ export BUILD_SUCCESSFUL "$(dirname "${0}")/commit_status_complete.sh" node "$(dirname "${0}")/ci_stats_complete.js" + +if [[ "$GITHUB_PR_NUMBER" ]]; then + DOCS_CHANGES_URL="https://kibana_$GITHUB_PR_NUMBER}.docs-preview.app.elstc.co/diff" + DOCS_CHANGES=$(curl --connect-timeout 10 -m 10 -sf "$DOCS_CHANGES_URL" || echo '') + + if [[ "$DOCS_CHANGES" && "$DOCS_CHANGES" != "There aren't any differences!" ]]; then + buildkite-agent meta-data set pr_comment:docs_changes:head "* [Documentation Changes](${DOCS_CHANGES_URL})" + fi +fi diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.js b/.buildkite/scripts/pipelines/pull_request/pipeline.js new file mode 100644 index 0000000000000..068de9917c213 --- /dev/null +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.js @@ -0,0 +1,84 @@ +const execSync = require('child_process').execSync; +const fs = require('fs'); +const { areChangesSkippable, doAnyChangesMatch } = require('kibana-buildkite-library'); + +const SKIPPABLE_PATHS = [ + /^docs\//, + /^rfcs\//, + /^.ci\/.+\.yml$/, + /^.ci\/es-snapshots\//, + /^.ci\/pipeline-library\//, + /^.ci\/Jenkinsfile_[^\/]+$/, + /^\.github\//, + /\.md$/, + /^\.backportrc\.json$/, +]; + +const REQUIRED_PATHS = [ + // this file is auto-generated and changes to it need to be validated with CI + /^docs\/developer\/plugin-list.asciidoc$/, + // don't skip CI on prs with changes to plugin readme files /i is for case-insensitive matching + /\/plugins\/[^\/]+\/readme\.(md|asciidoc)$/i, +]; + +const getPipeline = (filename, removeSteps = true) => { + const str = fs.readFileSync(filename).toString(); + return removeSteps ? str.replace(/^steps:/, '') : str; +}; + +const uploadPipeline = (pipelineContent) => { + const str = + typeof pipelineContent === 'string' ? pipelineContent : JSON.stringify(pipelineContent); + + execSync('buildkite-agent pipeline upload', { + input: str, + stdio: ['pipe', 'inherit', 'inherit'], + }); +}; + +(async () => { + try { + const skippable = await areChangesSkippable(SKIPPABLE_PATHS, REQUIRED_PATHS); + + if (skippable) { + console.log('All changes in PR are skippable. Skipping CI.'); + + // Since we skip everything, including post-build, we need to at least make sure the commit status gets set + execSync('BUILD_SUCCESSFUL=true .buildkite/scripts/lifecycle/commit_status_complete.sh', { + stdio: 'inherit', + }); + process.exit(0); + } + + const pipeline = []; + + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/base.yml', false)); + + if ( + await doAnyChangesMatch([ + /^x-pack\/plugins\/security_solution/, + /^x-pack\/test\/security_solution_cypress/, + /^x-pack\/plugins\/triggers_actions_ui\/public\/application\/sections\/action_connector_form/, + /^x-pack\/plugins\/triggers_actions_ui\/public\/application\/context\/actions_connectors_context\.tsx/, + ]) + ) { + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/security_solution.yml')); + } + + // Disabled for now, these are failing/disabled in Jenkins currently as well + // if ( + // await doAnyChangesMatch([ + // /^x-pack\/plugins\/apm/, + // ]) + // ) { + // pipeline.push(getPipeline('.buildkite/pipelines/pull_request/apm_cypress.yml')); + // } + + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/post_build.yml')); + + uploadPipeline(pipeline.join('\n')); + } catch (ex) { + console.error('PR pipeline generation error', ex.message); + process.exit(1); + } +})(); diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.sh b/.buildkite/scripts/pipelines/pull_request/pipeline.sh new file mode 100755 index 0000000000000..02be2acdf8588 --- /dev/null +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -euo pipefail + +node .buildkite/scripts/pipelines/pull_request/pipeline.js diff --git a/.buildkite/scripts/steps/functional/apm_cypress.sh b/.buildkite/scripts/steps/functional/apm_cypress.sh new file mode 100755 index 0000000000000..800f22c78d14c --- /dev/null +++ b/.buildkite/scripts/steps/functional/apm_cypress.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/steps/functional/common.sh + +export JOB=kibana-apm-cypress + +echo "--- APM Cypress Tests" + +cd "$XPACK_DIR" + +checks-reporter-with-killswitch "APM Cypress Tests" \ + node plugins/apm/scripts/test/e2e.js diff --git a/.buildkite/scripts/steps/functional/security_solution.sh b/.buildkite/scripts/steps/functional/security_solution.sh new file mode 100755 index 0000000000000..9b2bfc7207a95 --- /dev/null +++ b/.buildkite/scripts/steps/functional/security_solution.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/steps/functional/common.sh + +export JOB=kibana-security-solution-chrome + +echo "--- Security Solution tests (Chrome)" + +cd "$XPACK_DIR" + +checks-reporter-with-killswitch "Security Solution Cypress Tests (Chrome)" \ + node scripts/functional_tests \ + --debug --bail \ + --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ + --config test/security_solution_cypress/cli_config.ts diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.js b/.buildkite/scripts/steps/storybooks/build_and_upload.js index 49e36d2126cd4..0fdf24d87ffad 100644 --- a/.buildkite/scripts/steps/storybooks/build_and_upload.js +++ b/.buildkite/scripts/steps/storybooks/build_and_upload.js @@ -98,6 +98,12 @@ const upload = () => { gsutil -q -m cp -r -z js,css,html,json,map,txt,svg '*' 'gs://${STORYBOOK_BUCKET}/${STORYBOOK_DIRECTORY}/${process.env.BUILDKITE_COMMIT}/' gsutil -h "Cache-Control:no-cache, max-age=0, no-transform" cp -z html 'index.html' 'gs://${STORYBOOK_BUCKET}/${STORYBOOK_DIRECTORY}/latest/' `); + + if (process.env.BUILDKITE_PULL_REQUEST && process.env.BUILDKITE_PULL_REQUEST !== 'false') { + exec( + `buildkite-agent meta-data set pr_comment:storybooks:head '* [Storybooks Preview](${STORYBOOK_BASE_URL})'` + ); + } } finally { process.chdir(originalDirectory); } From 486a9e9244e7ef1f51c11086489b87be1d197c11 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Fri, 1 Oct 2021 19:40:22 -0400 Subject: [PATCH 18/98] [buildkite] Fix unbound variable in post_build script (#113687) --- .buildkite/scripts/lifecycle/post_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/scripts/lifecycle/post_build.sh b/.buildkite/scripts/lifecycle/post_build.sh index 6052814cc5f09..35e5a6006ee24 100755 --- a/.buildkite/scripts/lifecycle/post_build.sh +++ b/.buildkite/scripts/lifecycle/post_build.sh @@ -9,7 +9,7 @@ export BUILD_SUCCESSFUL node "$(dirname "${0}")/ci_stats_complete.js" -if [[ "$GITHUB_PR_NUMBER" ]]; then +if [[ "${GITHUB_PR_NUMBER:-}" ]]; then DOCS_CHANGES_URL="https://kibana_$GITHUB_PR_NUMBER}.docs-preview.app.elstc.co/diff" DOCS_CHANGES=$(curl --connect-timeout 10 -m 10 -sf "$DOCS_CHANGES_URL" || echo '') From 634fb36c028f8c566c6e5a0348a3e912091f9fa2 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Sat, 2 Oct 2021 02:38:43 +0200 Subject: [PATCH 19/98] [ML] Remove unused code. (#113263) - Removes unused code in server/lib/correlations. - The only remaining file get_filters.ts was moved to lib/search_strategies/queries. (Note at the moment Kibana search strategies are only used for correlations, but at some point we might want to restructure that possibly to lib/search_strategies/correlations/queries to make it more clear). --- ...et_correlations_for_failed_transactions.ts | 157 ------------------ .../errors/get_overall_error_timeseries.ts | 56 ------- .../get_correlations_for_slow_transactions.ts | 121 -------------- .../latency/get_duration_for_percentile.ts | 45 ----- .../latency/get_latency_distribution.ts | 98 ----------- .../correlations/latency/get_max_latency.ts | 58 ------- .../get_overall_latency_distribution.ts | 110 ------------ .../process_significant_term_aggs.ts | 80 --------- .../queries}/get_filters.ts | 10 +- .../queries/get_query_with_params.ts | 2 +- 10 files changed, 6 insertions(+), 731 deletions(-) delete mode 100644 x-pack/plugins/apm/server/lib/correlations/errors/get_correlations_for_failed_transactions.ts delete mode 100644 x-pack/plugins/apm/server/lib/correlations/errors/get_overall_error_timeseries.ts delete mode 100644 x-pack/plugins/apm/server/lib/correlations/latency/get_correlations_for_slow_transactions.ts delete mode 100644 x-pack/plugins/apm/server/lib/correlations/latency/get_duration_for_percentile.ts delete mode 100644 x-pack/plugins/apm/server/lib/correlations/latency/get_latency_distribution.ts delete mode 100644 x-pack/plugins/apm/server/lib/correlations/latency/get_max_latency.ts delete mode 100644 x-pack/plugins/apm/server/lib/correlations/latency/get_overall_latency_distribution.ts delete mode 100644 x-pack/plugins/apm/server/lib/correlations/process_significant_term_aggs.ts rename x-pack/plugins/apm/server/lib/{correlations => search_strategies/queries}/get_filters.ts (78%) diff --git a/x-pack/plugins/apm/server/lib/correlations/errors/get_correlations_for_failed_transactions.ts b/x-pack/plugins/apm/server/lib/correlations/errors/get_correlations_for_failed_transactions.ts deleted file mode 100644 index 89d9147610d69..0000000000000 --- a/x-pack/plugins/apm/server/lib/correlations/errors/get_correlations_for_failed_transactions.ts +++ /dev/null @@ -1,157 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { isEmpty, omit } from 'lodash'; -import { EventOutcome } from '../../../../common/event_outcome'; -import { - processSignificantTermAggs, - TopSigTerm, -} from '../process_significant_term_aggs'; -import { AggregationOptionsByType } from '../../../../../../../src/core/types/elasticsearch'; -import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; -import { EVENT_OUTCOME } from '../../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../helpers/setup_request'; -import { getBucketSize } from '../../helpers/get_bucket_size'; -import { - getTimeseriesAggregation, - getFailedTransactionRateTimeSeries, -} from '../../helpers/transaction_error_rate'; -import { CorrelationsOptions, getCorrelationsFilters } from '../get_filters'; - -interface Options extends CorrelationsOptions { - fieldNames: string[]; - setup: Setup; -} -export async function getCorrelationsForFailedTransactions(options: Options) { - const { fieldNames, setup, start, end } = options; - const { apmEventClient } = setup; - const filters = getCorrelationsFilters(options); - - const params = { - apm: { events: [ProcessorEvent.transaction] }, - track_total_hits: true, - body: { - size: 0, - query: { - bool: { filter: filters }, - }, - aggs: { - failed_transactions: { - filter: { term: { [EVENT_OUTCOME]: EventOutcome.failure } }, - - // significant term aggs - aggs: fieldNames.reduce((acc, fieldName) => { - return { - ...acc, - [fieldName]: { - significant_terms: { - size: 10, - field: fieldName, - background_filter: { - bool: { - filter: filters, - must_not: { - term: { [EVENT_OUTCOME]: EventOutcome.failure }, - }, - }, - }, - }, - }, - }; - }, {} as Record), - }, - }, - }, - }; - - const response = await apmEventClient.search( - 'get_correlations_for_failed_transactions', - params - ); - if (!response.aggregations) { - return { significantTerms: [] }; - } - - const sigTermAggs = omit( - response.aggregations?.failed_transactions, - 'doc_count' - ); - - const topSigTerms = processSignificantTermAggs({ sigTermAggs }); - return getErrorRateTimeSeries({ setup, filters, topSigTerms, start, end }); -} - -export async function getErrorRateTimeSeries({ - setup, - filters, - topSigTerms, - start, - end, -}: { - setup: Setup; - filters: ESFilter[]; - topSigTerms: TopSigTerm[]; - start: number; - end: number; -}) { - const { apmEventClient } = setup; - const { intervalString } = getBucketSize({ start, end, numBuckets: 15 }); - - if (isEmpty(topSigTerms)) { - return { significantTerms: [] }; - } - - const timeseriesAgg = getTimeseriesAggregation(start, end, intervalString); - - const perTermAggs = topSigTerms.reduce( - (acc, term, index) => { - acc[`term_${index}`] = { - filter: { term: { [term.fieldName]: term.fieldValue } }, - aggs: { timeseries: timeseriesAgg }, - }; - return acc; - }, - {} as { - [key: string]: { - filter: AggregationOptionsByType['filter']; - aggs: { timeseries: typeof timeseriesAgg }; - }; - } - ); - - const params = { - // TODO: add support for metrics - apm: { events: [ProcessorEvent.transaction] }, - body: { - size: 0, - query: { bool: { filter: filters } }, - aggs: perTermAggs, - }, - }; - - const response = await apmEventClient.search( - 'get_error_rate_timeseries', - params - ); - const { aggregations } = response; - - if (!aggregations) { - return { significantTerms: [] }; - } - - return { - significantTerms: topSigTerms.map((topSig, index) => { - const agg = aggregations[`term_${index}`]!; - - return { - ...topSig, - timeseries: getFailedTransactionRateTimeSeries(agg.timeseries.buckets), - }; - }), - }; -} diff --git a/x-pack/plugins/apm/server/lib/correlations/errors/get_overall_error_timeseries.ts b/x-pack/plugins/apm/server/lib/correlations/errors/get_overall_error_timeseries.ts deleted file mode 100644 index 14399a935aa52..0000000000000 --- a/x-pack/plugins/apm/server/lib/correlations/errors/get_overall_error_timeseries.ts +++ /dev/null @@ -1,56 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ProcessorEvent } from '../../../../common/processor_event'; -import { getBucketSize } from '../../helpers/get_bucket_size'; -import { - getTimeseriesAggregation, - getFailedTransactionRateTimeSeries, -} from '../../helpers/transaction_error_rate'; -import { Setup } from '../../helpers/setup_request'; -import { CorrelationsOptions, getCorrelationsFilters } from '../get_filters'; - -interface Options extends CorrelationsOptions { - setup: Setup; -} - -export async function getOverallErrorTimeseries(options: Options) { - const { setup, start, end } = options; - const filters = getCorrelationsFilters(options); - const { apmEventClient } = setup; - const { intervalString } = getBucketSize({ start, end, numBuckets: 15 }); - - const params = { - // TODO: add support for metrics - apm: { events: [ProcessorEvent.transaction] }, - body: { - size: 0, - query: { bool: { filter: filters } }, - aggs: { - timeseries: getTimeseriesAggregation(start, end, intervalString), - }, - }, - }; - - const response = await apmEventClient.search( - 'get_error_rate_timeseries', - params - ); - const { aggregations } = response; - - if (!aggregations) { - return { overall: null }; - } - - return { - overall: { - timeseries: getFailedTransactionRateTimeSeries( - aggregations.timeseries.buckets - ), - }, - }; -} diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_correlations_for_slow_transactions.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_correlations_for_slow_transactions.ts deleted file mode 100644 index 77c6fb5b1c1c6..0000000000000 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_correlations_for_slow_transactions.ts +++ /dev/null @@ -1,121 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { AggregationOptionsByType } from '../../../../../../../src/core/types/elasticsearch'; -import { TRANSACTION_DURATION } from '../../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../../common/processor_event'; -import { getDurationForPercentile } from './get_duration_for_percentile'; -import { processSignificantTermAggs } from '../process_significant_term_aggs'; -import { getLatencyDistribution } from './get_latency_distribution'; -import { withApmSpan } from '../../../utils/with_apm_span'; -import { CorrelationsOptions, getCorrelationsFilters } from '../get_filters'; -import { Setup } from '../../helpers/setup_request'; - -interface Options extends CorrelationsOptions { - durationPercentile: number; - fieldNames: string[]; - maxLatency: number; - distributionInterval: number; - setup: Setup; -} -export async function getCorrelationsForSlowTransactions(options: Options) { - return withApmSpan('get_correlations_for_slow_transactions', async () => { - const { - durationPercentile, - fieldNames, - setup, - maxLatency, - distributionInterval, - } = options; - const { apmEventClient } = setup; - const filters = getCorrelationsFilters(options); - const durationForPercentile = await getDurationForPercentile({ - durationPercentile, - filters, - setup, - }); - - if (!durationForPercentile) { - return { significantTerms: [] }; - } - - const params = { - apm: { events: [ProcessorEvent.transaction] }, - body: { - size: 0, - query: { - bool: { - // foreground filters - filter: filters, - must: { - function_score: { - query: { - range: { - [TRANSACTION_DURATION]: { gte: durationForPercentile }, - }, - }, - script_score: { - script: { - source: `Math.log(2 + doc['${TRANSACTION_DURATION}'].value)`, - }, - }, - }, - }, - }, - }, - aggs: fieldNames.reduce((acc, fieldName) => { - return { - ...acc, - [fieldName]: { - significant_terms: { - size: 10, - field: fieldName, - background_filter: { - bool: { - filter: [ - ...filters, - { - range: { - [TRANSACTION_DURATION]: { - lt: durationForPercentile, - }, - }, - }, - ], - }, - }, - }, - }, - }; - }, {} as Record), - }, - }; - - const response = await apmEventClient.search( - 'get_significant_terms', - params - ); - - if (!response.aggregations) { - return { significantTerms: [] }; - } - - const topSigTerms = processSignificantTermAggs({ - sigTermAggs: response.aggregations, - }); - - const significantTerms = await getLatencyDistribution({ - setup, - filters, - topSigTerms, - maxLatency, - distributionInterval, - }); - - return { significantTerms }; - }); -} diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_duration_for_percentile.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_duration_for_percentile.ts deleted file mode 100644 index e7346d15f5aae..0000000000000 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_duration_for_percentile.ts +++ /dev/null @@ -1,45 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; -import { TRANSACTION_DURATION } from '../../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../helpers/setup_request'; - -export async function getDurationForPercentile({ - durationPercentile, - filters, - setup, -}: { - durationPercentile: number; - filters: ESFilter[]; - setup: Setup; -}) { - const { apmEventClient } = setup; - const res = await apmEventClient.search('get_duration_for_percentiles', { - apm: { - events: [ProcessorEvent.transaction], - }, - body: { - size: 0, - query: { - bool: { filter: filters }, - }, - aggs: { - percentile: { - percentiles: { - field: TRANSACTION_DURATION, - percents: [durationPercentile], - }, - }, - }, - }, - }); - - const duration = Object.values(res.aggregations?.percentile.values || {})[0]; - return duration || 0; -} diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_latency_distribution.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_latency_distribution.ts deleted file mode 100644 index 14ba7ecd4a0b9..0000000000000 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_latency_distribution.ts +++ /dev/null @@ -1,98 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { AggregationOptionsByType } from '../../../../../../../src/core/types/elasticsearch'; -import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; -import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../helpers/setup_request'; -import { TopSigTerm } from '../process_significant_term_aggs'; - -import { - getDistributionAggregation, - trimBuckets, -} from './get_overall_latency_distribution'; - -export async function getLatencyDistribution({ - setup, - filters, - topSigTerms, - maxLatency, - distributionInterval, -}: { - setup: Setup; - filters: ESFilter[]; - topSigTerms: TopSigTerm[]; - maxLatency: number; - distributionInterval: number; -}) { - const { apmEventClient } = setup; - - const distributionAgg = getDistributionAggregation( - maxLatency, - distributionInterval - ); - - const perTermAggs = topSigTerms.reduce( - (acc, term, index) => { - acc[`term_${index}`] = { - filter: { term: { [term.fieldName]: term.fieldValue } }, - aggs: { - distribution: distributionAgg, - }, - }; - return acc; - }, - {} as Record< - string, - { - filter: AggregationOptionsByType['filter']; - aggs: { - distribution: typeof distributionAgg; - }; - } - > - ); - - const params = { - // TODO: add support for metrics - apm: { events: [ProcessorEvent.transaction] }, - body: { - size: 0, - query: { bool: { filter: filters } }, - aggs: perTermAggs, - }, - }; - - const response = await apmEventClient.search( - 'get_latency_distribution', - params - ); - - type Agg = NonNullable; - - if (!response.aggregations) { - return []; - } - - return topSigTerms.map((topSig, index) => { - // ignore the typescript error since existence of response.aggregations is already checked: - // @ts-expect-error - const agg = response.aggregations[`term_${index}`] as Agg[string]; - const total = agg.distribution.doc_count; - const buckets = trimBuckets( - agg.distribution.dist_filtered_by_latency.buckets - ); - - return { - ...topSig, - distribution: buckets.map((bucket) => ({ - x: bucket.key, - y: (bucket.doc_count / total) * 100, - })), - }; - }); -} diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_max_latency.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_max_latency.ts deleted file mode 100644 index 8838b5ff7a862..0000000000000 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_max_latency.ts +++ /dev/null @@ -1,58 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; -import { TRANSACTION_DURATION } from '../../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../helpers/setup_request'; -import { TopSigTerm } from '../process_significant_term_aggs'; - -export async function getMaxLatency({ - setup, - filters, - topSigTerms = [], -}: { - setup: Setup; - filters: ESFilter[]; - topSigTerms?: TopSigTerm[]; -}) { - const { apmEventClient } = setup; - - const params = { - // TODO: add support for metrics - apm: { events: [ProcessorEvent.transaction] }, - body: { - size: 0, - query: { - bool: { - filter: filters, - - ...(topSigTerms.length - ? { - // only include docs containing the significant terms - should: topSigTerms.map((term) => ({ - term: { [term.fieldName]: term.fieldValue }, - })), - minimum_should_match: 1, - } - : null), - }, - }, - aggs: { - // TODO: add support for metrics - // max_latency: { max: { field: TRANSACTION_DURATION } }, - max_latency: { - percentiles: { field: TRANSACTION_DURATION, percents: [99] }, - }, - }, - }, - }; - - const response = await apmEventClient.search('get_max_latency', params); - // return response.aggregations?.max_latency.value; - return Object.values(response.aggregations?.max_latency.values ?? {})[0]; -} diff --git a/x-pack/plugins/apm/server/lib/correlations/latency/get_overall_latency_distribution.ts b/x-pack/plugins/apm/server/lib/correlations/latency/get_overall_latency_distribution.ts deleted file mode 100644 index cab1496849d8c..0000000000000 --- a/x-pack/plugins/apm/server/lib/correlations/latency/get_overall_latency_distribution.ts +++ /dev/null @@ -1,110 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { dropRightWhile } from 'lodash'; -import { TRANSACTION_DURATION } from '../../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../../common/processor_event'; -import { getMaxLatency } from './get_max_latency'; -import { withApmSpan } from '../../../utils/with_apm_span'; -import { CorrelationsOptions, getCorrelationsFilters } from '../get_filters'; -import { Setup } from '../../helpers/setup_request'; - -export const INTERVAL_BUCKETS = 15; -interface Options extends CorrelationsOptions { - setup: Setup; -} - -export function getDistributionAggregation( - maxLatency: number, - distributionInterval: number -) { - return { - filter: { range: { [TRANSACTION_DURATION]: { lte: maxLatency } } }, - aggs: { - dist_filtered_by_latency: { - histogram: { - // TODO: add support for metrics - field: TRANSACTION_DURATION, - interval: distributionInterval, - min_doc_count: 0, - extended_bounds: { - min: 0, - max: maxLatency, - }, - }, - }, - }, - }; -} - -export async function getOverallLatencyDistribution(options: Options) { - const { setup } = options; - const filters = getCorrelationsFilters(options); - - return withApmSpan('get_overall_latency_distribution', async () => { - const { apmEventClient } = setup; - const maxLatency = await getMaxLatency({ setup, filters }); - if (!maxLatency) { - return { - maxLatency: null, - distributionInterval: null, - overallDistribution: null, - }; - } - const distributionInterval = Math.floor(maxLatency / INTERVAL_BUCKETS); - - const params = { - // TODO: add support for metrics - apm: { events: [ProcessorEvent.transaction] }, - body: { - size: 0, - query: { bool: { filter: filters } }, - aggs: { - // overall distribution agg - distribution: getDistributionAggregation( - maxLatency, - distributionInterval - ), - }, - }, - }; - - const response = await apmEventClient.search( - 'get_terms_distribution', - params - ); - - if (!response.aggregations) { - return { - maxLatency, - distributionInterval, - overallDistribution: null, - }; - } - - const { distribution } = response.aggregations; - const total = distribution.doc_count; - const buckets = trimBuckets(distribution.dist_filtered_by_latency.buckets); - - return { - maxLatency, - distributionInterval, - overallDistribution: buckets.map((bucket) => ({ - x: bucket.key, - y: (bucket.doc_count / total) * 100, - })), - }; - }); -} - -// remove trailing buckets that are empty and out of bounds of the desired number of buckets -export function trimBuckets(buckets: T[]) { - return dropRightWhile( - buckets, - (bucket, index) => bucket.doc_count === 0 && index > INTERVAL_BUCKETS - 1 - ); -} diff --git a/x-pack/plugins/apm/server/lib/correlations/process_significant_term_aggs.ts b/x-pack/plugins/apm/server/lib/correlations/process_significant_term_aggs.ts deleted file mode 100644 index ecb751cad5a3f..0000000000000 --- a/x-pack/plugins/apm/server/lib/correlations/process_significant_term_aggs.ts +++ /dev/null @@ -1,80 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { orderBy } from 'lodash'; -import { - AggregationOptionsByType, - AggregationResultOf, -} from '../../../../../../src/core/types/elasticsearch'; - -export interface TopSigTerm { - fieldName: string; - fieldValue: string | number; - score: number; - impact: number; - fieldCount: number; - valueCount: number; -} - -type SigTermAgg = AggregationResultOf< - { significant_terms: AggregationOptionsByType['significant_terms'] }, - {} ->; - -function getMaxImpactScore(scores: number[]) { - if (scores.length === 0) { - return 0; - } - - const sortedScores = scores.sort((a, b) => b - a); - const maxScore = sortedScores[0]; - - // calculate median - const halfSize = scores.length / 2; - const medianIndex = Math.floor(halfSize); - const medianScore = - medianIndex < halfSize - ? sortedScores[medianIndex] - : (sortedScores[medianIndex - 1] + sortedScores[medianIndex]) / 2; - - return Math.max(maxScore, medianScore * 2); -} - -export function processSignificantTermAggs({ - sigTermAggs, -}: { - sigTermAggs: Record; -}) { - const significantTerms = Object.entries(sigTermAggs) - // filter entries with buckets, i.e. Significant terms aggs - .filter((entry): entry is [string, SigTermAgg] => { - const [, agg] = entry; - return 'buckets' in agg; - }) - .flatMap(([fieldName, agg]) => { - return agg.buckets.map((bucket) => ({ - fieldName, - fieldValue: bucket.key, - fieldCount: agg.doc_count, - valueCount: bucket.doc_count, - score: bucket.score, - })); - }); - - const maxImpactScore = getMaxImpactScore( - significantTerms.map(({ score }) => score) - ); - - // get top 10 terms ordered by score - const topSigTerms = orderBy(significantTerms, 'score', 'desc') - .map((significantTerm) => ({ - ...significantTerm, - impact: significantTerm.score / maxImpactScore, - })) - .slice(0, 10); - return topSigTerms; -} diff --git a/x-pack/plugins/apm/server/lib/correlations/get_filters.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/get_filters.ts similarity index 78% rename from x-pack/plugins/apm/server/lib/correlations/get_filters.ts rename to x-pack/plugins/apm/server/lib/search_strategies/queries/get_filters.ts index e735c79aa0cde..8537a367b99eb 100644 --- a/x-pack/plugins/apm/server/lib/correlations/get_filters.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/get_filters.ts @@ -5,16 +5,16 @@ * 2.0. */ -import { ESFilter } from '../../../../../../src/core/types/elasticsearch'; -import { rangeQuery, kqlQuery } from '../../../../observability/server'; -import { environmentQuery } from '../../../common/utils/environment_query'; +import { ESFilter } from '../../../../../../../src/core/types/elasticsearch'; +import { rangeQuery, kqlQuery } from '../../../../../observability/server'; +import { environmentQuery } from '../../../../common/utils/environment_query'; import { SERVICE_NAME, TRANSACTION_NAME, TRANSACTION_TYPE, PROCESSOR_EVENT, -} from '../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../common/processor_event'; +} from '../../../../common/elasticsearch_fieldnames'; +import { ProcessorEvent } from '../../../../common/processor_event'; export interface CorrelationsOptions { environment: string; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/get_query_with_params.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/get_query_with_params.ts index d544bbc9e00f5..f00c89503f103 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/get_query_with_params.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/get_query_with_params.ts @@ -15,7 +15,7 @@ import type { SearchStrategyParams, } from '../../../../common/search_strategies/types'; import { rangeRt } from '../../../routes/default_api_types'; -import { getCorrelationsFilters } from '../../correlations/get_filters'; +import { getCorrelationsFilters } from './get_filters'; export const getTermsQuery = ({ fieldName, fieldValue }: FieldValuePair) => { return { term: { [fieldName]: fieldValue } }; From 4b89e148843d1b27165c58f68512c222df4239e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= Date: Sat, 2 Oct 2021 17:38:40 +0200 Subject: [PATCH 20/98] Bump eslint@7 (#94347) --- .eslintrc.js | 6 +- package.json | 44 +- .../javascript.js | 8 +- .../src/byte_size_value/index.ts | 2 +- .../kbn-config-schema/src/duration/index.ts | 2 +- packages/kbn-eslint-plugin-eslint/BUILD.bazel | 2 +- .../rules/disallow_license_headers.js | 4 +- .../rules/disallow_license_headers.test.js | 3 +- .../rules/module_migration.test.js | 9 +- .../rules/no_restricted_paths.test.js | 3 +- .../rules/require_license_header.js | 4 +- .../rules/require_license_header.test.js | 3 +- packages/kbn-pm/dist/index.js | 351 ++--- .../lib/snapshots/decorate_snapshot_ui.ts | 1 - src/dev/eslint/lint_files.ts | 10 +- src/dev/license_checker/config.ts | 7 +- .../actions/server/usage/actions_telemetry.ts | 2 +- .../plugins/alerting/common/parse_duration.ts | 2 +- .../alerting/server/usage/alerts_telemetry.ts | 4 +- .../RumDashboard/Charts/PageLoadDistChart.tsx | 1 - .../MaybeViewTraceLink.tsx | 6 +- .../lib/aeroelastic/layout_functions.js | 9 - .../helpers/http_requests.js | 4 +- .../guidance_panel/guidance_panel.tsx | 1 + .../packs/common/pack_queries_table.tsx | 2 +- .../packs/list/pack_table_queries_table.tsx | 1 - .../osquery/public/results/results_table.tsx | 1 + .../shared_components/lazy_osquery_action.tsx | 1 + .../components/charts/barchart.test.tsx | 1 - .../charts/draggable_legend.test.tsx | 1 - .../charts/draggable_legend_item.test.tsx | 1 - .../drag_and_drop/draggable_wrapper.test.tsx | 1 - .../drag_and_drop/draggable_wrapper.tsx | 2 - .../components/event_details/columns.tsx | 2 - .../event_fields_browser.test.tsx | 1 - .../events_viewer/events_viewer.tsx | 1 - .../common/components/events_viewer/index.tsx | 1 - .../plugins/timeline/processor.tsx | 12 +- .../components/markdown_editor/renderer.tsx | 3 + .../matrix_histogram/index.test.tsx | 2 - .../components/ml/entity_draggable.test.tsx | 1 - .../get_anomalies_host_table_columns.tsx | 2 - .../get_anomalies_network_table_columns.tsx | 2 - .../ml_popover/jobs_table/jobs_table.tsx | 2 - .../components/stat_items/index.test.tsx | 2 - .../containers/sourcerer/index.test.tsx | 2 - .../public/common/utils/route/spy_routes.tsx | 2 + .../rules/step_about_rule/index.test.tsx | 2 +- .../table_helpers.tsx | 2 - .../detection_engine/rules/all/columns.tsx | 2 - .../rules/all/exceptions/columns.tsx | 2 - .../rules/details/failure_history.tsx | 2 - .../authentications_table/index.tsx | 2 - .../uncommon_process_table/index.test.tsx | 1 - .../uncommon_process_table/index.tsx | 2 - .../pages/endpoint_hosts/view/index.tsx | 6 - .../network/components/ip/index.test.tsx | 1 - .../components/network_http_table/columns.tsx | 2 - .../network/components/port/index.test.tsx | 1 - .../source_destination/index.test.tsx | 1 - .../network/components/tls_table/columns.tsx | 2 - .../network/pages/details/index.test.tsx | 1 - .../threat_intel_panel_view.tsx | 1 - .../field_renderers/field_renderers.test.tsx | 1 - .../components/flyout/index.test.tsx | 1 - .../components/formatted_ip/index.test.tsx | 1 - .../components/netflow/index.test.tsx | 1 - .../components/open_timeline/index.test.tsx | 2 - .../timelines_table/common_columns.tsx | 2 - .../timelines_table/extended_columns.tsx | 2 - .../timelines_table/icon_header_columns.tsx | 2 - .../body/events/event_column_view.test.tsx | 1 - .../timeline/body/renderers/args.test.tsx | 1 - .../renderers/auditd/generic_details.test.tsx | 1 - .../auditd/generic_file_details.test.tsx | 1 - .../auditd/generic_row_renderer.test.tsx | 1 - .../renderers/auditd/generic_row_renderer.tsx | 2 - .../primary_secondary_user_info.test.tsx | 1 - .../session_user_host_working_dir.test.tsx | 1 - .../dns/dns_request_event_details.test.tsx | 1 - .../dns_request_event_details_line.test.tsx | 1 - .../body/renderers/empty_column_renderer.tsx | 2 - .../endgame_security_event_details.test.tsx | 1 - ...dgame_security_event_details_line.test.tsx | 1 - .../renderers/exit_code_draggable.test.tsx | 1 - .../body/renderers/file_draggable.test.tsx | 1 - .../body/renderers/file_hash.test.tsx | 1 - .../body/renderers/formatted_field.test.tsx | 1 - .../renderers/get_column_renderer.test.tsx | 1 - .../body/renderers/get_row_renderer.test.tsx | 1 - .../body/renderers/host_name.test.tsx | 1 - .../body/renderers/host_working_dir.test.tsx | 1 - .../netflow/netflow_row_renderer.tsx | 2 - .../parent_process_draggable.test.tsx | 1 - .../renderers/plain_column_renderer.test.tsx | 1 - .../body/renderers/process_draggable.test.tsx | 1 - .../body/renderers/process_hash.test.tsx | 1 - .../renderers/reason_column_renderer.test.tsx | 1 - .../registry/registry_event_details.test.tsx | 3 - .../registry/registry_event_details.tsx | 2 - .../registry_event_details_line.test.tsx | 1 - .../suricata/suricata_details.test.tsx | 1 - .../suricata/suricata_row_renderer.test.tsx | 1 - .../suricata/suricata_row_renderer.tsx | 2 - .../suricata/suricata_signature.test.tsx | 1 - .../renderers/system/generic_details.test.tsx | 1 - .../system/generic_file_details.test.tsx | 1 - .../system/generic_row_renderer.test.tsx | 1 - .../renderers/system/generic_row_renderer.tsx | 5 +- .../body/renderers/system/package.test.tsx | 1 - .../renderers/user_host_working_dir.test.tsx | 1 - .../body/renderers/zeek/zeek_details.test.tsx | 1 - .../renderers/zeek/zeek_row_renderer.test.tsx | 1 - .../body/renderers/zeek/zeek_row_renderer.tsx | 2 - .../renderers/zeek/zeek_signature.test.tsx | 1 - .../timeline/eql_tab_content/index.test.tsx | 1 - .../timelines/components/timeline/index.tsx | 3 +- .../pinned_tab_content/index.test.tsx | 1 - .../timeline/query_tab_content/index.test.tsx | 1 - .../timeline/tabs_content/index.tsx | 1 - .../public/components/t_grid/body/index.tsx | 2 - .../t_grid/event_rendered_view/index.tsx | 4 - .../alert_status_bulk_actions.tsx | 1 - .../t_grid/toolbar/bulk_actions/index.tsx | 1 - .../fields_browser/category_columns.tsx | 2 - .../public/mock/kibana_react.mock.ts | 1 + .../public/mock/mock_hover_actions.tsx | 1 - .../timelines/public/mock/plugin_mock.tsx | 6 - yarn.lock | 1218 ++++++++--------- 129 files changed, 843 insertions(+), 1032 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index c78a9f4aca2ac..7e865cd99a6d3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -492,6 +492,7 @@ module.exports = { { files: [ '**/*.stories.tsx', + '**/*.test.js', 'x-pack/test/apm_api_integration/**/*.ts', 'x-pack/test/functional/apps/**/*.js', 'x-pack/plugins/apm/**/*.js', @@ -506,6 +507,7 @@ module.exports = { ], rules: { 'import/no-default-export': 'off', + 'import/no-named-as-default-member': 'off', 'import/no-named-as-default': 'off', }, }, @@ -1547,8 +1549,8 @@ module.exports = { plugins: ['react', '@typescript-eslint'], files: ['x-pack/plugins/osquery/**/*.{js,mjs,ts,tsx}'], rules: { - 'arrow-body-style': ['error', 'as-needed'], - 'prefer-arrow-callback': 'error', + // 'arrow-body-style': ['error', 'as-needed'], + // 'prefer-arrow-callback': 'error', 'no-unused-vars': 'off', 'react/prop-types': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', diff --git a/package.json b/package.json index 967fe03934cff..c12e5ca9f060e 100644 --- a/package.json +++ b/package.json @@ -417,6 +417,8 @@ "devDependencies": { "@babel/cli": "^7.15.7", "@babel/core": "^7.15.5", + "@babel/eslint-parser": "^7.15.7", + "@babel/eslint-plugin": "^7.14.5", "@babel/generator": "^7.15.4", "@babel/parser": "^7.15.7", "@babel/plugin-proposal-class-properties": "^7.14.5", @@ -518,7 +520,7 @@ "@types/ejs": "^3.0.6", "@types/elasticsearch": "^5.0.33", "@types/enzyme": "^3.10.8", - "@types/eslint": "^6.1.3", + "@types/eslint": "^7.28.0", "@types/extract-zip": "^1.6.2", "@types/faker": "^5.1.5", "@types/fancy-log": "^1.3.1", @@ -640,9 +642,9 @@ "@types/xml2js": "^0.4.5", "@types/yauzl": "^2.9.1", "@types/zen-observable": "^0.8.0", - "@typescript-eslint/eslint-plugin": "^4.14.1", - "@typescript-eslint/parser": "^4.14.1", - "@typescript-eslint/typescript-estree": "^4.14.1", + "@typescript-eslint/eslint-plugin": "^4.31.2", + "@typescript-eslint/parser": "^4.31.2", + "@typescript-eslint/typescript-estree": "^4.31.2", "@yarnpkg/lockfile": "^1.1.0", "abab": "^2.0.4", "aggregate-error": "^3.1.0", @@ -653,7 +655,6 @@ "argsplit": "^1.0.5", "autoprefixer": "^9.7.4", "axe-core": "^4.0.2", - "babel-eslint": "^10.1.0", "babel-jest": "^26.6.3", "babel-loader": "^8.2.2", "babel-plugin-add-module-exports": "^1.0.4", @@ -690,26 +691,25 @@ "enzyme-adapter-react-16": "^1.15.6", "enzyme-adapter-utils": "^1.14.0", "enzyme-to-json": "^3.6.1", - "eslint": "^6.8.0", - "eslint-config-prettier": "^6.15.0", - "eslint-import-resolver-node": "0.3.2", - "eslint-import-resolver-webpack": "0.11.1", - "eslint-module-utils": "2.5.0", - "eslint-plugin-babel": "^5.3.1", - "eslint-plugin-ban": "^1.4.0", - "eslint-plugin-cypress": "^2.11.3", + "eslint": "^7.32.0", + "eslint-config-prettier": "^7.2.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-webpack": "^0.13.1", + "eslint-module-utils": "^2.6.2", + "eslint-plugin-ban": "^1.5.2", + "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-jest": "^24.3.4", - "eslint-plugin-jsx-a11y": "^6.2.3", - "eslint-plugin-mocha": "^6.2.2", - "eslint-plugin-no-unsanitized": "^3.0.2", - "eslint-plugin-node": "^11.0.0", + "eslint-plugin-import": "^2.24.2", + "eslint-plugin-jest": "^24.5.0", + "eslint-plugin-jsx-a11y": "^6.4.1", + "eslint-plugin-mocha": "^9.0.0", + "eslint-plugin-no-unsanitized": "^3.1.5", + "eslint-plugin-node": "^11.1.0", "eslint-plugin-prefer-object-spread": "^1.2.1", - "eslint-plugin-prettier": "^3.4.1", - "eslint-plugin-react": "^7.20.3", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-react": "^7.26.1", "eslint-plugin-react-hooks": "^4.2.0", - "eslint-plugin-react-perf": "^3.2.3", + "eslint-plugin-react-perf": "^3.3.0", "eslint-traverse": "^1.0.0", "expose-loader": "^0.7.5", "faker": "^5.1.0", diff --git a/packages/elastic-eslint-config-kibana/javascript.js b/packages/elastic-eslint-config-kibana/javascript.js index cd69b1ccb8226..095c973f75004 100644 --- a/packages/elastic-eslint-config-kibana/javascript.js +++ b/packages/elastic-eslint-config-kibana/javascript.js @@ -8,11 +8,11 @@ module.exports = { */ { files: ['**/*.js'], - parser: require.resolve('babel-eslint'), + parser: require.resolve('@babel/eslint-parser'), plugins: [ 'mocha', - 'babel', + '@babel', 'import', 'no-unsanitized', 'prefer-object-spread', @@ -36,6 +36,10 @@ module.exports = { parserOptions: { sourceType: 'module', ecmaVersion: 2018, + requireConfigFile: false, + babelOptions: { + presets: ['@kbn/babel-preset/node_preset'] + }, }, rules: { diff --git a/packages/kbn-config-schema/src/byte_size_value/index.ts b/packages/kbn-config-schema/src/byte_size_value/index.ts index b648b97ba68fe..fb90bd70ed5c6 100644 --- a/packages/kbn-config-schema/src/byte_size_value/index.ts +++ b/packages/kbn-config-schema/src/byte_size_value/index.ts @@ -34,7 +34,7 @@ export class ByteSizeValue { return new ByteSizeValue(number); } - const value = parseInt(match[1], 0); + const value = parseInt(match[1], 10); const unit = match[2]; return new ByteSizeValue(value * unitMultiplier[unit]); diff --git a/packages/kbn-config-schema/src/duration/index.ts b/packages/kbn-config-schema/src/duration/index.ts index 5364caed805fa..6a05a00c9e871 100644 --- a/packages/kbn-config-schema/src/duration/index.ts +++ b/packages/kbn-config-schema/src/duration/index.ts @@ -24,7 +24,7 @@ function stringToDuration(text: string) { return numberToDuration(number); } - const count = parseInt(result[1], 0); + const count = parseInt(result[1], 10); const unit = result[2] as DurationInputArg2; return momentDuration(count, unit); diff --git a/packages/kbn-eslint-plugin-eslint/BUILD.bazel b/packages/kbn-eslint-plugin-eslint/BUILD.bazel index 2677e88927ab3..5baab89d6f03d 100644 --- a/packages/kbn-eslint-plugin-eslint/BUILD.bazel +++ b/packages/kbn-eslint-plugin-eslint/BUILD.bazel @@ -29,7 +29,7 @@ NPM_MODULE_EXTRA_FILES = [ ] DEPS = [ - "@npm//babel-eslint", + "@npm//@babel/eslint-parser", "@npm//dedent", "@npm//eslint", "@npm//eslint-module-utils", diff --git a/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js b/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js index d7b63a4369310..997925a372da8 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js +++ b/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.js @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const babelEslint = require('babel-eslint'); +const babelEslint = require('@babel/eslint-parser'); const { assert, normalizeWhitespace, init } = require('../lib'); @@ -38,7 +38,7 @@ module.exports = { assert(!!licenses, '"licenses" option is required'); return licenses.map((license, i) => { - const parsed = babelEslint.parse(license); + const parsed = babelEslint.parse(license, { requireConfigFile: false }); assert( !parsed.body.length, diff --git a/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.test.js b/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.test.js index 48d4735de1f69..b98cc2597b0c5 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.test.js +++ b/packages/kbn-eslint-plugin-eslint/rules/disallow_license_headers.test.js @@ -11,9 +11,10 @@ const rule = require('./disallow_license_headers'); const dedent = require('dedent'); const ruleTester = new RuleTester({ - parser: require.resolve('babel-eslint'), + parser: require.resolve('@babel/eslint-parser'), parserOptions: { ecmaVersion: 2018, + requireConfigFile: false, }, }); diff --git a/packages/kbn-eslint-plugin-eslint/rules/module_migration.test.js b/packages/kbn-eslint-plugin-eslint/rules/module_migration.test.js index d89c8df213994..1ff65fc19a966 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/module_migration.test.js +++ b/packages/kbn-eslint-plugin-eslint/rules/module_migration.test.js @@ -11,9 +11,10 @@ const rule = require('./module_migration'); const dedent = require('dedent'); const ruleTester = new RuleTester({ - parser: require.resolve('babel-eslint'), + parser: require.resolve('@babel/eslint-parser'), parserOptions: { ecmaVersion: 2018, + requireConfigFile: false, }, }); @@ -69,6 +70,12 @@ ruleTester.run('@kbn/eslint/module-migration', rule, { message: 'Re-exported module "foo" should be "bar"', }, ], + output: dedent` + import 'bar' + require('bar/foo2') + export { foo } from 'bar' + export const foo2 = 'bar' + `, }, ], }); diff --git a/packages/kbn-eslint-plugin-eslint/rules/no_restricted_paths.test.js b/packages/kbn-eslint-plugin-eslint/rules/no_restricted_paths.test.js index 516ffc2b17bf7..fa04d54f94f72 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/no_restricted_paths.test.js +++ b/packages/kbn-eslint-plugin-eslint/rules/no_restricted_paths.test.js @@ -32,10 +32,11 @@ const { RuleTester } = require('eslint'); const rule = require('./no_restricted_paths'); const ruleTester = new RuleTester({ - parser: require.resolve('babel-eslint'), + parser: require.resolve('@babel/eslint-parser'), parserOptions: { sourceType: 'module', ecmaVersion: 2018, + requireConfigFile: false, }, }); diff --git a/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js b/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js index 50b78318ca713..3b4a6a29667c0 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js +++ b/packages/kbn-eslint-plugin-eslint/rules/require_license_header.js @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const babelEslint = require('babel-eslint'); +const babelEslint = require('@babel/eslint-parser'); const { assert, normalizeWhitespace, init } = require('../lib'); @@ -38,7 +38,7 @@ module.exports = { assert(!!license, '"license" option is required'); - const parsed = babelEslint.parse(license); + const parsed = babelEslint.parse(license, { requireConfigFile: false }); assert(!parsed.body.length, '"license" option must only include a single comment'); assert( parsed.comments.length === 1, diff --git a/packages/kbn-eslint-plugin-eslint/rules/require_license_header.test.js b/packages/kbn-eslint-plugin-eslint/rules/require_license_header.test.js index 827601e489f61..1f0dea8e369fb 100644 --- a/packages/kbn-eslint-plugin-eslint/rules/require_license_header.test.js +++ b/packages/kbn-eslint-plugin-eslint/rules/require_license_header.test.js @@ -11,9 +11,10 @@ const rule = require('./require_license_header'); const dedent = require('dedent'); const ruleTester = new RuleTester({ - parser: require.resolve('babel-eslint'), + parser: require.resolve('@babel/eslint-parser'), parserOptions: { ecmaVersion: 2018, + requireConfigFile: false, }, }); diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index d0afe0330fb8b..5bdc5047d84fe 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -37329,6 +37329,20 @@ var maybeRealpath = function maybeRealpath(realpath, x, opts, cb) { } }; +var defaultReadPackage = function defaultReadPackage(readFile, pkgfile, cb) { + readFile(pkgfile, function (readFileErr, body) { + if (readFileErr) cb(readFileErr); + else { + try { + var pkg = JSON.parse(body); + cb(null, pkg); + } catch (jsonErr) { + cb(null); + } + } + }); +}; + var getPackageCandidates = function getPackageCandidates(x, start, opts) { var dirs = nodeModulesPaths(start, opts, x); for (var i = 0; i < dirs.length; i++) { @@ -37357,6 +37371,13 @@ module.exports = function resolve(x, options, callback) { var isDirectory = opts.isDirectory || defaultIsDir; var readFile = opts.readFile || fs.readFile; var realpath = opts.realpath || defaultRealpath; + var readPackage = opts.readPackage || defaultReadPackage; + if (opts.readFile && opts.readPackage) { + var conflictErr = new TypeError('`readFile` and `readPackage` are mutually exclusive.'); + return process.nextTick(function () { + cb(conflictErr); + }); + } var packageIterator = opts.packageIterator; var extensions = opts.extensions || ['.js']; @@ -37484,9 +37505,10 @@ module.exports = function resolve(x, options, callback) { // on err, ex is false if (!ex) return loadpkg(path.dirname(dir), cb); - readFile(pkgfile, function (err, body) { + readPackage(readFile, pkgfile, function (err, pkgParam) { if (err) cb(err); - try { var pkg = JSON.parse(body); } catch (jsonErr) {} + + var pkg = pkgParam; if (pkg && opts.packageFilter) { pkg = opts.packageFilter(pkg, pkgfile); @@ -37512,11 +37534,10 @@ module.exports = function resolve(x, options, callback) { if (err) return cb(err); if (!ex) return loadAsFile(path.join(x, 'index'), fpkg, cb); - readFile(pkgfile, function (err, body) { + readPackage(readFile, pkgfile, function (err, pkgParam) { if (err) return cb(err); - try { - var pkg = JSON.parse(body); - } catch (jsonErr) {} + + var pkg = pkgParam; if (pkg && opts.packageFilter) { pkg = opts.packageFilter(pkg, pkgfile); @@ -37797,7 +37818,7 @@ function versionIncluded(nodeVersion, specifierValue) { } var current = typeof nodeVersion === 'undefined' - ? process.versions && process.versions.node && process.versions.node + ? process.versions && process.versions.node : nodeVersion; if (typeof current !== 'string') { @@ -37909,7 +37930,7 @@ module.exports = function bind(that) { /* 387 */ /***/ (function(module) { -module.exports = JSON.parse("{\"assert\":true,\"assert/strict\":\">= 15\",\"async_hooks\":\">= 8\",\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"child_process\":true,\"cluster\":true,\"console\":true,\"constants\":true,\"crypto\":true,\"_debug_agent\":\">= 1 && < 8\",\"_debugger\":\"< 8\",\"dgram\":true,\"diagnostics_channel\":\">= 15.1\",\"dns\":true,\"dns/promises\":\">= 15\",\"domain\":\">= 0.7.12\",\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":[\">= 10 && < 10.1\",\">= 14\"],\"_http_agent\":\">= 0.11.1\",\"_http_client\":\">= 0.11.1\",\"_http_common\":\">= 0.11.1\",\"_http_incoming\":\">= 0.11.1\",\"_http_outgoing\":\">= 0.11.1\",\"_http_server\":\">= 0.11.1\",\"http\":true,\"http2\":\">= 8.8\",\"https\":true,\"inspector\":\">= 8.0.0\",\"_linklist\":\"< 8\",\"module\":true,\"net\":true,\"node-inspect/lib/_inspect\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0 && < 12\",\"os\":true,\"path\":true,\"perf_hooks\":\">= 8.5\",\"process\":\">= 1\",\"punycode\":true,\"querystring\":true,\"readline\":true,\"repl\":true,\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"_stream_transform\":\">= 0.9.4\",\"_stream_wrap\":\">= 1.4.1\",\"_stream_passthrough\":\">= 0.9.4\",\"_stream_readable\":\">= 0.9.4\",\"_stream_writable\":\">= 0.9.4\",\"stream\":true,\"stream/promises\":\">= 15\",\"string_decoder\":true,\"sys\":[\">= 0.6 && < 0.7\",\">= 0.8\"],\"timers\":true,\"timers/promises\":\">= 15\",\"_tls_common\":\">= 0.11.13\",\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"tls\":true,\"trace_events\":\">= 10\",\"tty\":true,\"url\":true,\"util\":true,\"v8/tools/arguments\":\">= 10 && < 12\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8\":\">= 1\",\"vm\":true,\"wasi\":\">= 13.4 && < 13.5\",\"worker_threads\":\">= 11.7\",\"zlib\":true}"); +module.exports = JSON.parse("{\"assert\":true,\"node:assert\":[\">= 14.18 && < 15\",\">= 16\"],\"assert/strict\":\">= 15\",\"node:assert/strict\":\">= 16\",\"async_hooks\":\">= 8\",\"node:async_hooks\":[\">= 14.18 && < 15\",\">= 16\"],\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"node:buffer\":[\">= 14.18 && < 15\",\">= 16\"],\"child_process\":true,\"node:child_process\":[\">= 14.18 && < 15\",\">= 16\"],\"cluster\":true,\"node:cluster\":[\">= 14.18 && < 15\",\">= 16\"],\"console\":true,\"node:console\":[\">= 14.18 && < 15\",\">= 16\"],\"constants\":true,\"node:constants\":[\">= 14.18 && < 15\",\">= 16\"],\"crypto\":true,\"node:crypto\":[\">= 14.18 && < 15\",\">= 16\"],\"_debug_agent\":\">= 1 && < 8\",\"_debugger\":\"< 8\",\"dgram\":true,\"node:dgram\":[\">= 14.18 && < 15\",\">= 16\"],\"diagnostics_channel\":[\">= 14.17 && < 15\",\">= 15.1\"],\"node:diagnostics_channel\":[\">= 14.18 && < 15\",\">= 16\"],\"dns\":true,\"node:dns\":[\">= 14.18 && < 15\",\">= 16\"],\"dns/promises\":\">= 15\",\"node:dns/promises\":\">= 16\",\"domain\":\">= 0.7.12\",\"node:domain\":[\">= 14.18 && < 15\",\">= 16\"],\"events\":true,\"node:events\":[\">= 14.18 && < 15\",\">= 16\"],\"freelist\":\"< 6\",\"fs\":true,\"node:fs\":[\">= 14.18 && < 15\",\">= 16\"],\"fs/promises\":[\">= 10 && < 10.1\",\">= 14\"],\"node:fs/promises\":[\">= 14.18 && < 15\",\">= 16\"],\"_http_agent\":\">= 0.11.1\",\"node:_http_agent\":[\">= 14.18 && < 15\",\">= 16\"],\"_http_client\":\">= 0.11.1\",\"node:_http_client\":[\">= 14.18 && < 15\",\">= 16\"],\"_http_common\":\">= 0.11.1\",\"node:_http_common\":[\">= 14.18 && < 15\",\">= 16\"],\"_http_incoming\":\">= 0.11.1\",\"node:_http_incoming\":[\">= 14.18 && < 15\",\">= 16\"],\"_http_outgoing\":\">= 0.11.1\",\"node:_http_outgoing\":[\">= 14.18 && < 15\",\">= 16\"],\"_http_server\":\">= 0.11.1\",\"node:_http_server\":[\">= 14.18 && < 15\",\">= 16\"],\"http\":true,\"node:http\":[\">= 14.18 && < 15\",\">= 16\"],\"http2\":\">= 8.8\",\"node:http2\":[\">= 14.18 && < 15\",\">= 16\"],\"https\":true,\"node:https\":[\">= 14.18 && < 15\",\">= 16\"],\"inspector\":\">= 8\",\"node:inspector\":[\">= 14.18 && < 15\",\">= 16\"],\"_linklist\":\"< 8\",\"module\":true,\"node:module\":[\">= 14.18 && < 15\",\">= 16\"],\"net\":true,\"node:net\":[\">= 14.18 && < 15\",\">= 16\"],\"node-inspect/lib/_inspect\":\">= 7.6 && < 12\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6 && < 12\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6 && < 12\",\"os\":true,\"node:os\":[\">= 14.18 && < 15\",\">= 16\"],\"path\":true,\"node:path\":[\">= 14.18 && < 15\",\">= 16\"],\"path/posix\":\">= 15.3\",\"node:path/posix\":\">= 16\",\"path/win32\":\">= 15.3\",\"node:path/win32\":\">= 16\",\"perf_hooks\":\">= 8.5\",\"node:perf_hooks\":[\">= 14.18 && < 15\",\">= 16\"],\"process\":\">= 1\",\"node:process\":[\">= 14.18 && < 15\",\">= 16\"],\"punycode\":true,\"node:punycode\":[\">= 14.18 && < 15\",\">= 16\"],\"querystring\":true,\"node:querystring\":[\">= 14.18 && < 15\",\">= 16\"],\"readline\":true,\"node:readline\":[\">= 14.18 && < 15\",\">= 16\"],\"repl\":true,\"node:repl\":[\">= 14.18 && < 15\",\">= 16\"],\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"node:_stream_duplex\":[\">= 14.18 && < 15\",\">= 16\"],\"_stream_transform\":\">= 0.9.4\",\"node:_stream_transform\":[\">= 14.18 && < 15\",\">= 16\"],\"_stream_wrap\":\">= 1.4.1\",\"node:_stream_wrap\":[\">= 14.18 && < 15\",\">= 16\"],\"_stream_passthrough\":\">= 0.9.4\",\"node:_stream_passthrough\":[\">= 14.18 && < 15\",\">= 16\"],\"_stream_readable\":\">= 0.9.4\",\"node:_stream_readable\":[\">= 14.18 && < 15\",\">= 16\"],\"_stream_writable\":\">= 0.9.4\",\"node:_stream_writable\":[\">= 14.18 && < 15\",\">= 16\"],\"stream\":true,\"node:stream\":[\">= 14.18 && < 15\",\">= 16\"],\"stream/consumers\":\">= 16.7\",\"node:stream/consumers\":\">= 16.7\",\"stream/promises\":\">= 15\",\"node:stream/promises\":\">= 16\",\"stream/web\":\">= 16.5\",\"node:stream/web\":\">= 16.5\",\"string_decoder\":true,\"node:string_decoder\":[\">= 14.18 && < 15\",\">= 16\"],\"sys\":[\">= 0.6 && < 0.7\",\">= 0.8\"],\"node:sys\":[\">= 14.18 && < 15\",\">= 16\"],\"timers\":true,\"node:timers\":[\">= 14.18 && < 15\",\">= 16\"],\"timers/promises\":\">= 15\",\"node:timers/promises\":\">= 16\",\"_tls_common\":\">= 0.11.13\",\"node:_tls_common\":[\">= 14.18 && < 15\",\">= 16\"],\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"node:_tls_wrap\":[\">= 14.18 && < 15\",\">= 16\"],\"tls\":true,\"node:tls\":[\">= 14.18 && < 15\",\">= 16\"],\"trace_events\":\">= 10\",\"node:trace_events\":[\">= 14.18 && < 15\",\">= 16\"],\"tty\":true,\"node:tty\":[\">= 14.18 && < 15\",\">= 16\"],\"url\":true,\"node:url\":[\">= 14.18 && < 15\",\">= 16\"],\"util\":true,\"node:util\":[\">= 14.18 && < 15\",\">= 16\"],\"util/types\":\">= 15.3\",\"node:util/types\":\">= 16\",\"v8/tools/arguments\":\">= 10 && < 12\",\"v8/tools/codemap\":[\">= 4.4 && < 5\",\">= 5.2 && < 12\"],\"v8/tools/consarray\":[\">= 4.4 && < 5\",\">= 5.2 && < 12\"],\"v8/tools/csvparser\":[\">= 4.4 && < 5\",\">= 5.2 && < 12\"],\"v8/tools/logreader\":[\">= 4.4 && < 5\",\">= 5.2 && < 12\"],\"v8/tools/profile_view\":[\">= 4.4 && < 5\",\">= 5.2 && < 12\"],\"v8/tools/splaytree\":[\">= 4.4 && < 5\",\">= 5.2 && < 12\"],\"v8\":\">= 1\",\"node:v8\":[\">= 14.18 && < 15\",\">= 16\"],\"vm\":true,\"node:vm\":[\">= 14.18 && < 15\",\">= 16\"],\"wasi\":\">= 13.4 && < 13.5\",\"worker_threads\":\">= 11.7\",\"node:worker_threads\":[\">= 14.18 && < 15\",\">= 16\"],\"zlib\":true,\"node:zlib\":[\">= 14.18 && < 15\",\">= 16\"]}"); /***/ }), /* 388 */ @@ -37974,7 +37995,7 @@ module.exports = core; /* 389 */ /***/ (function(module) { -module.exports = JSON.parse("{\"assert\":true,\"assert/strict\":\">= 15\",\"async_hooks\":\">= 8\",\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"child_process\":true,\"cluster\":true,\"console\":true,\"constants\":true,\"crypto\":true,\"_debug_agent\":\">= 1 && < 8\",\"_debugger\":\"< 8\",\"dgram\":true,\"diagnostics_channel\":\">= 15.1\",\"dns\":true,\"dns/promises\":\">= 15\",\"domain\":\">= 0.7.12\",\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":[\">= 10 && < 10.1\",\">= 14\"],\"_http_agent\":\">= 0.11.1\",\"_http_client\":\">= 0.11.1\",\"_http_common\":\">= 0.11.1\",\"_http_incoming\":\">= 0.11.1\",\"_http_outgoing\":\">= 0.11.1\",\"_http_server\":\">= 0.11.1\",\"http\":true,\"http2\":\">= 8.8\",\"https\":true,\"inspector\":\">= 8.0.0\",\"_linklist\":\"< 8\",\"module\":true,\"net\":true,\"node-inspect/lib/_inspect\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0 && < 12\",\"os\":true,\"path\":true,\"perf_hooks\":\">= 8.5\",\"process\":\">= 1\",\"punycode\":true,\"querystring\":true,\"readline\":true,\"repl\":true,\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"_stream_transform\":\">= 0.9.4\",\"_stream_wrap\":\">= 1.4.1\",\"_stream_passthrough\":\">= 0.9.4\",\"_stream_readable\":\">= 0.9.4\",\"_stream_writable\":\">= 0.9.4\",\"stream\":true,\"stream/promises\":\">= 15\",\"string_decoder\":true,\"sys\":[\">= 0.6 && < 0.7\",\">= 0.8\"],\"timers\":true,\"timers/promises\":\">= 15\",\"_tls_common\":\">= 0.11.13\",\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"tls\":true,\"trace_events\":\">= 10\",\"tty\":true,\"url\":true,\"util\":true,\"v8/tools/arguments\":\">= 10 && < 12\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8\":\">= 1\",\"vm\":true,\"wasi\":\">= 13.4 && < 13.5\",\"worker_threads\":\">= 11.7\",\"zlib\":true}"); +module.exports = JSON.parse("{\"assert\":true,\"assert/strict\":\">= 15\",\"async_hooks\":\">= 8\",\"buffer_ieee754\":\"< 0.9.7\",\"buffer\":true,\"child_process\":true,\"cluster\":true,\"console\":true,\"constants\":true,\"crypto\":true,\"_debug_agent\":\">= 1 && < 8\",\"_debugger\":\"< 8\",\"dgram\":true,\"diagnostics_channel\":\">= 15.1\",\"dns\":true,\"dns/promises\":\">= 15\",\"domain\":\">= 0.7.12\",\"events\":true,\"freelist\":\"< 6\",\"fs\":true,\"fs/promises\":[\">= 10 && < 10.1\",\">= 14\"],\"_http_agent\":\">= 0.11.1\",\"_http_client\":\">= 0.11.1\",\"_http_common\":\">= 0.11.1\",\"_http_incoming\":\">= 0.11.1\",\"_http_outgoing\":\">= 0.11.1\",\"_http_server\":\">= 0.11.1\",\"http\":true,\"http2\":\">= 8.8\",\"https\":true,\"inspector\":\">= 8.0.0\",\"_linklist\":\"< 8\",\"module\":true,\"net\":true,\"node-inspect/lib/_inspect\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_client\":\">= 7.6.0 && < 12\",\"node-inspect/lib/internal/inspect_repl\":\">= 7.6.0 && < 12\",\"os\":true,\"path\":true,\"path/posix\":\">= 15.3\",\"path/win32\":\">= 15.3\",\"perf_hooks\":\">= 8.5\",\"process\":\">= 1\",\"punycode\":true,\"querystring\":true,\"readline\":true,\"repl\":true,\"smalloc\":\">= 0.11.5 && < 3\",\"_stream_duplex\":\">= 0.9.4\",\"_stream_transform\":\">= 0.9.4\",\"_stream_wrap\":\">= 1.4.1\",\"_stream_passthrough\":\">= 0.9.4\",\"_stream_readable\":\">= 0.9.4\",\"_stream_writable\":\">= 0.9.4\",\"stream\":true,\"stream/promises\":\">= 15\",\"string_decoder\":true,\"sys\":[\">= 0.6 && < 0.7\",\">= 0.8\"],\"timers\":true,\"timers/promises\":\">= 15\",\"_tls_common\":\">= 0.11.13\",\"_tls_legacy\":\">= 0.11.3 && < 10\",\"_tls_wrap\":\">= 0.11.3\",\"tls\":true,\"trace_events\":\">= 10\",\"tty\":true,\"url\":true,\"util\":true,\"util/types\":\">= 15.3\",\"v8/tools/arguments\":\">= 10 && < 12\",\"v8/tools/codemap\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/consarray\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/csvparser\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/logreader\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/profile_view\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8/tools/splaytree\":[\">= 4.4.0 && < 5\",\">= 5.2.0 && < 12\"],\"v8\":\">= 1\",\"vm\":true,\"wasi\":\">= 13.4 && < 13.5\",\"worker_threads\":\">= 11.7\",\"zlib\":true}"); /***/ }), /* 390 */ @@ -38038,6 +38059,14 @@ var maybeRealpathSync = function maybeRealpathSync(realpathSync, x, opts) { return x; }; +var defaultReadPackageSync = function defaultReadPackageSync(readFileSync, pkgfile) { + var body = readFileSync(pkgfile); + try { + var pkg = JSON.parse(body); + return pkg; + } catch (jsonErr) {} +}; + var getPackageCandidates = function getPackageCandidates(x, start, opts) { var dirs = nodeModulesPaths(start, opts, x); for (var i = 0; i < dirs.length; i++) { @@ -38056,6 +38085,10 @@ module.exports = function resolveSync(x, options) { var readFileSync = opts.readFileSync || fs.readFileSync; var isDirectory = opts.isDirectory || defaultIsDir; var realpathSync = opts.realpathSync || defaultRealpathSync; + var readPackageSync = opts.readPackageSync || defaultReadPackageSync; + if (opts.readFileSync && opts.readPackageSync) { + throw new TypeError('`readFileSync` and `readPackageSync` are mutually exclusive.'); + } var packageIterator = opts.packageIterator; var extensions = opts.extensions || ['.js']; @@ -38120,11 +38153,7 @@ module.exports = function resolveSync(x, options) { return loadpkg(path.dirname(dir)); } - var body = readFileSync(pkgfile); - - try { - var pkg = JSON.parse(body); - } catch (jsonErr) {} + var pkg = readPackageSync(readFileSync, pkgfile); if (pkg && opts.packageFilter) { // v2 will pass pkgfile @@ -38138,8 +38167,7 @@ module.exports = function resolveSync(x, options) { var pkgfile = path.join(maybeRealpathSync(realpathSync, x, opts), '/package.json'); if (isFile(pkgfile)) { try { - var body = readFileSync(pkgfile, 'UTF8'); - var pkg = JSON.parse(body); + var pkg = readPackageSync(readFileSync, pkgfile); } catch (e) {} if (pkg && opts.packageFilter) { @@ -61048,7 +61076,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(555); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildBazelProductionProjects"]; }); -/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(797); +/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(796); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__["buildNonBazelProductionProjects"]; }); /* @@ -61070,11 +61098,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return buildBazelProductionProjects; }); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(556); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(769); +/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(768); /* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(globby__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(797); +/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(796); /* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(413); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(231); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); @@ -61180,11 +61208,11 @@ const os = __webpack_require__(122); const pMap = __webpack_require__(557); const arrify = __webpack_require__(552); const globby = __webpack_require__(560); -const hasGlob = __webpack_require__(753); -const cpFile = __webpack_require__(755); -const junk = __webpack_require__(765); -const pFilter = __webpack_require__(766); -const CpyError = __webpack_require__(768); +const hasGlob = __webpack_require__(752); +const cpFile = __webpack_require__(754); +const junk = __webpack_require__(764); +const pFilter = __webpack_require__(765); +const CpyError = __webpack_require__(767); const defaultOptions = { ignoreJunk: true @@ -84420,8 +84448,8 @@ const fs = __webpack_require__(132); const path = __webpack_require__(4); const fastGlob = __webpack_require__(563); const gitIgnore = __webpack_require__(750); -const pify = __webpack_require__(751); -const slash = __webpack_require__(752); +const pify = __webpack_require__(404); +const slash = __webpack_require__(751); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -84993,81 +85021,6 @@ module.exports = options => new IgnoreBase(options) "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; -}; - - -/***/ }), -/* 752 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - module.exports = input => { const isExtendedLengthPath = /^\\\\\?\\/.test(input); const hasNonAscii = /[^\u0000-\u0080]+/.test(input); // eslint-disable-line no-control-regex @@ -85081,7 +85034,7 @@ module.exports = input => { /***/ }), -/* 753 */ +/* 752 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85094,7 +85047,7 @@ module.exports = input => { -var isGlob = __webpack_require__(754); +var isGlob = __webpack_require__(753); module.exports = function hasGlob(val) { if (val == null) return false; @@ -85114,7 +85067,7 @@ module.exports = function hasGlob(val) { /***/ }), -/* 754 */ +/* 753 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -85145,17 +85098,17 @@ module.exports = function isGlob(str) { /***/ }), -/* 755 */ +/* 754 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); const {constants: fsConstants} = __webpack_require__(132); -const pEvent = __webpack_require__(756); -const CpFileError = __webpack_require__(759); -const fs = __webpack_require__(761); -const ProgressEmitter = __webpack_require__(764); +const pEvent = __webpack_require__(755); +const CpFileError = __webpack_require__(758); +const fs = __webpack_require__(760); +const ProgressEmitter = __webpack_require__(763); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -85269,12 +85222,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 756 */ +/* 755 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(757); +const pTimeout = __webpack_require__(756); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -85565,12 +85518,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 757 */ +/* 756 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(758); +const pFinally = __webpack_require__(757); class TimeoutError extends Error { constructor(message) { @@ -85616,7 +85569,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 758 */ +/* 757 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85638,12 +85591,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 759 */ +/* 758 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(760); +const NestedError = __webpack_require__(759); class CpFileError extends NestedError { constructor(message, nested) { @@ -85657,7 +85610,7 @@ module.exports = CpFileError; /***/ }), -/* 760 */ +/* 759 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(113).inherits; @@ -85713,16 +85666,16 @@ module.exports = NestedError; /***/ }), -/* 761 */ +/* 760 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(113); const fs = __webpack_require__(233); -const makeDir = __webpack_require__(762); -const pEvent = __webpack_require__(756); -const CpFileError = __webpack_require__(759); +const makeDir = __webpack_require__(761); +const pEvent = __webpack_require__(755); +const CpFileError = __webpack_require__(758); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -85819,7 +85772,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 762 */ +/* 761 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85827,7 +85780,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(132); const path = __webpack_require__(4); const {promisify} = __webpack_require__(113); -const semver = __webpack_require__(763); +const semver = __webpack_require__(762); const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0'); @@ -85982,7 +85935,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 763 */ +/* 762 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -87584,7 +87537,7 @@ function coerce (version, options) { /***/ }), -/* 764 */ +/* 763 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87625,7 +87578,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 765 */ +/* 764 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87671,12 +87624,12 @@ exports.default = module.exports; /***/ }), -/* 766 */ +/* 765 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(767); +const pMap = __webpack_require__(766); const pFilter = async (iterable, filterer, options) => { const values = await pMap( @@ -87693,7 +87646,7 @@ module.exports.default = pFilter; /***/ }), -/* 767 */ +/* 766 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87772,12 +87725,12 @@ module.exports.default = pMap; /***/ }), -/* 768 */ +/* 767 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(760); +const NestedError = __webpack_require__(759); class CpyError extends NestedError { constructor(message, nested) { @@ -87791,7 +87744,7 @@ module.exports = CpyError; /***/ }), -/* 769 */ +/* 768 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87799,10 +87752,10 @@ module.exports = CpyError; const fs = __webpack_require__(132); const arrayUnion = __webpack_require__(242); const merge2 = __webpack_require__(243); -const fastGlob = __webpack_require__(770); +const fastGlob = __webpack_require__(769); const dirGlob = __webpack_require__(326); -const gitignore = __webpack_require__(795); -const {FilterStream, UniqueStream} = __webpack_require__(796); +const gitignore = __webpack_require__(794); +const {FilterStream, UniqueStream} = __webpack_require__(795); const DEFAULT_FILTER = () => false; @@ -87979,17 +87932,17 @@ module.exports.gitignore = gitignore; /***/ }), -/* 770 */ +/* 769 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const taskManager = __webpack_require__(771); -const async_1 = __webpack_require__(781); -const stream_1 = __webpack_require__(791); -const sync_1 = __webpack_require__(792); -const settings_1 = __webpack_require__(794); -const utils = __webpack_require__(772); +const taskManager = __webpack_require__(770); +const async_1 = __webpack_require__(780); +const stream_1 = __webpack_require__(790); +const sync_1 = __webpack_require__(791); +const settings_1 = __webpack_require__(793); +const utils = __webpack_require__(771); async function FastGlob(source, options) { assertPatternsInput(source); const works = getWorks(source, async_1.default, options); @@ -88053,14 +88006,14 @@ module.exports = FastGlob; /***/ }), -/* 771 */ +/* 770 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertPatternGroupToTask = exports.convertPatternGroupsToTasks = exports.groupPatternsByBaseDirectory = exports.getNegativePatternsAsPositive = exports.getPositivePatterns = exports.convertPatternsToTasks = exports.generate = void 0; -const utils = __webpack_require__(772); +const utils = __webpack_require__(771); function generate(patterns, settings) { const positivePatterns = getPositivePatterns(patterns); const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); @@ -88125,31 +88078,31 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 772 */ +/* 771 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.string = exports.stream = exports.pattern = exports.path = exports.fs = exports.errno = exports.array = void 0; -const array = __webpack_require__(773); +const array = __webpack_require__(772); exports.array = array; -const errno = __webpack_require__(774); +const errno = __webpack_require__(773); exports.errno = errno; -const fs = __webpack_require__(775); +const fs = __webpack_require__(774); exports.fs = fs; -const path = __webpack_require__(776); +const path = __webpack_require__(775); exports.path = path; -const pattern = __webpack_require__(777); +const pattern = __webpack_require__(776); exports.pattern = pattern; -const stream = __webpack_require__(779); +const stream = __webpack_require__(778); exports.stream = stream; -const string = __webpack_require__(780); +const string = __webpack_require__(779); exports.string = string; /***/ }), -/* 773 */ +/* 772 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88178,7 +88131,7 @@ exports.splitWhen = splitWhen; /***/ }), -/* 774 */ +/* 773 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88192,7 +88145,7 @@ exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 775 */ +/* 774 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88218,7 +88171,7 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 776 */ +/* 775 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88258,7 +88211,7 @@ exports.removeLeadingDotSegment = removeLeadingDotSegment; /***/ }), -/* 777 */ +/* 776 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88267,7 +88220,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = void 0; const path = __webpack_require__(4); const globParent = __webpack_require__(265); -const micromatch = __webpack_require__(778); +const micromatch = __webpack_require__(777); const picomatch = __webpack_require__(279); const GLOBSTAR = '**'; const ESCAPE_SYMBOL = '\\'; @@ -88397,7 +88350,7 @@ exports.matchAny = matchAny; /***/ }), -/* 778 */ +/* 777 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88871,7 +88824,7 @@ module.exports = micromatch; /***/ }), -/* 779 */ +/* 778 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88895,7 +88848,7 @@ function propagateCloseEventToSources(streams) { /***/ }), -/* 780 */ +/* 779 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88913,14 +88866,14 @@ exports.isEmpty = isEmpty; /***/ }), -/* 781 */ +/* 780 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(782); -const provider_1 = __webpack_require__(784); +const stream_1 = __webpack_require__(781); +const provider_1 = __webpack_require__(783); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -88948,7 +88901,7 @@ exports.default = ProviderAsync; /***/ }), -/* 782 */ +/* 781 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88957,7 +88910,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(173); const fsStat = __webpack_require__(289); const fsWalk = __webpack_require__(294); -const reader_1 = __webpack_require__(783); +const reader_1 = __webpack_require__(782); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -89010,7 +88963,7 @@ exports.default = ReaderStream; /***/ }), -/* 783 */ +/* 782 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89018,7 +88971,7 @@ exports.default = ReaderStream; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); const fsStat = __webpack_require__(289); -const utils = __webpack_require__(772); +const utils = __webpack_require__(771); class Reader { constructor(_settings) { this._settings = _settings; @@ -89050,17 +89003,17 @@ exports.default = Reader; /***/ }), -/* 784 */ +/* 783 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); -const deep_1 = __webpack_require__(785); -const entry_1 = __webpack_require__(788); -const error_1 = __webpack_require__(789); -const entry_2 = __webpack_require__(790); +const deep_1 = __webpack_require__(784); +const entry_1 = __webpack_require__(787); +const error_1 = __webpack_require__(788); +const entry_2 = __webpack_require__(789); class Provider { constructor(_settings) { this._settings = _settings; @@ -89105,14 +89058,14 @@ exports.default = Provider; /***/ }), -/* 785 */ +/* 784 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(772); -const partial_1 = __webpack_require__(786); +const utils = __webpack_require__(771); +const partial_1 = __webpack_require__(785); class DeepFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -89174,13 +89127,13 @@ exports.default = DeepFilter; /***/ }), -/* 786 */ +/* 785 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const matcher_1 = __webpack_require__(787); +const matcher_1 = __webpack_require__(786); class PartialMatcher extends matcher_1.default { match(filepath) { const parts = filepath.split('/'); @@ -89219,13 +89172,13 @@ exports.default = PartialMatcher; /***/ }), -/* 787 */ +/* 786 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(772); +const utils = __webpack_require__(771); class Matcher { constructor(_patterns, _settings, _micromatchOptions) { this._patterns = _patterns; @@ -89276,13 +89229,13 @@ exports.default = Matcher; /***/ }), -/* 788 */ +/* 787 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(772); +const utils = __webpack_require__(771); class EntryFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -89339,13 +89292,13 @@ exports.default = EntryFilter; /***/ }), -/* 789 */ +/* 788 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(772); +const utils = __webpack_require__(771); class ErrorFilter { constructor(_settings) { this._settings = _settings; @@ -89361,13 +89314,13 @@ exports.default = ErrorFilter; /***/ }), -/* 790 */ +/* 789 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(772); +const utils = __webpack_require__(771); class EntryTransformer { constructor(_settings) { this._settings = _settings; @@ -89394,15 +89347,15 @@ exports.default = EntryTransformer; /***/ }), -/* 791 */ +/* 790 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(173); -const stream_2 = __webpack_require__(782); -const provider_1 = __webpack_require__(784); +const stream_2 = __webpack_require__(781); +const provider_1 = __webpack_require__(783); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -89432,14 +89385,14 @@ exports.default = ProviderStream; /***/ }), -/* 792 */ +/* 791 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(793); -const provider_1 = __webpack_require__(784); +const sync_1 = __webpack_require__(792); +const provider_1 = __webpack_require__(783); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -89462,7 +89415,7 @@ exports.default = ProviderSync; /***/ }), -/* 793 */ +/* 792 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89470,7 +89423,7 @@ exports.default = ProviderSync; Object.defineProperty(exports, "__esModule", { value: true }); const fsStat = __webpack_require__(289); const fsWalk = __webpack_require__(294); -const reader_1 = __webpack_require__(783); +const reader_1 = __webpack_require__(782); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -89512,7 +89465,7 @@ exports.default = ReaderSync; /***/ }), -/* 794 */ +/* 793 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89576,7 +89529,7 @@ exports.default = Settings; /***/ }), -/* 795 */ +/* 794 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89584,7 +89537,7 @@ exports.default = Settings; const {promisify} = __webpack_require__(113); const fs = __webpack_require__(132); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(770); +const fastGlob = __webpack_require__(769); const gitIgnore = __webpack_require__(329); const slash = __webpack_require__(330); @@ -89703,7 +89656,7 @@ module.exports.sync = options => { /***/ }), -/* 796 */ +/* 795 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89756,7 +89709,7 @@ module.exports = { /***/ }), -/* 797 */ +/* 796 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.ts b/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.ts index 3e5746ea2a3be..02e96f62e2488 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.ts @@ -161,7 +161,6 @@ function getSnapshotState(file: string, updateSnapshot: SnapshotUpdateState) { path.join(dirname + `/__snapshots__/` + filename.replace(path.extname(filename), '.snap')), { updateSnapshot, - // @ts-expect-error getPrettier: () => prettier, getBabelTraverse: () => babelTraverse, } diff --git a/src/dev/eslint/lint_files.ts b/src/dev/eslint/lint_files.ts index b5849c0f8485f..77fe941fb7aeb 100644 --- a/src/dev/eslint/lint_files.ts +++ b/src/dev/eslint/lint_files.ts @@ -20,18 +20,13 @@ function lintFilesOnFS(cli: CLIEngine, files: File[]) { // For files living somewhere else (ie. git object) async function lintFilesOnContent(cli: CLIEngine, files: File[]) { - const report: { - results: any[]; - errorCount: number; - warningCount: number; - fixableErrorCount: number; - fixableWarningCount: number; - } = { + const report: CLIEngine.LintReport = { results: [], errorCount: 0, warningCount: 0, fixableErrorCount: 0, fixableWarningCount: 0, + usedDeprecatedRules: [], }; for (let i = 0; i < files.length; i++) { @@ -46,6 +41,7 @@ async function lintFilesOnContent(cli: CLIEngine, files: File[]) { report.warningCount += r.warningCount; report.fixableErrorCount += r.fixableErrorCount; report.fixableWarningCount += r.fixableWarningCount; + report.usedDeprecatedRules.push(...r.usedDeprecatedRules); } return report; diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index 132d2bfa82aa2..e4f1c6a2d2e01 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -76,10 +76,5 @@ export const LICENSE_OVERRIDES = { '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@7.15.0': ['Elastic License 2.0'], '@elastic/eui@38.0.1': ['SSPL-1.0 OR Elastic License 2.0'], - - // TODO can be removed if the https://github.com/jindw/xmldom/issues/239 is released - 'xmldom@0.1.27': ['MIT'], - - // TODO can be removed once we upgrade the use of walk dependency past or equal to v2.3.14 - 'walk@2.3.9': ['MIT'], + 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry }; diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index 76e038fb77e7f..544d6a411ccdc 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -78,7 +78,7 @@ export async function getTotalCount( } return { countTotal: - Object.keys(aggs).reduce((total: number, key: string) => parseInt(aggs[key], 0) + total, 0) + + Object.keys(aggs).reduce((total: number, key: string) => parseInt(aggs[key], 10) + total, 0) + (preconfiguredActions?.length ?? 0), countByType, }; diff --git a/x-pack/plugins/alerting/common/parse_duration.ts b/x-pack/plugins/alerting/common/parse_duration.ts index e88a2dbd742cb..3494a48fc8ab9 100644 --- a/x-pack/plugins/alerting/common/parse_duration.ts +++ b/x-pack/plugins/alerting/common/parse_duration.ts @@ -28,7 +28,7 @@ export function parseDuration(duration: string): number { } export function getDurationNumberInItsUnit(duration: string): number { - return parseInt(duration.replace(/[^0-9.]/g, ''), 0); + return parseInt(duration.replace(/[^0-9.]/g, ''), 10); } export function getDurationUnitValue(duration: string): string { diff --git a/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts b/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts index 46ac3e53895eb..7d8c1593f533d 100644 --- a/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts +++ b/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts @@ -259,7 +259,7 @@ export async function getTotalCountAggregations( const totalAlertsCount = Object.keys(aggregations.byAlertTypeId.value.types).reduce( (total: number, key: string) => - parseInt(aggregations.byAlertTypeId.value.types[key], 0) + total, + parseInt(aggregations.byAlertTypeId.value.types[key], 10) + total, 0 ); @@ -325,7 +325,7 @@ export async function getTotalCountInUse(esClient: ElasticsearchClient, kibanaIn return { countTotal: Object.keys(aggregations.byAlertTypeId.value.types).reduce( (total: number, key: string) => - parseInt(aggregations.byAlertTypeId.value.types[key], 0) + total, + parseInt(aggregations.byAlertTypeId.value.types[key], 10) + total, 0 ), countByType: Object.keys(aggregations.byAlertTypeId.value.types).reduce( diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/PageLoadDistChart.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/PageLoadDistChart.tsx index 589cce26b4d8c..4485dd8e33a10 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/PageLoadDistChart.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/Charts/PageLoadDistChart.tsx @@ -72,7 +72,6 @@ export function PageLoadDistChart({ onPercentileChange(minX, maxX); }; - // eslint-disable-next-line react/function-component-definition const headerFormatter: TooltipValueFormatter = (tooltip: TooltipValue) => { return (
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/MaybeViewTraceLink.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/MaybeViewTraceLink.tsx index c5828dea2c920..359dcdfda0a14 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/MaybeViewTraceLink.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/MaybeViewTraceLink.tsx @@ -15,7 +15,7 @@ import { TransactionDetailLink } from '../../../shared/Links/apm/transaction_det import { IWaterfall } from './waterfall_container/Waterfall/waterfall_helpers/waterfall_helpers'; import { Environment } from '../../../../../common/environment_rt'; -export const MaybeViewTraceLink = ({ +export function MaybeViewTraceLink({ transaction, waterfall, environment, @@ -23,7 +23,7 @@ export const MaybeViewTraceLink = ({ transaction: ITransaction; waterfall: IWaterfall; environment: Environment; -}) => { +}) { const { urlParams: { latencyAggregationType }, } = useUrlParams(); @@ -102,4 +102,4 @@ export const MaybeViewTraceLink = ({ ); } -}; +} diff --git a/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js b/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js index b4d33627d734a..dcee475557d98 100644 --- a/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js +++ b/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js @@ -580,15 +580,6 @@ export const applyLocalTransforms = (shapes, transformIntents) => { return shapes.map(shapeApplyLocalTransforms(transformIntents)); }; -// eslint-disable-next-line -const getUpstreamTransforms = (shapes, shape) => - shape.parent - ? getUpstreamTransforms( - shapes, - shapes.find((s) => s.id === shape.parent) - ).concat([shape.localTransformMatrix]) - : [shape.localTransformMatrix]; - const getUpstreams = (shapes, shape) => shape.parent ? getUpstreams( diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/http_requests.js b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/http_requests.js index 5c63e79374c73..5707f9fa5fdcd 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/http_requests.js +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/helpers/http_requests.js @@ -5,7 +5,7 @@ * 2.0. */ -import sinon from 'sinon'; +import { fakeServer } from 'sinon'; // Register helpers to mock HTTP Requests const registerHttpRequestMockHelpers = (server) => { @@ -124,7 +124,7 @@ const registerHttpRequestMockHelpers = (server) => { }; export const init = () => { - const server = sinon.fakeServer.create(); + const server = fakeServer.create(); server.respondImmediately = true; // We make requests to APIs which don't impact the UX, e.g. UI metric telemetry, diff --git a/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx index 7fa63404a4abd..2fe79a22fc764 100644 --- a/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx +++ b/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx @@ -50,6 +50,7 @@ function ListItem({ children: ReactNode; }) { return ( + // eslint-disable-next-line jsx-a11y/role-supports-aria-props
  • ( {query} diff --git a/x-pack/plugins/osquery/public/results/results_table.tsx b/x-pack/plugins/osquery/public/results/results_table.tsx index 0e683acf660a2..c59cd6281a364 100644 --- a/x-pack/plugins/osquery/public/results/results_table.tsx +++ b/x-pack/plugins/osquery/public/results/results_table.tsx @@ -120,6 +120,7 @@ const ResultsTableComponent: React.FC = ({ const renderCellValue: EuiDataGridProps['renderCellValue'] = useMemo( () => + // eslint-disable-next-line react/display-name ({ rowIndex, columnId }) => { // eslint-disable-next-line react-hooks/rules-of-hooks const data = useContext(DataContext); diff --git a/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx b/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx index 9cc55a65ce2bc..57f96c1f9bc03 100644 --- a/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx +++ b/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx @@ -8,6 +8,7 @@ import React, { lazy, Suspense } from 'react'; // @ts-expect-error update types +// eslint-disable-next-line react/display-name export const getLazyOsqueryAction = (services) => (props) => { const OsqueryAction = lazy(() => import('./osquery_action')); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/charts/barchart.test.tsx b/x-pack/plugins/security_solution/public/common/components/charts/barchart.test.tsx index ad15f0a5fa9fb..c24e41d096546 100644 --- a/x-pack/plugins/security_solution/public/common/components/charts/barchart.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/charts/barchart.test.tsx @@ -21,7 +21,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx b/x-pack/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx index 878a6de89747b..4dd6fa32db0ab 100644 --- a/x-pack/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/charts/draggable_legend.test.tsx @@ -21,7 +21,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/common/components/charts/draggable_legend_item.test.tsx b/x-pack/plugins/security_solution/public/common/components/charts/draggable_legend_item.test.tsx index de4d348bfb8f5..17b70a9903590 100644 --- a/x-pack/plugins/security_solution/public/common/components/charts/draggable_legend_item.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/charts/draggable_legend_item.test.tsx @@ -20,7 +20,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx index d27ad96ff3c4f..c5cf2b6ea3379 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx @@ -23,7 +23,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx index ddb9d17c40ead..ee62be0d88ae1 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx @@ -95,10 +95,8 @@ type RenderFunctionProp = ( interface Props { dataProvider: DataProvider; - disabled?: boolean; hideTopN?: boolean; isDraggable?: boolean; - inline?: boolean; render: RenderFunctionProp; timelineId?: string; truncate?: boolean; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx index b91978489f64e..dbb52ade2652c 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { EuiPanel, EuiText } from '@elastic/eui'; import { get } from 'lodash'; import memoizeOne from 'memoize-one'; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.test.tsx index 4c31db473ae32..a05a9e36a24e9 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.test.tsx @@ -22,7 +22,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx index d4cc68b12d786..632197aa6b219 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx @@ -121,7 +121,6 @@ interface Props { end: string; filters: Filter[]; headerFilterGroup?: React.ReactNode; - height?: number; id: TimelineId; indexNames: string[]; indexPattern: IIndexPattern; diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx index 768137c9d731d..d60db8a4bc461 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -37,7 +37,6 @@ const EMPTY_CONTROL_COLUMNS: ControlColumnProps[] = []; const leadingControlColumns: ControlColumnProps[] = [ { ...defaultControlColumn, - // eslint-disable-next-line react/display-name headerCellRender: () => <>{i18n.ACTIONS}, }, ]; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/processor.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/processor.tsx index 1546966c37cd8..f70f96a26c83a 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/processor.tsx +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/timeline/processor.tsx @@ -6,17 +6,17 @@ */ import React, { useCallback, memo } from 'react'; -import { EuiToolTip, EuiLink, EuiMarkdownAstNodePosition } from '@elastic/eui'; +import { EuiToolTip, EuiLink } from '@elastic/eui'; import { useTimelineClick } from '../../../../utils/timeline/use_timeline_click'; import { TimelineProps } from './types'; import * as i18n from './translations'; -export const TimelineMarkDownRendererComponent: React.FC< - TimelineProps & { - position: EuiMarkdownAstNodePosition; - } -> = ({ id, title, graphEventId }) => { +export const TimelineMarkDownRendererComponent: React.FC = ({ + id, + title, + graphEventId, +}) => { const handleTimelineClick = useTimelineClick(); const onClickTimeline = useCallback( () => handleTimelineClick(id ?? '', graphEventId), diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/renderer.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/renderer.tsx index 5fa84affe8f99..6c8f77a279a4a 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/renderer.tsx +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/renderer.tsx @@ -19,6 +19,7 @@ interface Props { const MarkdownRendererComponent: React.FC = ({ children, disableLinks }) => { const MarkdownLinkProcessingComponent: React.FC = useMemo( + // eslint-disable-next-line react/display-name () => (props) => , [disableLinks] ); @@ -38,4 +39,6 @@ const MarkdownRendererComponent: React.FC = ({ children, disableLinks }) ); }; +MarkdownRendererComponent.displayName = 'MarkdownRendererComponent'; + export const MarkdownRenderer = memo(MarkdownRendererComponent); diff --git a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx index 7c23faa433494..2260651287bd8 100644 --- a/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/matrix_histogram/index.test.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { mount, ReactWrapper } from 'enzyme'; import React from 'react'; diff --git a/x-pack/plugins/security_solution/public/common/components/ml/entity_draggable.test.tsx b/x-pack/plugins/security_solution/public/common/components/ml/entity_draggable.test.tsx index f08edb114b9a9..587d518bc11f0 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/entity_draggable.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/entity_draggable.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/common/components/ml/tables/get_anomalies_host_table_columns.tsx b/x-pack/plugins/security_solution/public/common/components/ml/tables/get_anomalies_host_table_columns.tsx index 197f88479347d..468cb416a2f9b 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/tables/get_anomalies_host_table_columns.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/tables/get_anomalies_host_table_columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { Columns } from '../../paginated_table'; diff --git a/x-pack/plugins/security_solution/public/common/components/ml/tables/get_anomalies_network_table_columns.tsx b/x-pack/plugins/security_solution/public/common/components/ml/tables/get_anomalies_network_table_columns.tsx index bc383ccefa453..4c4e131a9d467 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/tables/get_anomalies_network_table_columns.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/tables/get_anomalies_network_table_columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx index 3eb2d1eda1ead..5f39ddda2ca34 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React, { useEffect, useState } from 'react'; import { diff --git a/x-pack/plugins/security_solution/public/common/components/stat_items/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/stat_items/index.test.tsx index e2961de91c448..5f2c76632aba9 100644 --- a/x-pack/plugins/security_solution/public/common/components/stat_items/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/stat_items/index.test.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { mount, ReactWrapper } from 'enzyme'; import React from 'react'; import { ThemeProvider } from 'styled-components'; diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx index ae2e509a7d94e..ec28326f7d170 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import { act, renderHook } from '@testing-library/react-hooks'; import { Provider } from 'react-redux'; diff --git a/x-pack/plugins/security_solution/public/common/utils/route/spy_routes.tsx b/x-pack/plugins/security_solution/public/common/utils/route/spy_routes.tsx index 3f2d837530747..ab48ec0b6e006 100644 --- a/x-pack/plugins/security_solution/public/common/utils/route/spy_routes.tsx +++ b/x-pack/plugins/security_solution/public/common/utils/route/spy_routes.tsx @@ -99,4 +99,6 @@ export const SpyRouteComponent = memo< } ); +SpyRouteComponent.displayName = 'SpyRouteComponent'; + export const SpyRoute = withRouter(SpyRouteComponent); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx index 1793b31197f7d..2e4b866b3017b 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx @@ -35,7 +35,7 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name, @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any EuiFieldText: (props: any) => { const { isInvalid, isLoading, fullWidth, inputRef, isDisabled, ...validInputProps } = props; return ; diff --git a/x-pack/plugins/security_solution/public/detections/components/value_lists_management_modal/table_helpers.tsx b/x-pack/plugins/security_solution/public/detections/components/value_lists_management_modal/table_helpers.tsx index e7d726ed89e6f..223701a2f7f12 100644 --- a/x-pack/plugins/security_solution/public/detections/components/value_lists_management_modal/table_helpers.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/value_lists_management_modal/table_helpers.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import styled from 'styled-components'; import { EuiButtonIcon, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.tsx index c6145a70ec8d2..ad5a85a03464e 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { EuiBasicTableColumn, EuiTableActionsColumnType, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/columns.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/columns.tsx index 1ef3c3d3c5414..6d6fd974b20f5 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/columns.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import { EuiButtonIcon, EuiBasicTableColumn, EuiToolTip } from '@elastic/eui'; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/failure_history.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/failure_history.tsx index 2fedd6160af2c..a7db7ab57f6c2 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/failure_history.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/failure_history.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { EuiBasicTable, EuiPanel, diff --git a/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx index 453bb5c81dd58..b83853eec69a1 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { has } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; import { useDispatch } from 'react-redux'; diff --git a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.test.tsx b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.test.tsx index 2cd4ed1f57f84..29d3f110e8181 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.test.tsx @@ -26,7 +26,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx index 72dd7d7d88e8a..0541f2f1d403d 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React, { useCallback, useMemo } from 'react'; import { useDispatch } from 'react-redux'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index 4f211a7073a50..e71474321c868 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -301,7 +301,6 @@ export const EndpointList = () => { name: i18n.translate('xpack.securitySolution.endpoint.list.hostStatus', { defaultMessage: 'Agent status', }), - // eslint-disable-next-line react/display-name render: (hostStatus: HostInfo['host_status'], endpointInfo) => { return ( @@ -315,7 +314,6 @@ export const EndpointList = () => { defaultMessage: 'Policy', }), truncateText: true, - // eslint-disable-next-line react/display-name render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied'], item: HostInfo) => { return ( <> @@ -390,7 +388,6 @@ export const EndpointList = () => { name: i18n.translate('xpack.securitySolution.endpoint.list.os', { defaultMessage: 'OS', }), - // eslint-disable-next-line react/display-name render: (os: string) => { return ( @@ -407,7 +404,6 @@ export const EndpointList = () => { name: i18n.translate('xpack.securitySolution.endpoint.list.ip', { defaultMessage: 'IP address', }), - // eslint-disable-next-line react/display-name render: (ip: string[]) => { return ( { name: i18n.translate('xpack.securitySolution.endpoint.list.endpointVersion', { defaultMessage: 'Version', }), - // eslint-disable-next-line react/display-name render: (version: string) => { return ( @@ -462,7 +457,6 @@ export const EndpointList = () => { }), actions: [ { - // eslint-disable-next-line react/display-name render: (item: HostInfo) => { return ; }, diff --git a/x-pack/plugins/security_solution/public/network/components/ip/index.test.tsx b/x-pack/plugins/security_solution/public/network/components/ip/index.test.tsx index 63971ae508d5c..836d6885d1674 100644 --- a/x-pack/plugins/security_solution/public/network/components/ip/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/ip/index.test.tsx @@ -20,7 +20,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/network/components/network_http_table/columns.tsx b/x-pack/plugins/security_solution/public/network/components/network_http_table/columns.tsx index 8b5a7687e3f9d..9b8f842851064 100644 --- a/x-pack/plugins/security_solution/public/network/components/network_http_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/network/components/network_http_table/columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import numeral from '@elastic/numeral'; import { diff --git a/x-pack/plugins/security_solution/public/network/components/port/index.test.tsx b/x-pack/plugins/security_solution/public/network/components/port/index.test.tsx index fc48a022946d5..480d200c6756f 100644 --- a/x-pack/plugins/security_solution/public/network/components/port/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/port/index.test.tsx @@ -21,7 +21,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/network/components/source_destination/index.test.tsx b/x-pack/plugins/security_solution/public/network/components/source_destination/index.test.tsx index b59eb25cbfe25..3da5ec6d4b218 100644 --- a/x-pack/plugins/security_solution/public/network/components/source_destination/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/source_destination/index.test.tsx @@ -55,7 +55,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/network/components/tls_table/columns.tsx b/x-pack/plugins/security_solution/public/network/components/tls_table/columns.tsx index 6a2073ce3c542..7a45c418a4ff0 100644 --- a/x-pack/plugins/security_solution/public/network/components/tls_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/network/components/tls_table/columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import moment from 'moment'; diff --git a/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx b/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx index d9d5ac9241f19..612acdc813c92 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx @@ -27,7 +27,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx index ba4851600c4b4..0e968be1573de 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx @@ -34,7 +34,6 @@ const columns: Array> = [ field: 'path', truncateText: true, width: '80px', - // eslint-disable-next-line react/display-name render: (path: string) => , }, ]; diff --git a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx index e2194156ecf4d..9851f11d9adba 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx @@ -35,7 +35,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/index.test.tsx index fdfeba2a2c9c3..322a9eceb8d5c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/index.test.tsx @@ -34,7 +34,6 @@ jest.mock('react-redux', () => { }); jest.mock('../timeline', () => ({ - // eslint-disable-next-line react/display-name StatefulTimeline: () =>
    , })); diff --git a/x-pack/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx index 6a796c29523a1..7dc0a98461760 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/formatted_ip/index.test.tsx @@ -40,7 +40,6 @@ jest.mock('../../../common/components/drag_and_drop/draggable_wrapper', () => { const original = jest.requireActual('../../../common/components/drag_and_drop/draggable_wrapper'); return { ...original, - // eslint-disable-next-line react/display-name DraggableWrapper: () =>
    , }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/netflow/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/netflow/index.test.tsx index c73e372b4a71c..5392b382d6c82 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/netflow/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/netflow/index.test.tsx @@ -68,7 +68,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx index 92d602bb89e8f..d59b75fcfb506 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; import { mount } from 'enzyme'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/common_columns.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/common_columns.tsx index 21262d66fdbfe..9c85296b8f69d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/common_columns.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/common_columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { EuiButtonIcon, EuiLink } from '@elastic/eui'; import { omit } from 'lodash/fp'; import React from 'react'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/extended_columns.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/extended_columns.tsx index 0d326e8644645..4e2357dcbf7c7 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/extended_columns.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/extended_columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import { defaultToEmptyTag } from '../../../../common/components/empty_value'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/icon_header_columns.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/icon_header_columns.tsx index 103dbdcfd057f..6ad585ca207ec 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/icon_header_columns.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/icon_header_columns.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { EuiIcon, EuiToolTip } from '@elastic/eui'; import React from 'react'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx index 404127893b11c..b0ccbec6276db 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.test.tsx @@ -5,7 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ import { mount } from 'enzyme'; import React from 'react'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/args.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/args.test.tsx index d5ec8b6f94862..687880a2e60f4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/args.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/args.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_details.test.tsx index 2a5764e53756a..e3c82179b91e2 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_details.test.tsx @@ -21,7 +21,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_file_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_file_details.test.tsx index 009ffecf28f74..a4c5944f50623 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_file_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_file_details.test.tsx @@ -21,7 +21,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_row_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_row_renderer.test.tsx index 1f44feb3b394f..79836b0ac1e4e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_row_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_row_renderer.test.tsx @@ -26,7 +26,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_row_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_row_renderer.tsx index d0522e97157ab..8ac1a24c9d389 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_row_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/generic_row_renderer.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { IconType } from '@elastic/eui'; import { get } from 'lodash/fp'; import React from 'react'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/primary_secondary_user_info.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/primary_secondary_user_info.test.tsx index d6037a310dc7e..6aa2536e27a5a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/primary_secondary_user_info.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/primary_secondary_user_info.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/session_user_host_working_dir.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/session_user_host_working_dir.test.tsx index fa6eda6bce37d..5392cd1640122 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/session_user_host_working_dir.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/auditd/session_user_host_working_dir.test.tsx @@ -20,7 +20,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details.test.tsx index 9e6c5b819a20b..0cf90982c9c31 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details.test.tsx @@ -21,7 +21,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details_line.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details_line.test.tsx index 5c0aecf5fbbc7..39fe69c498d8b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details_line.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/dns/dns_request_event_details_line.test.tsx @@ -18,7 +18,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/empty_column_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/empty_column_renderer.tsx index db568726f1b20..a3a6618e7d07a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/empty_column_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/empty_column_renderer.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import React from 'react'; import { ColumnHeaderOptions } from '../../../../../../common'; import { TimelineNonEcsData } from '../../../../../../common/search_strategy/timeline'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details.test.tsx index 613d66505601a..438a98e85bb62 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details.test.tsx @@ -26,7 +26,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx index 879862d06b250..8da385e6273b0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/endgame/endgame_security_event_details_line.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx index 1bf8d1a4a4f51..ae6d033db12f4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/exit_code_draggable.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_draggable.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_draggable.test.tsx index cf3fce2c25c0b..404de863e26ad 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_draggable.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_draggable.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_hash.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_hash.test.tsx index 8ebd3ae8a67c2..e024d1ee9ccb6 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_hash.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/file_hash.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.test.tsx index 9d716f8325cbc..84000ec036c28 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.test.tsx @@ -21,7 +21,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/get_column_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/get_column_renderer.test.tsx index 852331aa021dd..93283e918d494 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/get_column_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/get_column_renderer.test.tsx @@ -27,7 +27,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/get_row_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/get_row_renderer.test.tsx index 6b76aba92678d..ed529b099c332 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/get_row_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/get_row_renderer.test.tsx @@ -26,7 +26,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx index de87c037d3ef7..1bbfc837ebd62 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx @@ -37,7 +37,6 @@ jest.mock('../../../../../common/lib/kibana/kibana_react', () => { }); jest.mock('../../../../../common/components/draggables', () => ({ - // eslint-disable-next-line react/display-name DefaultDraggable: () =>
    , })); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_working_dir.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_working_dir.test.tsx index d650710b25cad..837fe8aeab201 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_working_dir.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_working_dir.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/netflow_row_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/netflow_row_renderer.tsx index 272912b855af0..f38304e718675 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/netflow_row_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/netflow_row_renderer.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { get } from 'lodash/fp'; import React from 'react'; import styled from 'styled-components'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx index 7c28747cc84ef..2dc648049e81a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/parent_process_draggable.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/plain_column_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/plain_column_renderer.test.tsx index e970aaad026b1..722f95379257c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/plain_column_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/plain_column_renderer.test.tsx @@ -24,7 +24,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_draggable.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_draggable.test.tsx index 6509808fb0c9f..983330008d898 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_draggable.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_draggable.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_hash.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_hash.test.tsx index 7135f2a5fed6a..b41d60fe718b5 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_hash.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/process_hash.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/reason_column_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/reason_column_renderer.test.tsx index ee8a275279607..9d711b9593622 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/reason_column_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/reason_column_renderer.test.tsx @@ -61,7 +61,6 @@ const rowRenderers: RowRenderer[] = [ { id: RowRendererId.alerts, isInstance: (ecs) => ecs === validEcs, - // eslint-disable-next-line react/display-name renderRow: () => , }, ]; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/registry/registry_event_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/registry/registry_event_details.test.tsx index e5bb91c532505..a13cdb5e6cdc1 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/registry/registry_event_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/registry/registry_event_details.test.tsx @@ -7,7 +7,6 @@ import React from 'react'; -import { mockBrowserFields } from '../../../../../../common/containers/source/mock'; import { mockEndpointRegistryModificationEvent, TestProviders, @@ -24,7 +23,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); @@ -36,7 +34,6 @@ describe('RegistryEventDetails', () => { const wrapper = mount( { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.test.tsx index 355077ee50066..2d06c040c5b00 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_details.test.tsx @@ -22,7 +22,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.test.tsx index 661fc562cc34c..3703d6fe441c0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.test.tsx @@ -24,7 +24,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.tsx index 0faa6a4fbba74..887ffdd9584a5 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { get } from 'lodash/fp'; import React from 'react'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.test.tsx index b3911f9eded67..c5515bd4f2d90 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_signature.test.tsx @@ -24,7 +24,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_details.test.tsx index 35872d0093f02..16874b30de835 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_details.test.tsx @@ -21,7 +21,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx index f5dc4c6fdf599..20a635a16bbaf 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_file_details.test.tsx @@ -22,7 +22,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.test.tsx index 516d279765904..983ee00ef9b6b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.test.tsx @@ -89,7 +89,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.tsx index b1027bf12b7d2..ba791aae4b86c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/system/generic_row_renderer.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { get } from 'lodash/fp'; import React from 'react'; @@ -324,10 +322,9 @@ export const createEndpointRegistryRowRenderer = ({ dataset?.toLowerCase() === 'endpoint.events.registry' && action?.toLowerCase() === actionName ); }, - renderRow: ({ browserFields, data, isDraggable, timelineId }) => ( + renderRow: ({ data, isDraggable, timelineId }) => ( { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_host_working_dir.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_host_working_dir.test.tsx index b61e00f1752b8..fa1a92cc0b723 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_host_working_dir.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/user_host_working_dir.test.tsx @@ -19,7 +19,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.test.tsx index 7f0ec8b7b0b79..62836cbffb2b5 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_details.test.tsx @@ -20,7 +20,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.test.tsx index 12f2fd08163ba..b60a2965bfd70 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.test.tsx @@ -23,7 +23,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.tsx index 0a265fa7522b1..6786bb996325c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_row_renderer.tsx @@ -5,8 +5,6 @@ * 2.0. */ -/* eslint-disable react/display-name */ - import { get } from 'lodash/fp'; import React from 'react'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.test.tsx index 28034dac8f575..3f27b80359131 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.test.tsx @@ -34,7 +34,6 @@ jest.mock('@elastic/eui', () => { const original = jest.requireActual('@elastic/eui'); return { ...original, - // eslint-disable-next-line react/display-name EuiScreenReaderOnly: () => <>, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx index 815f8f43d5c14..ad141829858ae 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx @@ -31,7 +31,6 @@ jest.mock('../../../containers/details/index', () => ({ useTimelineEventsDetails: jest.fn(), })); jest.mock('../body/events/index', () => ({ - // eslint-disable-next-line react/display-name Events: () => <>, })); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx index 7c7342b366f73..a199dd5aa55f8 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx @@ -68,7 +68,7 @@ const StatefulTimelineComponent: React.FC = ({ getTimeline(state, timelineId) ?? timelineDefaults ) ); - const { setTimelineFullScreen, timelineFullScreen } = useTimelineFullScreen(); + const { timelineFullScreen } = useTimelineFullScreen(); useEffect(() => { if (!savedObjectId) { @@ -145,7 +145,6 @@ const StatefulTimelineComponent: React.FC = ({ graphEventId={graphEventId} renderCellValue={renderCellValue} rowRenderers={rowRenderers} - setTimelineFullScreen={setTimelineFullScreen} timelineId={timelineId} timelineType={timelineType} timelineDescription={description} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/pinned_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/pinned_tab_content/index.test.tsx index b8e99718fa933..cb41d0c69bc97 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/pinned_tab_content/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/pinned_tab_content/index.test.tsx @@ -32,7 +32,6 @@ jest.mock('../../../containers/details/index', () => ({ useTimelineEventsDetails: jest.fn(), })); jest.mock('../body/events/index', () => ({ - // eslint-disable-next-line react/display-name Events: () => <>, })); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx index 2fc8c2149c35b..c9bb14dfc0c67 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx @@ -34,7 +34,6 @@ jest.mock('../../../containers/details/index', () => ({ useTimelineEventsDetails: jest.fn(), })); jest.mock('../body/events/index', () => ({ - // eslint-disable-next-line react/display-name Events: () => <>, })); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx index cfe2af0ab7c31..1041d5fbc7d7d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx @@ -55,7 +55,6 @@ const PinnedTabContent = lazy(() => import('../pinned_tab_content')); interface BasicTimelineTab { renderCellValue: (props: CellValueElementProps) => React.ReactNode; rowRenderers: RowRenderer[]; - setTimelineFullScreen?: (fullScreen: boolean) => void; timelineFullScreen?: boolean; timelineId: TimelineId; timelineType: TimelineType; diff --git a/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx index d67cc746f352f..83079e0cdc2fe 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx @@ -199,7 +199,6 @@ const transformControlColumns = ({ controlColumns.map( ({ id: columnId, headerCellRender = EmptyHeaderCellRender, rowCellRender, width }, i) => ({ id: `${columnId}`, - // eslint-disable-next-line react/display-name headerCellRender: () => { const HeaderActions = headerCellRender; return ( @@ -222,7 +221,6 @@ const transformControlColumns = ({ ); }, - // eslint-disable-next-line react/display-name rowCellRender: ({ isDetails, isExpandable, diff --git a/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx index c04cc58f453c3..6f69c54233858 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx @@ -116,7 +116,6 @@ const EventRenderedViewComponent = ({ name: ActionTitle, truncateText: false, hideForMobile: false, - // eslint-disable-next-line react/display-name render: (name: unknown, item: unknown) => { const alertId = get(item, '_id'); const rowIndex = events.findIndex((evt) => evt._id === alertId); @@ -149,7 +148,6 @@ const EventRenderedViewComponent = ({ }), truncateText: false, hideForMobile: false, - // eslint-disable-next-line react/display-name render: (name: unknown, item: TimelineItem) => { const timestamp = get(item, `ecs.timestamp`); return ; @@ -162,7 +160,6 @@ const EventRenderedViewComponent = ({ }), truncateText: false, hideForMobile: false, - // eslint-disable-next-line react/display-name render: (name: unknown, item: TimelineItem) => { const ruleName = get(item, `ecs.signal.rule.name`); /* `ecs.${ALERT_RULE_NAME}`*/ const ruleId = get(item, `ecs.signal.rule.id`); /* `ecs.${ALERT_RULE_ID}`*/ @@ -176,7 +173,6 @@ const EventRenderedViewComponent = ({ }), truncateText: false, hideForMobile: false, - // eslint-disable-next-line react/display-name render: (name: unknown, item: TimelineItem) => { const ecsData = get(item, 'ecs'); const reason = get(item, `ecs.signal.reason`); /* `ecs.${ALERT_REASON}`*/ diff --git a/x-pack/plugins/timelines/public/components/t_grid/toolbar/bulk_actions/alert_status_bulk_actions.tsx b/x-pack/plugins/timelines/public/components/t_grid/toolbar/bulk_actions/alert_status_bulk_actions.tsx index be4a75e443494..08f47f5361161 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/toolbar/bulk_actions/alert_status_bulk_actions.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/toolbar/bulk_actions/alert_status_bulk_actions.tsx @@ -126,7 +126,6 @@ export const AlertStatusBulkActionsComponent = React.memo { export const createWithKibanaMock = () => { const services = createStartServicesMock(); + // eslint-disable-next-line react/display-name return (Component: unknown) => (props: unknown) => { return React.createElement(Component as string, { ...(props as object), kibana: { services } }); }; diff --git a/x-pack/plugins/timelines/public/mock/mock_hover_actions.tsx b/x-pack/plugins/timelines/public/mock/mock_hover_actions.tsx index 0a8542713da68..31df992f5ef0b 100644 --- a/x-pack/plugins/timelines/public/mock/mock_hover_actions.tsx +++ b/x-pack/plugins/timelines/public/mock/mock_hover_actions.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; -/* eslint-disable react/display-name */ export const mockHoverActions = { getAddToTimelineButton: () => <>{'Add To Timeline'}, getColumnToggleButton: () => <>{'Column Toggle'}, diff --git a/x-pack/plugins/timelines/public/mock/plugin_mock.tsx b/x-pack/plugins/timelines/public/mock/plugin_mock.tsx index 70e895cb000d5..066485319f911 100644 --- a/x-pack/plugins/timelines/public/mock/plugin_mock.tsx +++ b/x-pack/plugins/timelines/public/mock/plugin_mock.tsx @@ -17,19 +17,13 @@ import { mockHoverActions } from './mock_hover_actions'; export const createTGridMocks = () => ({ getHoverActions: () => mockHoverActions, - // eslint-disable-next-line react/display-name getTGrid: () => <>{'hello grid'}, - // eslint-disable-next-line react/display-name getFieldBrowser: () =>
    , - // eslint-disable-next-line react/display-name getLastUpdated: (props: LastUpdatedAtProps) => , - // eslint-disable-next-line react/display-name getLoadingPanel: (props: LoadingPanelProps) => , getUseAddToTimeline: () => useAddToTimeline, getUseAddToTimelineSensor: () => useAddToTimelineSensor, getUseDraggableKeyboardWrapper: () => useDraggableKeyboardWrapper, - // eslint-disable-next-line react/display-name getAddToExistingCaseButton: () =>
    , - // eslint-disable-next-line react/display-name getAddToNewCaseButton: () =>
    , }); diff --git a/yarn.lock b/yarn.lock index c7435bb22ca27..6d491e4b8ba49 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,6 +25,13 @@ dependencies: "@babel/highlight" "^7.10.4" +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.5.5": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" @@ -133,6 +140,22 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/eslint-parser@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.7.tgz#2dc3d0ff0ea22bb1e08d93b4eeb1149bf1c75f2d" + integrity sha512-yJkHyomClm6A2Xzb8pdAo4HzYMSXFn1O5zrCYvbFP0yQFvHueLedV8WiEno8yJOKStjUXzBZzJFeWQ7b3YMsqQ== + dependencies: + eslint-scope "^5.1.1" + eslint-visitor-keys "^2.1.0" + semver "^6.3.0" + +"@babel/eslint-plugin@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/eslint-plugin/-/eslint-plugin-7.14.5.tgz#70b76608d49094062e8da2a2614d50fec775c00f" + integrity sha512-nzt/YMnOOIRikvSn2hk9+W2omgJBy6U8TN0R+WTTmqapA+HnZTuviZaketdTE9W7/k/+E/DfZlt1ey1NSE39pg== + dependencies: + eslint-rule-composer "^0.3.0" + "@babel/generator@^7.12.1", "@babel/generator@^7.12.10", "@babel/generator@^7.12.5", "@babel/generator@^7.13.0", "@babel/generator@^7.4.4": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.5.tgz#848d7b9f031caca9d0cd0af01b063f226f52d785" @@ -574,7 +597,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.13", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7", "@babel/parser@^7.13.0", "@babel/parser@^7.4.5", "@babel/parser@^7.7.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.13", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7", "@babel/parser@^7.13.0", "@babel/parser@^7.4.5": version "7.13.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.9.tgz#ca34cb95e1c2dd126863a84465ae8ef66114be99" integrity sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw== @@ -2001,7 +2024,7 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.5.tgz#665450911c6031af38f81db530f387ec04cd9a98" integrity sha512-121rumjddw9c3NCQ55KGkyE1h/nzWhU/owjhw0l4mQrkzz4x9SGS1X8gFLraHwX7td3Yo4QTL+qj0NcIzN87BA== @@ -2033,7 +2056,7 @@ "@babel/parser" "^7.15.4" "@babel/types" "^7.15.4" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.4.5": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== @@ -2063,7 +2086,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.14.5", "@babel/types@^7.14.9", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.14.5", "@babel/types@^7.14.9", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.15.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== @@ -2743,6 +2766,21 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@eslint/eslintrc@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" + integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^13.9.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@gulp-sourcemaps/identity-map@1.X": version "1.0.2" resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz#1e6fe5d8027b1f285dc0d31762f566bccd73d5a9" @@ -3059,6 +3097,20 @@ "@hapi/bourne" "2.x.x" "@hapi/hoek" "9.x.x" +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" + integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== + "@icons/material@^0.2.4": version "0.2.4" resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" @@ -5966,18 +6018,18 @@ "@types/cheerio" "*" "@types/react" "*" -"@types/eslint@^6.1.3": - version "6.1.3" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-6.1.3.tgz#ec2a66e445a48efaa234020eb3b6e8f06afc9c61" - integrity sha512-llYf1QNZaDweXtA7uY6JczcwHmFwJL9TpK3E6sY0B18l6ulDT6VWNMAdEjYccFHiDfxLPxffd8QmSDV4QUUspA== +"@types/eslint@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.0.tgz#7e41f2481d301c68e14f483fe10b017753ce8d5a" + integrity sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A== dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree@*": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + version "0.0.50" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" + integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== "@types/expect@^1.20.4": version "1.20.4" @@ -6317,12 +6369,12 @@ "@types/parse5" "*" "@types/tough-cookie" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4": +"@types/json-schema@*", "@types/json-schema@^7.0.4": version "7.0.5" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== -"@types/json-schema@^7.0.6": +"@types/json-schema@^7.0.6", "@types/json-schema@^7.0.7": version "7.0.7" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== @@ -6665,12 +6717,7 @@ dependencies: "@types/node" "*" -"@types/prettier@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.2.tgz#5bb52ee68d0f8efa9cc0099920e56be6cc4e37f3" - integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA== - -"@types/prettier@^2.3.2": +"@types/prettier@^2.0.0", "@types/prettier@^2.3.2": version "2.3.2" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== @@ -7250,148 +7297,73 @@ resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg== -"@typescript-eslint/eslint-plugin@^4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.1.tgz#22dd301ce228aaab3416b14ead10b1db3e7d3180" - integrity sha512-5JriGbYhtqMS1kRcZTQxndz1lKMwwEXKbwZbkUZNnp6MJX0+OVXnG0kOlBZP4LUAxEyzu3cs+EXd/97MJXsGfw== +"@typescript-eslint/eslint-plugin@^4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz#9f41efaee32cdab7ace94b15bd19b756dd099b0a" + integrity sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA== dependencies: - "@typescript-eslint/experimental-utils" "4.14.1" - "@typescript-eslint/scope-manager" "4.14.1" - debug "^4.1.1" + "@typescript-eslint/experimental-utils" "4.31.2" + "@typescript-eslint/scope-manager" "4.31.2" + debug "^4.3.1" functional-red-black-tree "^1.0.1" - lodash "^4.17.15" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.1.tgz#a5c945cb24dabb96747180e1cfc8487f8066f471" - integrity sha512-2CuHWOJwvpw0LofbyG5gvYjEyoJeSvVH2PnfUQSn0KQr4v8Dql2pr43ohmx4fdPQ/eVoTSFjTi/bsGEXl/zUUQ== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.14.1" - "@typescript-eslint/types" "4.14.1" - "@typescript-eslint/typescript-estree" "4.14.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/experimental-utils@^4.0.1": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.3.0.tgz#3f3c6c508e01b8050d51b016e7f7da0e3aefcb87" - integrity sha512-cmmIK8shn3mxmhpKfzMMywqiEheyfXLV/+yPDnOTvQX/ztngx7Lg/OD26J8gTZfkLKUmaEBxO2jYP3keV7h2OQ== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.3.0" - "@typescript-eslint/types" "4.3.0" - "@typescript-eslint/typescript-estree" "4.3.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/parser@^4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.14.1.tgz#3bd6c24710cd557d8446625284bcc9c6d52817c6" - integrity sha512-mL3+gU18g9JPsHZuKMZ8Z0Ss9YP1S5xYZ7n68Z98GnPq02pYNQuRXL85b9GYhl6jpdvUc45Km7hAl71vybjUmw== - dependencies: - "@typescript-eslint/scope-manager" "4.14.1" - "@typescript-eslint/types" "4.14.1" - "@typescript-eslint/typescript-estree" "4.14.1" - debug "^4.1.1" - -"@typescript-eslint/scope-manager@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.14.1.tgz#8444534254c6f370e9aa974f035ced7fe713ce02" - integrity sha512-F4bjJcSqXqHnC9JGUlnqSa3fC2YH5zTtmACS1Hk+WX/nFB0guuynVK5ev35D4XZbdKjulXBAQMyRr216kmxghw== - dependencies: - "@typescript-eslint/types" "4.14.1" - "@typescript-eslint/visitor-keys" "4.14.1" - -"@typescript-eslint/scope-manager@4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.3.0.tgz#c743227e087545968080d2362cfb1273842cb6a7" - integrity sha512-cTeyP5SCNE8QBRfc+Lgh4Xpzje46kNUhXYfc3pQWmJif92sjrFuHT9hH4rtOkDTo/si9Klw53yIr+djqGZS1ig== - dependencies: - "@typescript-eslint/types" "4.3.0" - "@typescript-eslint/visitor-keys" "4.3.0" - -"@typescript-eslint/types@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.14.1.tgz#b3d2eb91dafd0fd8b3fce7c61512ac66bd0364aa" - integrity sha512-SkhzHdI/AllAgQSxXM89XwS1Tkic7csPdndUuTKabEwRcEfR8uQ/iPA3Dgio1rqsV3jtqZhY0QQni8rLswJM2w== - -"@typescript-eslint/types@4.28.3": - version "4.28.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.3.tgz#8fffd436a3bada422c2c1da56060a0566a9506c7" - integrity sha512-kQFaEsQBQVtA9VGVyciyTbIg7S3WoKHNuOp/UF5RG40900KtGqfoiETWD/v0lzRXc+euVE9NXmfer9dLkUJrkA== + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" -"@typescript-eslint/types@4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.3.0.tgz#1f0b2d5e140543e2614f06d48fb3ae95193c6ddf" - integrity sha512-Cx9TpRvlRjOppGsU6Y6KcJnUDOelja2NNCX6AZwtVHRzaJkdytJWMuYiqi8mS35MRNA3cJSwDzXePfmhU6TANw== +"@typescript-eslint/experimental-utils@4.31.2", "@typescript-eslint/experimental-utils@^4.0.1": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz#98727a9c1e977dd5d20c8705e69cd3c2a86553fa" + integrity sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.31.2" + "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/typescript-estree" "4.31.2" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/parser@^4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.31.2.tgz#54aa75986e3302d91eff2bbbaa6ecfa8084e9c34" + integrity sha512-EcdO0E7M/sv23S/rLvenHkb58l3XhuSZzKf6DBvLgHqOYdL6YFMYVtreGFWirxaU2mS1GYDby3Lyxco7X5+Vjw== + dependencies: + "@typescript-eslint/scope-manager" "4.31.2" + "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/typescript-estree" "4.31.2" + debug "^4.3.1" -"@typescript-eslint/typescript-estree@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.1.tgz#20d3b8c8e3cdc8f764bdd5e5b0606dd83da6075b" - integrity sha512-M8+7MbzKC1PvJIA8kR2sSBnex8bsR5auatLCnVlNTJczmJgqRn8M+sAlQfkEq7M4IY3WmaNJ+LJjPVRrREVSHQ== +"@typescript-eslint/scope-manager@4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz#1d528cb3ed3bcd88019c20a57c18b897b073923a" + integrity sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w== dependencies: - "@typescript-eslint/types" "4.14.1" - "@typescript-eslint/visitor-keys" "4.14.1" - debug "^4.1.1" - globby "^11.0.1" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" + "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/visitor-keys" "4.31.2" -"@typescript-eslint/typescript-estree@4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.3.0.tgz#0edc1068e6b2e4c7fdc54d61e329fce76241cee8" - integrity sha512-ZAI7xjkl+oFdLV/COEz2tAbQbR3XfgqHEGy0rlUXzfGQic6EBCR4s2+WS3cmTPG69aaZckEucBoTxW9PhzHxxw== - dependencies: - "@typescript-eslint/types" "4.3.0" - "@typescript-eslint/visitor-keys" "4.3.0" - debug "^4.1.1" - globby "^11.0.1" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" +"@typescript-eslint/types@4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.31.2.tgz#2aea7177d6d744521a168ed4668eddbd912dfadf" + integrity sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w== -"@typescript-eslint/typescript-estree@^4.14.1": - version "4.28.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.3.tgz#253d7088100b2a38aefe3c8dd7bd1f8232ec46fb" - integrity sha512-YAb1JED41kJsqCQt1NcnX5ZdTA93vKFCMP4lQYG6CFxd0VzDJcKttRlMrlG+1qiWAw8+zowmHU1H0OzjWJzR2w== +"@typescript-eslint/typescript-estree@4.31.2", "@typescript-eslint/typescript-estree@^4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz#abfd50594d8056b37e7428df3b2d185ef2d0060c" + integrity sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA== dependencies: - "@typescript-eslint/types" "4.28.3" - "@typescript-eslint/visitor-keys" "4.28.3" + "@typescript-eslint/types" "4.31.2" + "@typescript-eslint/visitor-keys" "4.31.2" debug "^4.3.1" globby "^11.0.3" is-glob "^4.0.1" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/visitor-keys@4.14.1": - version "4.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.1.tgz#e93c2ff27f47ee477a929b970ca89d60a117da91" - integrity sha512-TAblbDXOI7bd0C/9PE1G+AFo7R5uc+ty1ArDoxmrC1ah61Hn6shURKy7gLdRb1qKJmjHkqu5Oq+e4Kt0jwf1IA== +"@typescript-eslint/visitor-keys@4.31.2": + version "4.31.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz#7d5b4a4705db7fe59ecffb273c1d082760f635cc" + integrity sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug== dependencies: - "@typescript-eslint/types" "4.14.1" - eslint-visitor-keys "^2.0.0" - -"@typescript-eslint/visitor-keys@4.28.3": - version "4.28.3" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.3.tgz#26ac91e84b23529968361045829da80a4e5251c4" - integrity sha512-ri1OzcLnk1HH4gORmr1dllxDzzrN6goUIz/P4MHFV0YZJDCADPR3RvYNp0PW2SetKTThar6wlbFTL00hV2Q+fg== - dependencies: - "@typescript-eslint/types" "4.28.3" - eslint-visitor-keys "^2.0.0" - -"@typescript-eslint/visitor-keys@4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.3.0.tgz#0e5ab0a09552903edeae205982e8521e17635ae0" - integrity sha512-xZxkuR7XLM6RhvLkgv9yYlTcBHnTULzfnw4i6+z2TGBLy9yljAypQaZl9c3zFvy7PNI7fYWyvKYtohyF8au3cw== - dependencies: - "@typescript-eslint/types" "4.3.0" + "@typescript-eslint/types" "4.31.2" eslint-visitor-keys "^2.0.0" "@ungap/promise-all-settled@1.1.2": @@ -7633,6 +7605,11 @@ acorn-jsx@^5.1.0: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== +acorn-jsx@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: version "1.8.2" resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" @@ -7667,7 +7644,7 @@ acorn@^6.0.1, acorn@^6.0.4, acorn@^6.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.0.0, acorn@^7.1.0, acorn@^7.1.1: +acorn@^7.0.0, acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0: version "7.4.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== @@ -7811,7 +7788,7 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.5.5, ajv@^6.9.1: +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.5.5: version "6.12.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== @@ -7831,6 +7808,16 @@ ajv@^6.11.0, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.1: + version "8.6.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764" + integrity sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -8198,14 +8185,6 @@ aria-hidden@^1.1.1: dependencies: tslib "^1.0.0" -aria-query@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" - integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= - dependencies: - ast-types-flow "0.0.7" - commander "^2.11.0" - aria-query@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" @@ -8288,13 +8267,15 @@ array-from@^2.1.1: resolved "https://registry.yarnpkg.com/array-from/-/array-from-2.1.1.tgz#cfe9d8c26628b9dc5aecc62a9f5d8f1f352c1195" integrity sha1-z+nYwmYoudxa7MYqn12PHzUsEZU= -array-includes@^3.0.3, array-includes@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" - integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== +array-includes@^3.0.3, array-includes@^3.1.1, array-includes@^3.1.2, array-includes@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a" + integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.0" + es-abstract "^1.18.0-next.2" + get-intrinsic "^1.1.1" is-string "^1.0.5" array-initial@^1.0.0: @@ -8356,21 +8337,23 @@ array.prototype.find@^2.1.1: define-properties "^1.1.3" es-abstract "^1.17.4" -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== +array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3, array.prototype.flat@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" + integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.18.0-next.1" -array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" - integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== +array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" + integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.18.0-next.1" function-bind "^1.1.1" array.prototype.map@^1.0.1: @@ -8467,7 +8450,7 @@ ast-transform@0.0.0: esprima "~1.0.4" through "~2.3.4" -ast-types-flow@0.0.7, ast-types-flow@^0.0.7: +ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= @@ -8494,11 +8477,6 @@ ast-types@^0.7.0: resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.7.8.tgz#902d2e0d60d071bdcd46dc115e1809ed11c138a9" integrity sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk= -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -8688,12 +8666,10 @@ axios@^0.21.2: dependencies: follow-redirects "^1.14.0" -axobject-query@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" - integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww== - dependencies: - ast-types-flow "0.0.7" +axobject-query@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" + integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== babel-code-frame@^6.26.0: version "6.26.0" @@ -8704,18 +8680,6 @@ babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-eslint@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - babel-generator@^6.18.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" @@ -10296,7 +10260,7 @@ chai@^4.1.2: pathval "^1.1.0" type-detect "^4.0.5" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -10960,7 +10924,7 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@2, commander@^2.11.0, commander@^2.19.0, commander@^2.20.0, commander@^2.7.1, commander@^2.9.0: +commander@2, commander@^2.19.0, commander@^2.20.0, commander@^2.7.1, commander@^2.9.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -11198,11 +11162,6 @@ container-info@^1.0.1: resolved "https://registry.yarnpkg.com/container-info/-/container-info-1.0.1.tgz#6b383cb5e197c8d921e88983388facb04124b56b" integrity sha512-wk/+uJvPHOFG+JSwQS+fw6H6yw3Oyc8Kw9L4O2MN817uA90OqJ59nlZbbLPqDudsjJ7Tetee3pwExdKpd2ahjQ== -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= - content-disposition@0.5.3, content-disposition@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -12340,10 +12299,10 @@ dagre@^0.8.2: graphlib "^2.1.8" lodash "^4.17.15" -damerau-levenshtein@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" - integrity sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ= +damerau-levenshtein@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791" + integrity sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug== dash-ast@^1.0.0: version "1.0.0" @@ -12433,7 +12392,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@3.X, debug@^3.0.0, debug@^3.0.1, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@3.X, debug@^3.0.0, debug@^3.0.1, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -13062,14 +13021,6 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -13547,7 +13498,7 @@ emittery@^0.7.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" integrity sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4= -emoji-regex@^7.0.1, emoji-regex@^7.0.2: +emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== @@ -13557,6 +13508,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.0.0: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -13617,6 +13573,15 @@ endent@^2.0.1: fast-json-parse "^1.0.3" objectorarray "^1.0.4" +enhanced-resolve@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" + integrity sha1-TW5omzcl+GCQknzMhs2fFjW4ni4= + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.2.0" + tapable "^0.1.8" + enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" @@ -13626,16 +13591,7 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0: memory-fs "^0.5.0" tapable "^1.0.0" -enhanced-resolve@~0.9.0: - version "0.9.1" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" - integrity sha1-TW5omzcl+GCQknzMhs2fFjW4ni4= - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.2.0" - tapable "^0.1.8" - -enquirer@^2.3.6: +enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -13773,27 +13729,29 @@ error-stack-parser@^2.0.4, error-stack-parser@^2.0.6: dependencies: stackframe "^1.1.1" -es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5, es-abstract@^1.18.0-next.2, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.9.0: - version "1.18.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4" - integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw== +es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.1, es-abstract@^1.18.2, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.9.0: + version "1.18.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" + integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" function-bind "^1.1.1" get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" has "^1.0.3" has-symbols "^1.0.2" - is-callable "^1.2.3" + internal-slot "^1.0.3" + is-callable "^1.2.4" is-negative-zero "^2.0.1" - is-regex "^1.1.2" - is-string "^1.0.5" - object-inspect "^1.9.0" + is-regex "^1.1.4" + is-string "^1.0.7" + object-inspect "^1.11.0" object-keys "^1.1.1" object.assign "^4.1.2" string.prototype.trimend "^1.0.4" string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.0" + unbox-primitive "^1.0.1" es-array-method-boxes-properly@^1.0.0: version "1.0.0" @@ -13974,12 +13932,10 @@ escodegen@~1.2.0: optionalDependencies: source-map "~0.1.30" -eslint-config-prettier@^6.15.0: - version "6.15.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" - integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== - dependencies: - get-stdin "^6.0.0" +eslint-config-prettier@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz#f4a4bd2832e810e8cc7c1411ec85b3e85c0c53f9" + integrity sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg== eslint-formatter-pretty@^4.0.0: version "4.0.0" @@ -13994,72 +13950,50 @@ eslint-formatter-pretty@^4.0.0: string-width "^4.2.0" supports-hyperlinks "^2.0.0" -eslint-import-resolver-node@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== - dependencies: - debug "^2.6.9" - resolve "^1.5.0" - -eslint-import-resolver-node@^0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" - integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== dependencies: - debug "^2.6.9" - resolve "^1.13.1" + debug "^3.2.7" + resolve "^1.20.0" -eslint-import-resolver-webpack@0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.11.1.tgz#fcf1fd57a775f51e18f442915f85dd6ba45d2f26" - integrity sha512-eK3zR7xVQR/MaoBWwGuD+CULYVuqe5QFlDukman71aI6IboCGzggDUohHNfu1ZeBnbHcUHJc0ywWoXUBNB6qdg== +eslint-import-resolver-webpack@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.1.tgz#6d2fb928091daf2da46efa1e568055555b2de902" + integrity sha512-O/8mG6AHmaKYSMb4lWxiXPpaARxOJ4rMQEHJ8vTgjS1MXooJA3KPgBPPAdOPoV17v5ML5120qod5FBLM+DtgEw== dependencies: array-find "^1.0.0" - debug "^2.6.8" - enhanced-resolve "~0.9.0" + debug "^3.2.7" + enhanced-resolve "^0.9.1" find-root "^1.1.0" - has "^1.0.1" - interpret "^1.0.0" - lodash "^4.17.4" - node-libs-browser "^1.0.0 || ^2.0.0" - resolve "^1.10.0" - semver "^5.3.0" - -eslint-module-utils@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz#cdf0b40d623032274ccd2abd7e64c4e524d6e19c" - integrity sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw== - dependencies: - debug "^2.6.9" - pkg-dir "^2.0.0" + has "^1.0.3" + interpret "^1.4.0" + is-core-module "^2.4.0" + is-regex "^1.1.3" + lodash "^4.17.21" + resolve "^1.20.0" + semver "^5.7.1" -eslint-module-utils@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" - integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== +eslint-module-utils@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534" + integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q== dependencies: - debug "^2.6.9" + debug "^3.2.7" pkg-dir "^2.0.0" -eslint-plugin-babel@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz#75a2413ffbf17e7be57458301c60291f2cfbf560" - integrity sha512-VsQEr6NH3dj664+EyxJwO4FCYm/00JhYb3Sk3ft8o+fpKuIfQ9TaW6uVUfvwMXHcf/lsnRIoyFPsLMyiWCSL/g== - dependencies: - eslint-rule-composer "^0.3.0" - -eslint-plugin-ban@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-ban/-/eslint-plugin-ban-1.4.0.tgz#b3a7b000412921336b1feeece5b8ce9a69dea605" - integrity sha512-wtrUOLg8WUiGDkVnmyMseLRtXYBM+bJTe2STvhqznHVj6RPAiNEVLbvDj2b0WWwY/2ldKqeaw3iHUHwfCJ8c8Q== +eslint-plugin-ban@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-ban/-/eslint-plugin-ban-1.5.2.tgz#5ca01fa5acdecf79e7422e2876eb330c22b5de9a" + integrity sha512-i6yjMbep866kREX8HfCPM32QyTZG4gfhlEFjL7s04P+sJjsM+oa0pejwyLOz/6s/oiW7BQqc6u3Dcr9tKz+svg== dependencies: requireindex "~1.2.0" -eslint-plugin-cypress@^2.11.3: - version "2.11.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.11.3.tgz#54ee4067aa8192aa62810cd35080eb577e191ab7" - integrity sha512-hOoAid+XNFtpvOzZSNWP5LDrQBEJwbZwjib4XJ1KcRYKjeVj0mAmPmucG4Egli4j/aruv+Ow/acacoloWWCl9Q== +eslint-plugin-cypress@^2.12.1: + version "2.12.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz#9aeee700708ca8c058e00cdafe215199918c2632" + integrity sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA== dependencies: globals "^11.12.0" @@ -14079,63 +14013,68 @@ eslint-plugin-eslint-comments@^3.2.0: escape-string-regexp "^1.0.5" ignore "^5.0.5" -eslint-plugin-import@^2.22.1: - version "2.22.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" - integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== +eslint-plugin-import@^2.24.2: + version "2.24.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz#2c8cd2e341f3885918ee27d18479910ade7bb4da" + integrity sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q== dependencies: - array-includes "^3.1.1" - array.prototype.flat "^1.2.3" - contains-path "^0.1.0" + array-includes "^3.1.3" + array.prototype.flat "^1.2.4" debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.4" - eslint-module-utils "^2.6.0" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.6.2" + find-up "^2.0.0" has "^1.0.3" + is-core-module "^2.6.0" minimatch "^3.0.4" - object.values "^1.1.1" - read-pkg-up "^2.0.0" - resolve "^1.17.0" - tsconfig-paths "^3.9.0" + object.values "^1.1.4" + pkg-up "^2.0.0" + read-pkg-up "^3.0.0" + resolve "^1.20.0" + tsconfig-paths "^3.11.0" -eslint-plugin-jest@^24.3.4: - version "24.3.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.3.4.tgz#6d90c3554de0302e879603dd6405474c98849f19" - integrity sha512-3n5oY1+fictanuFkTWPwSlehugBTAgwLnYLFsCllzE3Pl1BwywHl5fL0HFxmMjoQY8xhUDk8uAWc3S4JOHGh3A== +eslint-plugin-jest@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.5.0.tgz#a223a0040a19af749a161807254f0e47f5bfdcc3" + integrity sha512-Cm+XdX7Nms2UXGRnivHFVcM3ZmlKheHvc9VD78iZLO1XcqB59WbVjrMSiesCbHDlToxWjMJDiJMgc1CzFE13Vg== dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" -eslint-plugin-jsx-a11y@^6.2.3: - version "6.2.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz#b872a09d5de51af70a97db1eea7dc933043708aa" - integrity sha512-CawzfGt9w83tyuVekn0GDPU9ytYtxyxyFZ3aSWROmnRRFQFT2BiPJd7jvRdzNDi6oLWaS2asMeYSNMjWTV4eNg== +eslint-plugin-jsx-a11y@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd" + integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg== dependencies: - "@babel/runtime" "^7.4.5" - aria-query "^3.0.0" - array-includes "^3.0.3" + "@babel/runtime" "^7.11.2" + aria-query "^4.2.2" + array-includes "^3.1.1" ast-types-flow "^0.0.7" - axobject-query "^2.0.2" - damerau-levenshtein "^1.0.4" - emoji-regex "^7.0.2" + axe-core "^4.0.2" + axobject-query "^2.2.0" + damerau-levenshtein "^1.0.6" + emoji-regex "^9.0.0" has "^1.0.3" - jsx-ast-utils "^2.2.1" + jsx-ast-utils "^3.1.0" + language-tags "^1.0.5" -eslint-plugin-mocha@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-6.2.2.tgz#6ef4b78bd12d744beb08a06e8209de330985100d" - integrity sha512-oNhPzfkT6Q6CJ0HMVJ2KLxEWG97VWGTmuHOoRcDLE0U88ugUyFNV9wrT2XIt5cGtqc5W9k38m4xTN34L09KhBA== +eslint-plugin-mocha@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-9.0.0.tgz#b4457d066941eecb070dc06ed301c527d9c61b60" + integrity sha512-d7knAcQj1jPCzZf3caeBIn3BnW6ikcvfz0kSqQpwPYcVGLoJV5sz0l0OJB2LR8I7dvTDbqq1oV6ylhSgzA10zg== dependencies: - ramda "^0.26.1" + eslint-utils "^3.0.0" + ramda "^0.27.1" -eslint-plugin-no-unsanitized@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.0.2.tgz#83c6fcf8e34715112757e03dd4ee436dce29ed45" - integrity sha512-JnwpoH8Sv4QOjrTDutENBHzSnyYtspdjtglYtqUtAHe6f6LLKqykJle+UwFPg23GGwt5hI3amS9CRDezW8GAww== +eslint-plugin-no-unsanitized@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-3.1.5.tgz#7e1ee74cf41ae59fec48c2ee2e21a7dcb86965fb" + integrity sha512-s/6w++p1590h/H/dE2Wo660bOkaM/3OEK14Y7xm1UT0bafxkKw1Cq0ksjxkxLdH/WWd014DlsLKuD6CyNrR2Dw== -eslint-plugin-node@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.0.0.tgz#365944bb0804c5d1d501182a9bc41a0ffefed726" - integrity sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg== +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== dependencies: eslint-plugin-es "^3.0.0" eslint-utils "^2.0.0" @@ -14149,10 +14088,10 @@ eslint-plugin-prefer-object-spread@^1.2.1: resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-object-spread/-/eslint-plugin-prefer-object-spread-1.2.1.tgz#27fb91853690cceb3ae6101d9c8aecc6a67a402c" integrity sha1-J/uRhTaQzOs65hAdnIrsxqZ6QCw= -eslint-plugin-prettier@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" - integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== +eslint-plugin-prettier@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" + integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ== dependencies: prettier-linter-helpers "^1.0.0" @@ -14161,27 +14100,30 @@ eslint-plugin-react-hooks@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== -eslint-plugin-react-perf@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-perf/-/eslint-plugin-react-perf-3.2.3.tgz#e28d42d3a1f7ec3c8976a94735d8e17e7d652a45" - integrity sha512-bMiPt7uywwS1Ly25n752NE3Ei0XBZ3igplTkZ8GPJKyZVVUd3cHgzILGeQW2HIeAkzQ9zwk9HM6EcYDipdFk3Q== +eslint-plugin-react-perf@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-perf/-/eslint-plugin-react-perf-3.3.0.tgz#d606792b5c7b63a6d03c558d7edd8b8d33080805" + integrity sha512-POzjKFOuHpyGZFwLkqPK8kxLy/tYVeq30h+SEM1UwfSmkyPcbEjbbGw1gN5R1hxCHf4zJ0G0NIbY+oCe8i/DNQ== -eslint-plugin-react@^7.20.3: - version "7.20.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz#0590525e7eb83890ce71f73c2cf836284ad8c2f1" - integrity sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg== +eslint-plugin-react@^7.26.1: + version "7.26.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.26.1.tgz#41bcfe3e39e6a5ac040971c1af94437c80daa40e" + integrity sha512-Lug0+NOFXeOE+ORZ5pbsh6mSKjBKXDXItUD2sQoT+5Yl0eoT82DqnXeTMfUare4QVCn9QwXbfzO/dBLjLXwVjQ== dependencies: - array-includes "^3.1.1" - array.prototype.flatmap "^1.2.3" + array-includes "^3.1.3" + array.prototype.flatmap "^1.2.4" doctrine "^2.1.0" - has "^1.0.3" - jsx-ast-utils "^2.4.1" - object.entries "^1.1.2" - object.fromentries "^2.0.2" - object.values "^1.1.1" + estraverse "^5.2.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.0.4" + object.entries "^1.1.4" + object.fromentries "^2.0.4" + object.hasown "^1.0.0" + object.values "^1.1.4" prop-types "^15.7.2" - resolve "^1.17.0" - string.prototype.matchall "^4.0.2" + resolve "^2.0.0-next.3" + semver "^6.3.0" + string.prototype.matchall "^4.0.5" eslint-rule-composer@^0.3.0: version "0.3.0" @@ -14201,12 +14143,12 @@ eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - esrecurse "^4.1.0" + esrecurse "^4.3.0" estraverse "^4.1.1" eslint-traverse@^1.0.0: @@ -14214,13 +14156,6 @@ eslint-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/eslint-traverse/-/eslint-traverse-1.0.0.tgz#108d360a171a6e6334e1af0cee905a93bd0dcc53" integrity sha512-bSp37rQs93LF8rZ409EI369DGCI4tELbFVmFNxI6QbuveS7VRxYVyUhwDafKN/enMyUh88HQQ7ZoGUHtPuGdcw== -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - eslint-utils@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" @@ -14228,67 +14163,89 @@ eslint-utils@^2.0.0: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== eslint-visitor-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint-visitor-keys@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint@^7.32.0: + version "7.32.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" + integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== dependencies: - "@babel/code-frame" "^7.0.0" + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.3" + "@humanwhocodes/config-array" "^0.5.0" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + enquirer "^2.3.5" + escape-string-regexp "^4.0.0" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" + glob-parent "^5.1.2" + globals "^13.6.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" + levn "^0.4.1" + lodash.merge "^4.6.2" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.9" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" - integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== dependencies: - acorn "^7.1.0" - acorn-jsx "^5.1.0" - eslint-visitor-keys "^1.1.0" + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" @@ -14305,12 +14262,12 @@ esprima@~3.1.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== dependencies: - estraverse "^4.0.0" + estraverse "^5.1.0" esrecurse@^4.1.0: version "4.2.1" @@ -14319,11 +14276,23 @@ esrecurse@^4.1.0: dependencies: estraverse "^4.1.0" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + estraverse@~1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.5.1.tgz#867a3e8e58a9f84618afb6c2ddbcd916b7cbaf71" @@ -14913,13 +14882,6 @@ figures@^3.2.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - file-entry-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" @@ -14927,6 +14889,13 @@ file-entry-cache@^6.0.0: dependencies: flat-cache "^3.0.4" +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + file-loader@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.2.0.tgz#5fb124d2369d7075d70a9a5abecd12e60a95215e" @@ -15166,15 +15135,6 @@ flagged-respawn@^1.0.0: resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7" integrity sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c= -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -15193,11 +15153,6 @@ flatstr@^1.0.12: resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== -flatted@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" - integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== - flatted@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" @@ -15653,7 +15608,7 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== @@ -15701,11 +15656,6 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - get-stdin@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" @@ -15743,6 +15693,14 @@ get-stream@^5.0.0, get-stream@^5.1.0: dependencies: pump "^3.0.0" +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -15835,7 +15793,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0: +glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -15981,12 +15939,12 @@ globals@^11.1.0, globals@^11.12.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^12.1.0: - version "12.3.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" - integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== +globals@^13.6.0, globals@^13.9.0: + version "13.11.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.11.0.tgz#40ef678da117fe7bd2e28f1fab24951bd0255be7" + integrity sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g== dependencies: - type-fest "^0.8.1" + type-fest "^0.20.2" globals@^9.18.0: version "9.18.0" @@ -16467,6 +16425,13 @@ has-to-string-tag-x@^1.2.0: dependencies: has-symbol-support-x "^1.4.1" +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -17387,14 +17352,14 @@ internal-ip@^4.3.0: default-gateway "^4.2.0" ipaddr.js "^1.9.0" -internal-slot@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" - integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== dependencies: - es-abstract "^1.17.0-next.1" + get-intrinsic "^1.1.0" has "^1.0.3" - side-channel "^1.0.2" + side-channel "^1.0.4" interpret@^1.0.0, interpret@^1.1.0, interpret@^1.4.0: version "1.4.0" @@ -17579,10 +17544,10 @@ is-buffer@^2.0.0: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" - integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== is-ci@^2.0.0: version "2.0.0" @@ -17610,13 +17575,6 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" - integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== - dependencies: - has "^1.0.3" - is-core-module@^2.2.0: version "2.7.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3" @@ -17624,6 +17582,13 @@ is-core-module@^2.2.0: dependencies: has "^1.0.3" +is-core-module@^2.4.0, is-core-module@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" + integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -17978,13 +17943,13 @@ 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.4, is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.1, is-regex@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" - integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== +is-regex@^1.0.4, is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.1, is-regex@^1.1.2, is-regex@^1.1.3, is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: call-bind "^1.0.2" - has-symbols "^1.0.1" + has-tostringtag "^1.0.0" is-regexp@^2.0.0: version "2.1.0" @@ -18028,10 +17993,12 @@ 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, 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-string@^1.0.4, is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" is-subset@^0.1.1: version "0.1.1" @@ -19181,6 +19148,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -19323,13 +19295,13 @@ jsts@^1.6.2: resolved "https://registry.yarnpkg.com/jsts/-/jsts-1.6.2.tgz#c0efc885edae06ae84f78cbf2a0110ba929c5925" integrity sha512-JNfDQk/fo5MeXx4xefvCyHZD22/DHowHr5K07FdgCJ81MEqn02HsDV5FQvYTz60ZIOv/+hhGbsVzXX5cuDWWlA== -jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" - integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" + integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q== dependencies: - array-includes "^3.1.1" - object.assign "^4.1.0" + array-includes "^3.1.2" + object.assign "^4.1.2" jszip@^3.2.2: version "3.3.0" @@ -19490,6 +19462,18 @@ labeled-stream-splicer@^2.0.0: inherits "^2.0.1" stream-splicer "^2.0.0" +language-subtag-registry@~0.3.2: + version "0.3.21" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" + integrity sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg== + +language-tags@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" + integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= + dependencies: + language-subtag-registry "~0.3.2" + last-run@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" @@ -19580,7 +19564,15 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.3.0, levn@~0.3.0: +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= @@ -19748,14 +19740,14 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= dependencies: graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" + parse-json "^4.0.0" + pify "^3.0.0" strip-bom "^3.0.0" load-json-file@^6.2.0: @@ -19853,7 +19845,7 @@ lodash.clone@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= -lodash.clonedeep@4.5.0: +lodash.clonedeep@4.5.0, lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= @@ -19968,7 +19960,7 @@ lodash.memoize@~3.0.3: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= -lodash.merge@^4.6.1: +lodash.merge@^4.6.1, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== @@ -20028,6 +20020,11 @@ lodash.toarray@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + lodash.union@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" @@ -21620,7 +21617,7 @@ node-jq@2.0.0: strip-final-newline "^2.0.0" tempfile "^3.0.0" -"node-libs-browser@^1.0.0 || ^2.0.0", node-libs-browser@^2.2.1: +node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== @@ -21984,10 +21981,10 @@ object-identity-map@^1.0.2: dependencies: object.entries "^1.1.0" -object-inspect@^1.6.0, object-inspect@^1.7.0, object-inspect@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" - integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== +object-inspect@^1.11.0, object-inspect@^1.6.0, object-inspect@^1.7.0, object-inspect@^1.9.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" + integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== object-inspect@~1.6.0: version "1.6.0" @@ -22041,16 +22038,16 @@ 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, object.entries@^1.1.1, object.entries@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" - integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== +object.entries@^1.0.4, object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2, object.entries@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.4.tgz#43ccf9a50bc5fd5b649d45ab1a579f24e088cafd" + integrity sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.5" - has "^1.0.3" + es-abstract "^1.18.2" -"object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.2, object.fromentries@^2.0.3: +"object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.3, object.fromentries@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8" integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ== @@ -22068,6 +22065,14 @@ object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0 define-properties "^1.1.3" es-abstract "^1.17.0-next.1" +object.hasown@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.0.0.tgz#bdbade33cfacfb25d7f26ae2b6cb870bf99905c2" + integrity sha512-qYMF2CLIjxxLGleeM0jrcB4kiv3loGVAjKQKvH8pSU/i2VcRRvUNmxbD+nEMmrXRfORhuVJuH8OtSYCZoue3zA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.1" + object.map@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" @@ -22091,15 +22096,14 @@ object.reduce@^1.0.0: for-own "^1.0.0" make-iterator "^1.0.0" -object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.3.tgz#eaa8b1e17589f02f698db093f7c62ee1699742ee" - integrity sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw== +object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.2, object.values@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30" + integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - has "^1.0.3" + es-abstract "^1.18.2" objectorarray@^1.0.4: version "1.0.4" @@ -22203,7 +22207,7 @@ optional-js@^2.0.0: resolved "https://registry.yarnpkg.com/optional-js/-/optional-js-2.1.1.tgz#c2dc519ad119648510b4d241dbb60b1167c36a46" integrity sha512-mUS4bDngcD5kKzzRUd1HVQkr9Lzzby3fSrrPR9wOHhQiyYo+hDS5NVli5YQzGjQRQ15k5Sno4xH9pfykJdeEUA== -optionator@^0.8.1, optionator@^0.8.3: +optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -22215,6 +22219,18 @@ optionator@^0.8.1, optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + ora@^4.0.3, ora@^4.0.4: version "4.1.1" resolved "https://registry.yarnpkg.com/ora/-/ora-4.1.1.tgz#566cc0348a15c36f5f0e979612842e02ba9dddbc" @@ -22880,13 +22896,6 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -23086,6 +23095,13 @@ pkg-up@3.1.0, pkg-up@^3.1.0: dependencies: find-up "^3.0.0" +pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + platform@^1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444" @@ -23645,6 +23661,11 @@ prebuild-install@^6.1.2: tar-fs "^2.0.0" tunnel-agent "^0.6.0" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -24194,12 +24215,12 @@ ramda@^0.21.0: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU= -ramda@^0.26, ramda@^0.26.1: +ramda@^0.26: version "0.26.1" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== -ramda@~0.27.1: +ramda@^0.27.1, ramda@~0.27.1: version "0.27.1" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== @@ -25074,13 +25095,13 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= dependencies: find-up "^2.0.0" - read-pkg "^2.0.0" + read-pkg "^3.0.0" read-pkg-up@^7.0.0, read-pkg-up@^7.0.1: version "7.0.1" @@ -25100,14 +25121,14 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= dependencies: - load-json-file "^2.0.0" + load-json-file "^4.0.0" normalize-package-data "^2.3.2" - path-type "^2.0.0" + path-type "^3.0.0" read-pkg@^5.2.0: version "5.2.0" @@ -25388,23 +25409,18 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" - integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0, regexp.prototype.flags@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e" - integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g== +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== regexpu-core@^4.7.1: version "4.7.1" @@ -25800,7 +25816,7 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-from-string@^2.0.1: +require-from-string@^2.0.1, require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== @@ -25927,15 +25943,7 @@ resolve@1.8.1: dependencies: path-parse "^1.0.5" -resolve@^1.1.10, resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.7.1, resolve@^1.8.1: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== - dependencies: - is-core-module "^2.1.0" - path-parse "^1.0.6" - -resolve@^1.14.2: +resolve@^1.1.10, resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.20.0, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.4.0, resolve@^1.7.1, resolve@^1.8.1: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -25943,6 +25951,14 @@ resolve@^1.14.2: is-core-module "^2.2.0" path-parse "^1.0.6" +resolve@^2.0.0-next.3: + version "2.0.0-next.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" + integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + resolve@~1.10.1: version "1.10.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.1.tgz#664842ac960795bbe758221cdccda61fb64b5f18" @@ -26036,13 +26052,6 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -26050,6 +26059,13 @@ rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -26421,7 +26437,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.3.2, semver@^7.3.2, semver@~7.3.2: +semver@7.3.2, semver@^7.2.1, semver@^7.3.2, semver@~7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== @@ -26780,15 +26796,6 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -27579,17 +27586,19 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" - integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== +"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.5.tgz#59370644e1db7e4c0c045277690cf7b01203c4da" + integrity sha512-Z5ZaXO0svs0M2xd/6By3qpeKpLKd9mO4v4q3oMEQrk8Ck4xOD5d5XeBOOjGrmVZZ/AHB1S0CgG4N5r1G9N3E2Q== dependencies: + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.17.0" - has-symbols "^1.0.1" - internal-slot "^1.0.2" - regexp.prototype.flags "^1.3.0" - side-channel "^1.0.2" + es-abstract "^1.18.2" + get-intrinsic "^1.1.1" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.3.1" + side-channel "^1.0.4" string.prototype.padend@^3.0.0: version "3.0.0" @@ -27757,7 +27766,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.0.1, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -28127,25 +28136,17 @@ tabbable@^3.0.0: resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2" integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ== -table@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" - integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== +table@^6.0.3, table@^6.0.9: + version "6.7.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" + integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== dependencies: - ajv "^6.9.1" - lodash "^4.17.11" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -table@^6.0.3: - version "6.0.4" - resolved "https://registry.yarnpkg.com/table/-/table-6.0.4.tgz#c523dd182177e926c723eb20e1b341238188aa0d" - integrity sha512-sBT4xRLdALd+NFBvwOz8bw4b15htyythha+q+DVZqy2RS08PPC8O2sZFgJYEY7bJvbCFKccs+WIZ/cd+xxTWCw== - dependencies: - ajv "^6.12.4" - lodash "^4.17.20" + ajv "^8.0.1" + lodash.clonedeep "^4.5.0" + lodash.truncate "^4.4.2" slice-ansi "^4.0.0" string-width "^4.2.0" + strip-ansi "^6.0.0" tapable@^0.1.8: version "0.1.10" @@ -28973,10 +28974,10 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tsconfig-paths@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" - integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== +tsconfig-paths@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36" + integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.1" @@ -29017,13 +29018,6 @@ tsutils@2.27.2: dependencies: tslib "^1.8.1" -tsutils@^3.17.1: - version "3.17.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" - integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== - dependencies: - tslib "^1.8.1" - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -29053,6 +29047,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -29219,7 +29220,7 @@ umd@^3.0.0: resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== -unbox-primitive@^1.0.0: +unbox-primitive@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== @@ -30944,7 +30945,7 @@ winston@^3.0.0, winston@^3.3.3: triple-beam "^1.3.0" winston-transport "^4.4.0" -word-wrap@~1.2.3: +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -31084,13 +31085,6 @@ write-pkg@^4.0.0: type-fest "^0.4.1" write-json-file "^3.2.0" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@^6.1.2, ws@^6.2.1: version "6.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" From 284732f058d8dba17a42ff99d4b9d1741bf89d1c Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Sun, 3 Oct 2021 09:43:45 -0700 Subject: [PATCH 21/98] [ci-stats] Local metrics fixes (#113492) * Rename `{ group: 'yarn start', id: 'started' }` to `{ group: 'scripts/kibana', id: 'dev server started' }` for consistency * Rename `{ group: '@kbn/optimizer' }` to `{ group: 'scripts/build_kibana_platform_plugins' }` for consistency * Include email for Elastic employees * Standardize on Unix paths * Set `subProcess: true` if the timing is already captured by a parent. * Move nestedTiming to global and use normalize-path --- packages/kbn-cli-dev-mode/src/cli_dev_mode.ts | 6 +-- .../ci_stats_reporter/ci_stats_reporter.ts | 20 +++++--- packages/kbn-dev-utils/src/run/metrics.ts | 49 ++++++++++--------- .../src/report_optimizer_timings.ts | 2 +- packages/kbn-pm/dist/index.js | 18 ++++--- packages/kbn-pm/src/commands/bootstrap.ts | 5 +- packages/kbn-pm/src/run.ts | 2 + 7 files changed, 58 insertions(+), 44 deletions(-) diff --git a/packages/kbn-cli-dev-mode/src/cli_dev_mode.ts b/packages/kbn-cli-dev-mode/src/cli_dev_mode.ts index a681f1ff2e4cd..28f38592ff3c4 100644 --- a/packages/kbn-cli-dev-mode/src/cli_dev_mode.ts +++ b/packages/kbn-cli-dev-mode/src/cli_dev_mode.ts @@ -289,8 +289,8 @@ export class CliDevMode { await reporter.timings({ timings: [ { - group: 'yarn start', - id: 'started', + group: 'scripts/kibana', + id: 'dev server started', ms: Date.now() - this.startTime!, meta: { success }, }, @@ -313,7 +313,7 @@ export class CliDevMode { await reporter.timings({ timings: [ { - group: 'yarn start', + group: 'scripts/kibana', id: 'dev server restart', ms, meta: { diff --git a/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts b/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts index 3e9db78c2630c..4d6ea646b2ab1 100644 --- a/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts +++ b/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts @@ -90,20 +90,24 @@ export class CiStatsReporter { this.log.debug(e.message); } + const isElasticCommitter = email && email.endsWith('@elastic.co') ? true : false; + const defaultMetadata = { - osPlatform: Os.platform(), - osRelease: Os.release(), - osArch: Os.arch(), + committerHash: email + ? crypto.createHash('sha256').update(email).digest('hex').substring(0, 20) + : undefined, cpuCount: Os.cpus()?.length, cpuModel: Os.cpus()[0]?.model, cpuSpeed: Os.cpus()[0]?.speed, + email: isElasticCommitter ? email : undefined, freeMem: Os.freemem(), - totalMem: Os.totalmem(), - committerHash: email - ? crypto.createHash('sha256').update(email).digest('hex').substring(0, 20) - : undefined, - isElasticCommitter: email ? email.endsWith('@elastic.co') : undefined, + isElasticCommitter, kibanaUuid, + nestedTiming: process.env.CI_STATS_NESTED_TIMING ? true : false, + osArch: Os.arch(), + osPlatform: Os.platform(), + osRelease: Os.release(), + totalMem: Os.totalmem(), }; this.log.debug('CIStatsReporter committerHash: %s', defaultMetadata.committerHash); diff --git a/packages/kbn-dev-utils/src/run/metrics.ts b/packages/kbn-dev-utils/src/run/metrics.ts index 7d60bccee3a75..90a005bfc64dd 100644 --- a/packages/kbn-dev-utils/src/run/metrics.ts +++ b/packages/kbn-dev-utils/src/run/metrics.ts @@ -8,6 +8,7 @@ import path from 'path'; import { REPO_ROOT } from '@kbn/utils'; +import normalizePath from 'normalize-path'; import { CiStatsReporter } from '../ci_stats_reporter'; import { ToolingLog } from '../tooling_log'; @@ -23,39 +24,39 @@ export class Metrics { this.reporter = CiStatsReporter.fromEnv(log); this.meta = new Map(); this.startTime = Date.now(); - this.filePath = path.relative(REPO_ROOT, process.argv[1]).replace('.js', ''); + + // standardize to unix path + this.filePath = normalizePath(path.relative(REPO_ROOT, process.argv[1]).replace('.js', '')); + } + + createTiming(meta: object, command?: string) { + return { + group: `${command ? `${this.filePath} ${command}` : this.filePath}`, + id: 'total', + ms: Date.now() - this.startTime, + meta: { + nestedTiming: process.env.CI_STATS_NESTED_TIMING, + ...Object.fromEntries(this.meta), + ...meta, + }, + }; + } + + async reportCancelled(command?: string) { + return await this.reporter.timings({ + timings: [this.createTiming({ cancelled: true }, command)], + }); } async reportSuccess(command?: string) { return await this.reporter.timings({ - timings: [ - { - group: `${command ? `${this.filePath} ${command}` : this.filePath}`, - id: 'total', - ms: Date.now() - this.startTime, - meta: { - success: true, - ...Object.fromEntries(this.meta), - }, - }, - ], + timings: [this.createTiming({ success: true }, command)], }); } async reportError(errorMessage?: string, command?: string) { return await this.reporter.timings({ - timings: [ - { - group: `${command ? `${this.filePath} ${command}` : this.filePath}`, - id: 'total', - ms: Date.now() - this.startTime, - meta: { - success: false, - errorMessage, - ...Object.fromEntries(this.meta), - }, - }, - ], + timings: [this.createTiming({ success: false, errorMessage }, command)], }); } } diff --git a/packages/kbn-optimizer/src/report_optimizer_timings.ts b/packages/kbn-optimizer/src/report_optimizer_timings.ts index 094838a21a0be..e57d0b9a641c6 100644 --- a/packages/kbn-optimizer/src/report_optimizer_timings.ts +++ b/packages/kbn-optimizer/src/report_optimizer_timings.ts @@ -46,7 +46,7 @@ export function reportOptimizerTimings(log: ToolingLog, config: OptimizerConfig) await reporter.timings({ timings: [ { - group: '@kbn/optimizer', + group: 'scripts/build_kibana_platform_plugins', id: 'total', ms: time, meta: { diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 5bdc5047d84fe..c96a1eb28cfce 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -9024,18 +9024,21 @@ class CiStatsReporter { this.log.debug(e.message); } + const isElasticCommitter = email && email.endsWith('@elastic.co') ? true : false; const defaultMetadata = { - osPlatform: _os.default.platform(), - osRelease: _os.default.release(), - osArch: _os.default.arch(), + committerHash: email ? _crypto.default.createHash('sha256').update(email).digest('hex').substring(0, 20) : undefined, cpuCount: (_Os$cpus = _os.default.cpus()) === null || _Os$cpus === void 0 ? void 0 : _Os$cpus.length, cpuModel: (_Os$cpus$ = _os.default.cpus()[0]) === null || _Os$cpus$ === void 0 ? void 0 : _Os$cpus$.model, cpuSpeed: (_Os$cpus$2 = _os.default.cpus()[0]) === null || _Os$cpus$2 === void 0 ? void 0 : _Os$cpus$2.speed, + email: isElasticCommitter ? email : undefined, freeMem: _os.default.freemem(), - totalMem: _os.default.totalmem(), - committerHash: email ? _crypto.default.createHash('sha256').update(email).digest('hex').substring(0, 20) : undefined, - isElasticCommitter: email ? email.endsWith('@elastic.co') : undefined, - kibanaUuid + isElasticCommitter, + kibanaUuid, + nestedTiming: process.env.CI_STATS_NESTED_TIMING ? true : false, + osArch: _os.default.arch(), + osPlatform: _os.default.platform(), + osRelease: _os.default.release(), + totalMem: _os.default.totalmem() }; this.log.debug('CIStatsReporter committerHash: %s', defaultMetadata.committerHash); return await this.req({ @@ -60653,6 +60656,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope +process.env.CI_STATS_NESTED_TIMING = 'true'; async function runCommand(command, config) { const runStartTime = Date.now(); let kbn; diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index f8f209fb90de1..95eeeb329da3d 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -145,7 +145,10 @@ export const BootstrapCommand: ICommand = { upstreamBranch: kbn.kibanaProject.json.branch, // prevent loading @kbn/utils by passing null kibanaUuid: kbn.getUuid() || null, - timings: timings.map((t) => ({ group: 'scripts/kbn bootstrap', ...t })), + timings: timings.map((t) => ({ + group: 'scripts/kbn bootstrap', + ...t, + })), }); }, }; diff --git a/packages/kbn-pm/src/run.ts b/packages/kbn-pm/src/run.ts index ae3669ff3b16b..41d26e26a3c29 100644 --- a/packages/kbn-pm/src/run.ts +++ b/packages/kbn-pm/src/run.ts @@ -15,6 +15,8 @@ import { buildProjectGraph } from './utils/projects'; import { renderProjectsTree } from './utils/projects_tree'; import { Kibana } from './utils/kibana'; +process.env.CI_STATS_NESTED_TIMING = 'true'; + export async function runCommand(command: ICommand, config: Omit) { const runStartTime = Date.now(); let kbn; From 7162f16f7a4d55be767d9c007cfb370e8d7709aa Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Mon, 4 Oct 2021 08:53:40 +0300 Subject: [PATCH 22/98] [Vislib] Removes fontAwesome usage (#113516) * [Vislib] Removes fontAwesome usage * Fix CI * Fix types * Update src/plugins/vis_types/vislib/public/vislib/components/tooltip/_tooltip.scss Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com> Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/vis_types/vislib/kibana.json | 2 +- .../editor/components/gauge/labels_panel.tsx | 14 ---- src/plugins/vis_types/vislib/public/plugin.ts | 2 - .../vislib/public/vis_controller.tsx | 3 - .../vislib/components/tooltip/_tooltip.scss | 3 +- .../vislib/public/vislib/lib/_alerts.scss | 55 ------------- .../vislib/public/vislib/lib/_index.scss | 1 - .../vislib/public/vislib/lib/alerts.js | 79 ------------------- .../vislib/public/vislib/lib/binder.ts | 6 +- .../vislib/public/vislib/lib/handler.js | 5 +- .../public/vislib/lib/layout/_layout.scss | 4 - .../vislib/lib/layout/types/column_layout.js | 4 - .../vislib/lib/layout/types/gauge_layout.js | 4 - .../vislib/public/vislib/lib/vis_config.js | 1 - .../vislib/partials/touchdown_template.tsx | 3 +- .../vislib/visualizations/gauges/meter.js | 13 --- .../point_series/heatmap_chart.js | 7 -- src/plugins/vis_types/vislib/tsconfig.json | 1 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 20 files changed, 8 insertions(+), 203 deletions(-) delete mode 100644 src/plugins/vis_types/vislib/public/vislib/lib/_alerts.scss delete mode 100644 src/plugins/vis_types/vislib/public/vislib/lib/alerts.js diff --git a/src/plugins/vis_types/vislib/kibana.json b/src/plugins/vis_types/vislib/kibana.json index 39cc9bb53c01c..dfefa11cb06e5 100644 --- a/src/plugins/vis_types/vislib/kibana.json +++ b/src/plugins/vis_types/vislib/kibana.json @@ -3,7 +3,7 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["charts", "data", "expressions", "visualizations", "kibanaLegacy"], + "requiredPlugins": ["charts", "data", "expressions", "visualizations"], "requiredBundles": ["kibanaUtils", "visDefaultEditor", "visTypeXy", "visTypePie", "fieldFormats"], "owner": { "name": "Vis Editors", diff --git a/src/plugins/vis_types/vislib/public/editor/components/gauge/labels_panel.tsx b/src/plugins/vis_types/vislib/public/editor/components/gauge/labels_panel.tsx index ae200892cec57..4650a37d2f986 100644 --- a/src/plugins/vis_types/vislib/public/editor/components/gauge/labels_panel.tsx +++ b/src/plugins/vis_types/vislib/public/editor/components/gauge/labels_panel.tsx @@ -49,20 +49,6 @@ function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInter setGaugeValue('style', { ...stateParams.gauge.style, [paramName]: value }) } /> - - ); } diff --git a/src/plugins/vis_types/vislib/public/plugin.ts b/src/plugins/vis_types/vislib/public/plugin.ts index 7e9095ce41990..07e9b72aa429f 100644 --- a/src/plugins/vis_types/vislib/public/plugin.ts +++ b/src/plugins/vis_types/vislib/public/plugin.ts @@ -12,7 +12,6 @@ import { Plugin as ExpressionsPublicPlugin } from '../../../expressions/public'; import { VisualizationsSetup } from '../../../visualizations/public'; import { ChartsPluginSetup } from '../../../charts/public'; import { DataPublicPluginStart } from '../../../data/public'; -import { KibanaLegacyStart } from '../../../kibana_legacy/public'; import { LEGACY_PIE_CHARTS_LIBRARY } from '../../pie/common/index'; import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn'; @@ -31,7 +30,6 @@ export interface VisTypeVislibPluginSetupDependencies { /** @internal */ export interface VisTypeVislibPluginStartDependencies { data: DataPublicPluginStart; - kibanaLegacy: KibanaLegacyStart; } export type VisTypeVislibCoreSetup = CoreSetup; diff --git a/src/plugins/vis_types/vislib/public/vis_controller.tsx b/src/plugins/vis_types/vislib/public/vis_controller.tsx index 7bae32d031b46..1e940d23e83da 100644 --- a/src/plugins/vis_types/vislib/public/vis_controller.tsx +++ b/src/plugins/vis_types/vislib/public/vis_controller.tsx @@ -79,9 +79,6 @@ export const createVislibVisController = ( return; } - const [, { kibanaLegacy }] = await core.getStartServices(); - kibanaLegacy.loadFontAwesome(); - // @ts-expect-error const { Vis: Vislib } = await import('./vislib/vis'); const { uiState, event: fireEvent } = handlers; diff --git a/src/plugins/vis_types/vislib/public/vislib/components/tooltip/_tooltip.scss b/src/plugins/vis_types/vislib/public/vislib/components/tooltip/_tooltip.scss index bafec7edf3b94..6448ceca38c23 100644 --- a/src/plugins/vis_types/vislib/public/vislib/components/tooltip/_tooltip.scss +++ b/src/plugins/vis_types/vislib/public/vislib/components/tooltip/_tooltip.scss @@ -49,8 +49,7 @@ } .visTooltip__headerIcon { - flex: 0 0 auto; - padding-right: $euiSizeS; + margin-right: $euiSizeXS; } .visTooltip__headerText { diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/_alerts.scss b/src/plugins/vis_types/vislib/public/vislib/lib/_alerts.scss deleted file mode 100644 index 596f4675b1254..0000000000000 --- a/src/plugins/vis_types/vislib/public/vislib/lib/_alerts.scss +++ /dev/null @@ -1,55 +0,0 @@ - -.visAlerts__tray { - position: absolute; - bottom: ($euiSizeXS + 1px); - left: 0; - right: 0; - list-style: none; - padding: 0; - - transition-property: opacity; - transition-delay: $euiAnimSpeedExtraFast; - transition-duration: $euiAnimSpeedExtraFast; -} - -.visAlerts__icon { - margin: 0; - padding: 0 $euiSizeS; - flex: 0 0 auto; - align-self: center; -} - -.visAlerts__text { - flex: 1 1 auto; - margin: 0; - padding: 0; -} - -.visAlerts__close { - cursor: pointer; -} - -.visAlert { - margin: 0 $euiSizeS $euiSizeS; - padding: $euiSizeXS $euiSizeS $euiSizeXS $euiSizeXS; - display: flex; -} - -// Modifier naming and colors. -$visAlertTypes: ( - info: $euiColorPrimary, - success: $euiColorSecondary, - warning: $euiColorWarning, - danger: $euiColorDanger, -); - -// Create button modifiders based upon the map. -@each $name, $color in $visAlertTypes { - .visAlert--#{$name} { - $backgroundColor: tintOrShade($color, 90%, 70%); - $textColor: makeHighContrastColor($color, $backgroundColor); - - background-color: $backgroundColor; - color: $textColor; - } -} diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/_index.scss b/src/plugins/vis_types/vislib/public/vislib/lib/_index.scss index 6ab284fd8d122..5217bc7300bf5 100644 --- a/src/plugins/vis_types/vislib/public/vislib/lib/_index.scss +++ b/src/plugins/vis_types/vislib/public/vislib/lib/_index.scss @@ -1,2 +1 @@ -@import './alerts'; @import './layout/index'; diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/alerts.js b/src/plugins/vis_types/vislib/public/vislib/lib/alerts.js deleted file mode 100644 index 6d4299c125edf..0000000000000 --- a/src/plugins/vis_types/vislib/public/vislib/lib/alerts.js +++ /dev/null @@ -1,79 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import $ from 'jquery'; -import _ from 'lodash'; - -/** - * Adds alerts that float in front of a visualization - * - * @class Alerts - * @constructor - * @param el {HTMLElement} Reference to DOM element - */ -export class Alerts { - constructor(vis, alertDefs) { - this.vis = vis; - this.data = vis.data; - this.alertDefs = _.cloneDeep(alertDefs); - - this.alerts = _(alertDefs) - .map((alertDef) => { - if (!alertDef) return; - if (alertDef.test && !alertDef.test(vis, this.data)) return; - return this._addAlert(alertDef); - }) - .compact(); - } - - _addAlert(alertDef) { - const type = alertDef.type || 'info'; - const icon = alertDef.icon || type; - const msg = alertDef.msg; - // alert container - const $icon = $('').addClass('visAlerts__icon fa fa-' + icon); - const $text = $('

    ').addClass('visAlerts__text').text(msg); - const $closeIcon = $('').addClass('fa fa-close'); - const $closeDiv = $('

    ').addClass('visAlerts__close').append($closeIcon); - - const $alert = $('
    ') - .addClass('visAlert visAlert--' + type) - .append([$icon, $text, $closeDiv]); - $closeDiv.on('click', () => { - $alert.remove(); - }); - - return $alert; - } - - // renders initial alerts - render() { - const alerts = this.alerts; - const vis = this.vis; - - $(vis.element).find('.visWrapper__alerts').append($('
    ').addClass('visAlerts__tray')); - if (!alerts.size()) return; - $(vis.element).find('.visAlerts__tray').append(alerts.value()); - } - - // shows new alert - show(msg, type) { - const vis = this.vis; - const alert = { - msg: msg, - type: type, - }; - if (this.alertDefs.find((alertDef) => alertDef.msg === alert.msg)) return; - this.alertDefs.push(alert); - $(vis.element).find('.visAlerts__tray').append(this._addAlert(alert)); - } - - destroy() { - $(this.vis.element).find('.visWrapper__alerts').remove(); - } -} diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/binder.ts b/src/plugins/vis_types/vislib/public/vislib/lib/binder.ts index 886745ba19563..31e49697d4bd9 100644 --- a/src/plugins/vis_types/vislib/public/vislib/lib/binder.ts +++ b/src/plugins/vis_types/vislib/public/vislib/lib/binder.ts @@ -33,14 +33,14 @@ export class Binder { destroyers.forEach((fn) => fn()); } - jqOn(el: HTMLElement, ...args: [string, (event: JQueryEventObject) => void]) { + jqOn(el: HTMLElement, ...args: [string, (event: JQuery.Event) => void]) { const $el = $(el); $el.on(...args); this.disposal.push(() => $el.off(...args)); } - fakeD3Bind(el: HTMLElement, event: string, handler: (event: JQueryEventObject) => void) { - this.jqOn(el, event, (e: JQueryEventObject) => { + fakeD3Bind(el: HTMLElement, event: string, handler: (event: JQuery.Event) => void) { + this.jqOn(el, event, (e: JQuery.Event) => { // mimic https://github.com/mbostock/d3/blob/3abb00113662463e5c19eb87cd33f6d0ddc23bc0/src/selection/on.js#L87-L94 const o = d3.event; // Events can be reentrant (e.g., focus). d3.event = e; diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/handler.js b/src/plugins/vis_types/vislib/public/vislib/lib/handler.js index a2b747f4d5d9c..7a68b128faf09 100644 --- a/src/plugins/vis_types/vislib/public/vislib/lib/handler.js +++ b/src/plugins/vis_types/vislib/public/vislib/lib/handler.js @@ -17,7 +17,6 @@ import { visTypes as chartTypes } from '../visualizations/vis_types'; import { NoResults } from '../errors'; import { Layout } from './layout/layout'; import { ChartTitle } from './chart_title'; -import { Alerts } from './alerts'; import { Axis } from './axis/axis'; import { ChartGrid as Grid } from './chart_grid'; import { Binder } from './binder'; @@ -46,7 +45,6 @@ export class Handler { this.ChartClass = chartTypes[visConfig.get('type')]; this.uiSettings = uiSettings; this.charts = []; - this.vis = vis; this.visConfig = visConfig; this.data = visConfig.data; @@ -56,7 +54,6 @@ export class Handler { .map((axisArgs) => new Axis(visConfig, axisArgs)); this.valueAxes = visConfig.get('valueAxes').map((axisArgs) => new Axis(visConfig, axisArgs)); this.chartTitle = new ChartTitle(visConfig); - this.alerts = new Alerts(this, visConfig.get('alerts')); this.grid = new Grid(this, visConfig.get('grid')); if (visConfig.get('type') === 'point_series') { @@ -69,7 +66,7 @@ export class Handler { this.layout = new Layout(visConfig); this.binder = new Binder(); - this.renderArray = _.filter([this.layout, this.chartTitle, this.alerts], Boolean); + this.renderArray = _.filter([this.layout, this.chartTitle], Boolean); this.renderArray = this.renderArray .concat(this.valueAxes) diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/layout/_layout.scss b/src/plugins/vis_types/vislib/public/vislib/lib/layout/_layout.scss index 7ead0b314c7ad..4612602d93f1c 100644 --- a/src/plugins/vis_types/vislib/public/vislib/lib/layout/_layout.scss +++ b/src/plugins/vis_types/vislib/public/vislib/lib/layout/_layout.scss @@ -271,10 +271,6 @@ min-width: 0; } -.visWrapper__alerts { - position: relative; -} - // General Axes .visAxis__column--top .axis-div svg { diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/layout/types/column_layout.js b/src/plugins/vis_types/vislib/public/vislib/lib/layout/types/column_layout.js index e8cc0f15e89e2..02910394035f8 100644 --- a/src/plugins/vis_types/vislib/public/vislib/lib/layout/types/column_layout.js +++ b/src/plugins/vis_types/vislib/public/vislib/lib/layout/types/column_layout.js @@ -90,10 +90,6 @@ export function columnLayout(el, data) { class: 'visWrapper__chart', splits: chartSplit, }, - { - type: 'div', - class: 'visWrapper__alerts', - }, { type: 'div', class: 'visAxis--x visAxis__column--bottom', diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/layout/types/gauge_layout.js b/src/plugins/vis_types/vislib/public/vislib/lib/layout/types/gauge_layout.js index 6b38f126232c7..e3b808b63c8c1 100644 --- a/src/plugins/vis_types/vislib/public/vislib/lib/layout/types/gauge_layout.js +++ b/src/plugins/vis_types/vislib/public/vislib/lib/layout/types/gauge_layout.js @@ -51,10 +51,6 @@ export function gaugeLayout(el, data) { class: 'visWrapper__chart', splits: chartSplit, }, - { - type: 'div', - class: 'visWrapper__alerts', - }, { type: 'div', class: 'visAxis__splitTitles--x', diff --git a/src/plugins/vis_types/vislib/public/vislib/lib/vis_config.js b/src/plugins/vis_types/vislib/public/vislib/lib/vis_config.js index 30dc2d82d4890..cc9e48897d053 100644 --- a/src/plugins/vis_types/vislib/public/vislib/lib/vis_config.js +++ b/src/plugins/vis_types/vislib/public/vislib/lib/vis_config.js @@ -18,7 +18,6 @@ const DEFAULT_VIS_CONFIG = { style: { margin: { top: 10, right: 3, bottom: 5, left: 3 }, }, - alerts: [], categoryAxes: [], valueAxes: [], grid: {}, diff --git a/src/plugins/vis_types/vislib/public/vislib/partials/touchdown_template.tsx b/src/plugins/vis_types/vislib/public/vislib/partials/touchdown_template.tsx index 55955da07ebdd..731fbed7482c4 100644 --- a/src/plugins/vis_types/vislib/public/vislib/partials/touchdown_template.tsx +++ b/src/plugins/vis_types/vislib/public/vislib/partials/touchdown_template.tsx @@ -8,6 +8,7 @@ import React from 'react'; import ReactDOM from 'react-dom/server'; +import { EuiIcon } from '@elastic/eui'; interface Props { wholeBucket: boolean; @@ -16,7 +17,7 @@ interface Props { export const touchdownTemplate = ({ wholeBucket }: Props) => { return ReactDOM.renderToStaticMarkup(

    - + {wholeBucket ? 'Part of this bucket' : 'This area'} may contain partial data. The selected time range does not fully cover it. diff --git a/src/plugins/vis_types/vislib/public/vislib/visualizations/gauges/meter.js b/src/plugins/vis_types/vislib/public/vislib/visualizations/gauges/meter.js index ad278847b0780..4073aeeed434b 100644 --- a/src/plugins/vis_types/vislib/public/vislib/visualizations/gauges/meter.js +++ b/src/plugins/vis_types/vislib/public/vislib/visualizations/gauges/meter.js @@ -175,7 +175,6 @@ export class MeterGauge { const marginFactor = 0.95; const tooltip = this.gaugeChart.tooltip; const isTooltip = this.gaugeChart.handler.visConfig.get('addTooltip'); - const isDisplayWarning = this.gaugeChart.handler.visConfig.get('isDisplayWarning', false); const { angleFactor, maxAngle, minAngle } = this.gaugeConfig.gaugeType === 'Circle' ? circleAngles : arcAngles; const maxRadius = (Math.min(width, height / angleFactor) / 2) * marginFactor; @@ -261,7 +260,6 @@ export class MeterGauge { .style('fill', (d) => this.getColorBucket(Math.max(min, d.y))); const smallContainer = svg.node().getBBox().height < 70; - let hiddenLabels = smallContainer; // If the value label is hidden we later want to hide also all other labels // since they don't make sense as long as the actual value is hidden. @@ -286,7 +284,6 @@ export class MeterGauge { // The text is too long if it's larger than the inner free space minus a couple of random pixels for padding. const textTooLong = textLength >= getInnerFreeSpace() - 6; if (textTooLong) { - hiddenLabels = true; valueLabelHidden = true; } return textTooLong ? 'none' : 'initial'; @@ -302,9 +299,6 @@ export class MeterGauge { .style('display', function () { const textLength = this.getBBox().width; const textTooLong = textLength > maxRadius; - if (textTooLong) { - hiddenLabels = true; - } return smallContainer || textTooLong ? 'none' : 'initial'; }); @@ -317,9 +311,6 @@ export class MeterGauge { .style('display', function () { const textLength = this.getBBox().width; const textTooLong = textLength > maxRadius; - if (textTooLong) { - hiddenLabels = true; - } return valueLabelHidden || smallContainer || textTooLong ? 'none' : 'initial'; }); } @@ -335,10 +326,6 @@ export class MeterGauge { }); } - if (hiddenLabels && isDisplayWarning) { - this.gaugeChart.handler.alerts.show('Some labels were hidden due to size constraints'); - } - //center the visualization const transformX = width / 2; const transformY = height / 2 > maxRadius ? height / 2 : maxRadius; diff --git a/src/plugins/vis_types/vislib/public/vislib/visualizations/point_series/heatmap_chart.js b/src/plugins/vis_types/vislib/public/vislib/visualizations/point_series/heatmap_chart.js index bef6c939f864a..ecab91103d614 100644 --- a/src/plugins/vis_types/vislib/public/vislib/visualizations/point_series/heatmap_chart.js +++ b/src/plugins/vis_types/vislib/public/vislib/visualizations/point_series/heatmap_chart.js @@ -248,7 +248,6 @@ export class HeatmapChart extends PointSeries { }; } - let hiddenLabels = false; squares .append('text') .text((d) => zAxisFormatter(d.y)) @@ -257,9 +256,6 @@ export class HeatmapChart extends PointSeries { const textHeight = this.getBBox().height; const textTooLong = textLength > maxLength; const textTooWide = textHeight > maxHeight; - if (!d.hide && (textTooLong || textTooWide)) { - hiddenLabels = true; - } return d.hide || textTooLong || textTooWide ? 'none' : 'initial'; }) .style('dominant-baseline', 'central') @@ -278,9 +274,6 @@ export class HeatmapChart extends PointSeries { const verticalCenter = y(d) + squareHeight / 2; return `rotate(${rotate},${horizontalCenter},${verticalCenter})`; }); - if (hiddenLabels) { - this.baseChart.handler.alerts.show('Some labels were hidden due to size constraints'); - } } if (isTooltip) { diff --git a/src/plugins/vis_types/vislib/tsconfig.json b/src/plugins/vis_types/vislib/tsconfig.json index 8246b3f30646b..db00cd34203e6 100644 --- a/src/plugins/vis_types/vislib/tsconfig.json +++ b/src/plugins/vis_types/vislib/tsconfig.json @@ -17,7 +17,6 @@ { "path": "../../data/tsconfig.json" }, { "path": "../../expressions/tsconfig.json" }, { "path": "../../visualizations/tsconfig.json" }, - { "path": "../../kibana_legacy/tsconfig.json" }, { "path": "../../kibana_utils/tsconfig.json" }, { "path": "../../vis_default_editor/tsconfig.json" }, { "path": "../../vis_types/xy/tsconfig.json" }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 34e44d37bc4b8..1b83bcac5837f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -5628,7 +5628,6 @@ "visTypeVislib.aggResponse.allDocsTitle": "すべてのドキュメント", "visTypeVislib.controls.gaugeOptions.alignmentLabel": "アラインメント", "visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "範囲を自動拡張", - "visTypeVislib.controls.gaugeOptions.displayWarningsLabel": "警告を表示", "visTypeVislib.controls.gaugeOptions.extendRangeTooltip": "範囲をデータの最高値に広げます。", "visTypeVislib.controls.gaugeOptions.gaugeTypeLabel": "ゲージタイプ", "visTypeVislib.controls.gaugeOptions.labelsTitle": "ラベル", @@ -5639,7 +5638,6 @@ "visTypeVislib.controls.gaugeOptions.showScaleLabel": "縮尺を表示", "visTypeVislib.controls.gaugeOptions.styleTitle": "スタイル", "visTypeVislib.controls.gaugeOptions.subTextLabel": "サブラベル", - "visTypeVislib.controls.gaugeOptions.switchWarningsTooltip": "警告のオン/オフを切り替えます。オンにすると、すべてのラベルを表示できない際に警告が表示されます。", "visTypeVislib.controls.heatmapOptions.colorLabel": "色", "visTypeVislib.controls.heatmapOptions.colorScaleLabel": "カラースケール", "visTypeVislib.controls.heatmapOptions.colorsNumberLabel": "色の数", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1ec387f8f0f30..c29557eebd3f8 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -5674,7 +5674,6 @@ "visTypeVislib.aggResponse.allDocsTitle": "所有文档", "visTypeVislib.controls.gaugeOptions.alignmentLabel": "对齐方式", "visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "自动扩展范围", - "visTypeVislib.controls.gaugeOptions.displayWarningsLabel": "显示警告", "visTypeVislib.controls.gaugeOptions.extendRangeTooltip": "将数据范围扩展到数据中的最大值。", "visTypeVislib.controls.gaugeOptions.gaugeTypeLabel": "仪表类型", "visTypeVislib.controls.gaugeOptions.labelsTitle": "标签", @@ -5685,7 +5684,6 @@ "visTypeVislib.controls.gaugeOptions.showScaleLabel": "显示比例", "visTypeVislib.controls.gaugeOptions.styleTitle": "样式", "visTypeVislib.controls.gaugeOptions.subTextLabel": "子标签", - "visTypeVislib.controls.gaugeOptions.switchWarningsTooltip": "打开/关闭警告。打开时,如果标签没有全部显示,则显示警告。", "visTypeVislib.controls.heatmapOptions.colorLabel": "颜色", "visTypeVislib.controls.heatmapOptions.colorScaleLabel": "色阶", "visTypeVislib.controls.heatmapOptions.colorsNumberLabel": "颜色个数", From e0894f3dc22c8c2f07b4a845794638815baf17b7 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Mon, 4 Oct 2021 11:45:33 +0300 Subject: [PATCH 23/98] Unskips the visualize reporting functional test suite (#113535) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/test/functional/apps/visualize/reporting.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/visualize/reporting.ts b/x-pack/test/functional/apps/visualize/reporting.ts index 9491416f328eb..f08d242f4024f 100644 --- a/x-pack/test/functional/apps/visualize/reporting.ts +++ b/x-pack/test/functional/apps/visualize/reporting.ts @@ -42,8 +42,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/113496 - describe.skip('Print PDF button', () => { + describe('Print PDF button', () => { it('is available if new', async () => { await PageObjects.common.navigateToUrl('visualize', 'new', { useActualUrl: true }); await PageObjects.visualize.clickAggBasedVisualizations(); @@ -54,6 +53,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('becomes available when saved', async () => { + await PageObjects.timePicker.timePickerExists(); const fromTime = 'Apr 27, 2019 @ 23:56:51.374'; const toTime = 'Aug 23, 2019 @ 16:18:51.821'; await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); From 93522e5fa8b4d73dffaf1aaaa3e1d5d9703b29d4 Mon Sep 17 00:00:00 2001 From: Diana Derevyankina <54894989+DziyanaDzeraviankina@users.noreply.github.com> Date: Mon, 4 Oct 2021 12:41:56 +0300 Subject: [PATCH 24/98] [Lens] Rename Index pattern to Data view (#110252) * [Lens] Rename Index pattern to Data view * Update tests expected labels * Remove couple of unused translations * Remove unused translation * Revert accidentally not applied string because of merge conflict Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../editor_frame/config_panel/add_layer.tsx | 2 +- .../workspace_panel/workspace_panel.tsx | 12 ++++++------ .../editor_frame_service/error_helper.ts | 5 ++--- .../change_indexpattern.tsx | 4 ++-- .../indexpattern_datasource/datapanel.tsx | 18 +++++++++--------- .../dimensions_editor_helpers.tsx | 2 +- .../indexpattern_datasource/field_item.tsx | 8 ++++---- .../indexpattern_datasource/indexpattern.tsx | 4 ++-- .../indexpattern_datasource/layerpanel.tsx | 4 ++-- .../no_fields_callout.test.tsx | 2 +- .../no_fields_callout.tsx | 2 +- .../operations/definitions/last_value.test.tsx | 2 +- .../operations/definitions/last_value.tsx | 8 ++++---- .../operations/layer_helpers.ts | 4 +--- .../plugins/lens/server/routes/field_stats.ts | 2 +- .../translations/translations/ja-JP.json | 16 ---------------- .../translations/translations/zh-CN.json | 18 ------------------ 17 files changed, 38 insertions(+), 75 deletions(-) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/add_layer.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/add_layer.tsx index e052e06f1b2f1..b0c10abb75810 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/add_layer.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/add_layer.tsx @@ -57,7 +57,7 @@ export function AddLayerButton({ })} content={i18n.translate('xpack.lens.xyChart.addLayerTooltip', { defaultMessage: - 'Use multiple layers to combine visualization types or visualize different index patterns.', + 'Use multiple layers to combine visualization types or visualize different data views.', })} position="bottom" > diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx index c34e3c4137368..b3b9345344116 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx @@ -151,9 +151,9 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({ ? [ { shortMessage: '', - longMessage: i18n.translate('xpack.lens.indexPattern.missingIndexPattern', { + longMessage: i18n.translate('xpack.lens.indexPattern.missingDataView', { defaultMessage: - 'The {count, plural, one {index pattern} other {index patterns}} ({count, plural, one {id} other {ids}}: {indexpatterns}) cannot be found', + 'The {count, plural, one {data view} other {data views}} ({count, plural, one {id} other {ids}}: {indexpatterns}) cannot be found', values: { count: missingIndexPatterns.length, indexpatterns: missingIndexPatterns.join(', '), @@ -569,8 +569,8 @@ export const VisualizationWrapper = ({ })} data-test-subj="configuration-failure-reconfigure-indexpatterns" > - {i18n.translate('xpack.lens.editorFrame.indexPatternReconfigure', { - defaultMessage: `Recreate it in the index pattern management page`, + {i18n.translate('xpack.lens.editorFrame.dataViewReconfigure', { + defaultMessage: `Recreate it in the data view management page`, })} @@ -580,8 +580,8 @@ export const VisualizationWrapper = ({ <>

    diff --git a/x-pack/plugins/lens/public/editor_frame_service/error_helper.ts b/x-pack/plugins/lens/public/editor_frame_service/error_helper.ts index b19a295b68407..9df48d99ce762 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/error_helper.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/error_helper.ts @@ -160,9 +160,8 @@ export function getMissingCurrentDatasource() { } export function getMissingIndexPatterns(indexPatternIds: string[]) { - return i18n.translate('xpack.lens.editorFrame.expressionMissingIndexPattern', { - defaultMessage: - 'Could not find the {count, plural, one {index pattern} other {index pattern}}: {ids}', + return i18n.translate('xpack.lens.editorFrame.expressionMissingDataView', { + defaultMessage: 'Could not find the {count, plural, one {data view} other {data views}}: {ids}', values: { count: indexPatternIds.length, ids: indexPatternIds.join(', ') }, }); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx index 64d7f5efc9c4d..ca44e833981ab 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx @@ -69,8 +69,8 @@ export function ChangeIndexPattern({ >

    - {i18n.translate('xpack.lens.indexPattern.changeIndexPatternTitle', { - defaultMessage: 'Index pattern', + {i18n.translate('xpack.lens.indexPattern.changeDataViewTitle', { + defaultMessage: 'Data view', })}

    @@ -642,7 +642,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ iconType="boxesHorizontal" data-test-subj="lnsIndexPatternActions" aria-label={i18n.translate('xpack.lens.indexPatterns.actionsPopoverLabel', { - defaultMessage: 'Index pattern settings', + defaultMessage: 'Data view settings', })} onClick={() => { setPopoverOpen(!popoverOpen); @@ -663,7 +663,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ }} > {i18n.translate('xpack.lens.indexPatterns.addFieldButton', { - defaultMessage: 'Add field to index pattern', + defaultMessage: 'Add field to data view', })} , {i18n.translate('xpack.lens.indexPatterns.manageFieldButton', { - defaultMessage: 'Manage index pattern fields', + defaultMessage: 'Manage data view fields', })} , ]} @@ -709,7 +709,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ data-test-subj="lnsIndexPatternFieldSearch" placeholder={i18n.translate('xpack.lens.indexPatterns.filterByNameLabel', { defaultMessage: 'Search field names', - description: 'Search the list of fields in the index pattern for the provided text', + description: 'Search the list of fields in the data view for the provided text', })} value={localState.nameFilter} onChange={(e) => { @@ -717,7 +717,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ }} aria-label={i18n.translate('xpack.lens.indexPatterns.filterByNameLabel', { defaultMessage: 'Search field names', - description: 'Search the list of fields in the index pattern for the provided text', + description: 'Search the list of fields in the data view for the provided text', })} aria-describedby={fieldSearchDescriptionId} /> diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx index a39f3705fd230..dc6dc6dc31c86 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx @@ -217,7 +217,7 @@ export function getErrorMessage( } if (fieldInvalid) { return i18n.translate('xpack.lens.indexPattern.invalidFieldLabel', { - defaultMessage: 'Invalid field. Check your index pattern or pick another field.', + defaultMessage: 'Invalid field. Check your data view or pick another field.', }); } } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx index 9c22ec9d4bb05..ee6065aabf9d1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx @@ -348,7 +348,7 @@ function FieldPanelHeader({ @@ -366,7 +366,7 @@ function FieldPanelHeader({ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx index 2138b06a4c344..c408d0130825b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx @@ -98,8 +98,8 @@ export function getIndexPatternDatasource({ const uiSettings = core.uiSettings; const onIndexPatternLoadError = (err: Error) => core.notifications.toasts.addError(err, { - title: i18n.translate('xpack.lens.indexPattern.indexPatternLoadError', { - defaultMessage: 'Error loading index pattern', + title: i18n.translate('xpack.lens.indexPattern.dataViewLoadError', { + defaultMessage: 'Error loading data view', }), }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx index 12536e556f306..28f2921ccc771 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx @@ -23,8 +23,8 @@ export function LayerPanel({ state, layerId, onChangeIndexPattern }: IndexPatter const indexPattern = state.indexPatterns[layer.indexPatternId]; - const notFoundTitleLabel = i18n.translate('xpack.lens.layerPanel.missingIndexPattern', { - defaultMessage: 'Index pattern not found', + const notFoundTitleLabel = i18n.translate('xpack.lens.layerPanel.missingDataView', { + defaultMessage: 'Data view not found', }); return ( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.test.tsx index 69dc150922b4a..635c06691a733 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.test.tsx @@ -16,7 +16,7 @@ describe('NoFieldCallout', () => { `); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.tsx index 6b434e8cd41a6..073b21c700ccc 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.tsx @@ -32,7 +32,7 @@ export const NoFieldsCallout = ({ size="s" color="warning" title={i18n.translate('xpack.lens.indexPatterns.noFieldsLabel', { - defaultMessage: 'No fields exist in this index pattern.', + defaultMessage: 'No fields exist in this data view.', })} /> ); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx index 77af42ab41888..d0dd8a438ed1c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx @@ -343,7 +343,7 @@ describe('last_value', () => { 'data' ); expect(disabledStatus).toEqual( - 'This function requires the presence of a date field in your index' + 'This function requires the presence of a date field in your data view' ); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx index 88c9d82092e21..9a3ba9a044148 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx @@ -134,7 +134,7 @@ export const lastValueOperation: OperationDefinition @@ -284,7 +284,7 @@ export const lastValueOperation: OperationDefinition) { const field = indexPattern.fields.find((f) => f.name === fieldName); if (!field) { - throw new Error(`Field {fieldName} not found in index pattern ${indexPattern.title}`); + throw new Error(`Field {fieldName} not found in data view ${indexPattern.title}`); } const filter = timeFieldName diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 1b83bcac5837f..c2d46fa5762d2 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -238,8 +238,6 @@ "xpack.lens.editorFrame.expressionMissingDatasource": "ビジュアライゼーションのデータソースが見つかりませんでした", "xpack.lens.editorFrame.expressionMissingVisualizationType": "ビジュアライゼーションタイプが見つかりません。", "xpack.lens.editorFrame.goToForums": "リクエストとフィードバック", - "xpack.lens.editorFrame.indexPatternNotFound": "インデックスパターンが見つかりませんでした", - "xpack.lens.editorFrame.indexPatternReconfigure": "インデックスパターン管理ページで再作成", "xpack.lens.editorFrame.invisibleIndicatorLabel": "このディメンションは現在グラフに表示されません", "xpack.lens.editorFrame.networkErrorMessage": "ネットワークエラーです。しばらくたってから再試行するか、管理者に連絡してください。", "xpack.lens.editorFrame.noColorIndicatorLabel": "このディメンションには個別の色がありません", @@ -366,7 +364,6 @@ "xpack.lens.indexPattern.cardinality": "ユニークカウント", "xpack.lens.indexPattern.cardinality.signature": "フィールド:文字列", "xpack.lens.indexPattern.cardinalityOf": "{name} のユニークカウント", - "xpack.lens.indexPattern.changeIndexPatternTitle": "インデックスパターン", "xpack.lens.indexPattern.chooseField": "フィールドを選択", "xpack.lens.indexPattern.chooseFieldLabel": "この関数を使用するには、フィールドを選択してください。", "xpack.lens.indexPattern.chooseSubFunction": "サブ関数を選択", @@ -406,7 +403,6 @@ "xpack.lens.indexPattern.derivative": "差異", "xpack.lens.indexPattern.derivativeOf": "{name} の差異", "xpack.lens.indexPattern.differences.signature": "メトリック:数値", - "xpack.lens.indexPattern.editFieldLabel": "インデックスパターンフィールドを編集", "xpack.lens.indexPattern.emptyDimensionButton": "空のディメンション", "xpack.lens.indexPattern.emptyFieldsLabel": "空のフィールド", "xpack.lens.indexPattern.emptyFieldsLabelHelp": "空のフィールドには、フィルターに基づく最初の 500 件のドキュメントの値が含まれていませんでした。", @@ -467,15 +463,12 @@ "xpack.lens.indexPattern.functionsLabel": "関数を選択", "xpack.lens.indexPattern.groupByDropdown": "グループ分けの条件", "xpack.lens.indexPattern.incompleteOperation": "(未完了)", - "xpack.lens.indexPattern.indexPatternLoadError": "インデックスパターンの読み込み中にエラーが発生", "xpack.lens.indexPattern.intervals": "間隔", - "xpack.lens.indexPattern.invalidFieldLabel": "無効なフィールドです。インデックスパターンを確認するか、別のフィールドを選択してください。", "xpack.lens.indexPattern.invalidInterval": "無効な間隔値", "xpack.lens.indexPattern.invalidOperationLabel": "選択した関数はこのフィールドで動作しません。", "xpack.lens.indexPattern.invalidReferenceConfiguration": "ディメンション\"{dimensionLabel}\"の構成が正しくありません", "xpack.lens.indexPattern.invalidTimeShift": "無効な時間シフトです。正の整数の後に単位s、m、h、d、w、M、yのいずれかを入力します。例:3時間は3hです", "xpack.lens.indexPattern.lastValue": "最終値", - "xpack.lens.indexPattern.lastValue.disabled": "この関数には、インデックスの日付フィールドが必要です", "xpack.lens.indexPattern.lastValue.invalidTypeSortField": "フィールド {invalidField} は日付フィールドではないため、並べ替えで使用できません", "xpack.lens.indexPattern.lastValue.signature": "フィールド:文字列", "xpack.lens.indexPattern.lastValue.sortField": "日付フィールドで並べ替え", @@ -511,8 +504,6 @@ "xpack.lens.indexPattern.movingAverage.windowLimitations": "ウィンドウには現在の値が含まれません。", "xpack.lens.indexPattern.movingAverageOf": "{name} の移動平均", "xpack.lens.indexPattern.multipleDateHistogramsError": "\"{dimensionLabel}\"は唯一の日付ヒストグラムではありません。時間シフトを使用するときには、1つの日付ヒストグラムのみを使用していることを確認してください。", - "xpack.lens.indexPattern.noPatternsDescription": "インデックスパターンを作成するか、別のデータソースに切り替えてください", - "xpack.lens.indexPattern.noPatternsLabel": "インデックスパターンがありません", "xpack.lens.indexPattern.numberFormatLabel": "数字", "xpack.lens.indexPattern.ofDocumentsLabel": "ドキュメント", "xpack.lens.indexPattern.otherDocsLabel": "その他", @@ -556,7 +547,6 @@ "xpack.lens.indexPattern.referenceFunctionPlaceholder": "サブ関数", "xpack.lens.indexPattern.removeColumnAriaLabel": "フィールドを追加するか、{groupLabel}までドラッグアンドドロップします", "xpack.lens.indexPattern.removeColumnLabel": "「{groupLabel}」から構成を削除", - "xpack.lens.indexPattern.removeFieldLabel": "インデックスパターンを削除", "xpack.lens.indexPattern.sortField.invalid": "無効なフィールドです。インデックスパターンを確認するか、別のフィールドを選択してください。", "xpack.lens.indexpattern.suggestions.nestingChangeLabel": "各 {outerOperation} の {innerOperation}", "xpack.lens.indexpattern.suggestions.overallLabel": "全体の {operation}", @@ -602,12 +592,8 @@ "xpack.lens.indexPattern.timeShiftSmallWarning": "{label}は{columnTimeShift}の時間シフトを使用しています。これは{interval}の日付ヒストグラム間隔よりも小さいです。不一致のデータを防止するには、時間シフトとして{interval}を使用します。", "xpack.lens.indexPattern.uniqueLabel": "{label} [{num}]", "xpack.lens.indexPattern.useAsTopLevelAgg": "最初にこのフィールドでグループ化", - "xpack.lens.indexPatterns.actionsPopoverLabel": "インデックスパターン設定", - "xpack.lens.indexPatterns.addFieldButton": "フィールドをインデックスパターンに追加", "xpack.lens.indexPatterns.clearFiltersLabel": "名前とタイプフィルターを消去", "xpack.lens.indexPatterns.fieldFiltersLabel": "タイプでフィルタリング", - "xpack.lens.indexPatterns.filterByNameLabel": "検索フィールド名", - "xpack.lens.indexPatterns.manageFieldButton": "インデックスパターンを管理", "xpack.lens.indexPatterns.noAvailableDataLabel": "データを含むフィールドはありません。", "xpack.lens.indexPatterns.noDataLabel": "フィールドがありません。", "xpack.lens.indexPatterns.noEmptyDataLabel": "空のフィールドがありません。", @@ -615,14 +601,12 @@ "xpack.lens.indexPatterns.noFields.fieldTypeFilterBullet": "別のフィールドフィルターを使用", "xpack.lens.indexPatterns.noFields.globalFiltersBullet": "グローバルフィルターを変更", "xpack.lens.indexPatterns.noFields.tryText": "試行対象:", - "xpack.lens.indexPatterns.noFieldsLabel": "このインデックスパターンにはフィールドがありません。", "xpack.lens.indexPatterns.noFilteredFieldsLabel": "選択したフィルターと一致するフィールドはありません。", "xpack.lens.indexPatterns.noMetaDataLabel": "メタフィールドがありません。", "xpack.lens.indexPatternSuggestion.removeLayerLabel": "{indexPatternTitle}のみを表示", "xpack.lens.indexPatternSuggestion.removeLayerPositionLabel": "レイヤー{layerNumber}のみを表示", "xpack.lens.labelInput.label": "ラベル", "xpack.lens.layerPanel.layerVisualizationType": "レイヤービジュアライゼーションタイプ", - "xpack.lens.layerPanel.missingIndexPattern": "インデックスパターンが見つかりませんでした", "xpack.lens.lensSavedObjectLabel": "レンズビジュアライゼーション", "xpack.lens.metric.addLayer": "ビジュアライゼーションレイヤーを追加", "xpack.lens.metric.groupLabel": "表形式の値と単一の値", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c29557eebd3f8..e3f53a34449ef 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -241,11 +241,8 @@ "xpack.lens.editorFrame.expressionFailureMessage": "请求错误:{type},{reason}", "xpack.lens.editorFrame.expressionFailureMessageWithContext": "请求错误:{type},{context} 中的 {reason}", "xpack.lens.editorFrame.expressionMissingDatasource": "无法找到可视化的数据源", - "xpack.lens.editorFrame.expressionMissingIndexPattern": "找不到{count, plural, other {索引模式}}:{ids}", "xpack.lens.editorFrame.expressionMissingVisualizationType": "找不到可视化类型。", "xpack.lens.editorFrame.goToForums": "提出请求并提供反馈", - "xpack.lens.editorFrame.indexPatternNotFound": "未找到索引模式", - "xpack.lens.editorFrame.indexPatternReconfigure": "在索引模式管理页面中重新创建", "xpack.lens.editorFrame.invisibleIndicatorLabel": "此维度当前在图表中不可见", "xpack.lens.editorFrame.networkErrorMessage": "网络错误,请稍后重试或联系管理员。", "xpack.lens.editorFrame.noColorIndicatorLabel": "此维度没有单独的颜色", @@ -374,7 +371,6 @@ "xpack.lens.indexPattern.cardinality": "唯一计数", "xpack.lens.indexPattern.cardinality.signature": "field: string", "xpack.lens.indexPattern.cardinalityOf": "{name} 的唯一计数", - "xpack.lens.indexPattern.changeIndexPatternTitle": "索引模式", "xpack.lens.indexPattern.chooseField": "选择字段", "xpack.lens.indexPattern.chooseFieldLabel": "要使用此函数,请选择字段。", "xpack.lens.indexPattern.chooseSubFunction": "选择子函数", @@ -414,7 +410,6 @@ "xpack.lens.indexPattern.derivative": "差异", "xpack.lens.indexPattern.derivativeOf": "{name} 的差异", "xpack.lens.indexPattern.differences.signature": "指标:数字", - "xpack.lens.indexPattern.editFieldLabel": "编辑索引模式字段", "xpack.lens.indexPattern.emptyDimensionButton": "空维度", "xpack.lens.indexPattern.emptyFieldsLabel": "空字段", "xpack.lens.indexPattern.emptyFieldsLabelHelp": "空字段在基于您的筛选的前 500 个文档中不包含任何值。", @@ -476,15 +471,12 @@ "xpack.lens.indexPattern.functionsLabel": "选择函数", "xpack.lens.indexPattern.groupByDropdown": "分组依据", "xpack.lens.indexPattern.incompleteOperation": "(不完整)", - "xpack.lens.indexPattern.indexPatternLoadError": "加载索引模式时出错", "xpack.lens.indexPattern.intervals": "时间间隔", - "xpack.lens.indexPattern.invalidFieldLabel": "字段无效。检查索引模式或选取其他字段。", "xpack.lens.indexPattern.invalidInterval": "时间间隔值无效", "xpack.lens.indexPattern.invalidOperationLabel": "此字段不适用于选定函数。", "xpack.lens.indexPattern.invalidReferenceConfiguration": "维度“{dimensionLabel}”配置不正确", "xpack.lens.indexPattern.invalidTimeShift": "时间偏移无效。输入正整数数量,后跟以下单位之一:s、m、h、d、w、M、y。例如,3h 表示 3 小时", "xpack.lens.indexPattern.lastValue": "最后值", - "xpack.lens.indexPattern.lastValue.disabled": "此功能要求索引中存在日期字段", "xpack.lens.indexPattern.lastValue.invalidTypeSortField": "字段 {invalidField} 不是日期字段,不能用于排序", "xpack.lens.indexPattern.lastValue.signature": "field: string", "xpack.lens.indexPattern.lastValue.sortField": "按日期字段排序", @@ -504,7 +496,6 @@ "xpack.lens.indexPattern.min.description": "单值指标聚合,返回从聚合文档提取的数值中的最小值。", "xpack.lens.indexPattern.minOf": "{name} 的最小值", "xpack.lens.indexPattern.missingFieldLabel": "缺失字段", - "xpack.lens.indexPattern.missingIndexPattern": "找不到{count, plural, other {索引模式}} ({count, plural, other {id}}:{indexpatterns})", "xpack.lens.indexPattern.missingReferenceError": "“{dimensionLabel}”配置不完整", "xpack.lens.indexPattern.moveToWorkspace": "将 {field} 添加到工作区", "xpack.lens.indexPattern.moveToWorkspaceDisabled": "此字段无法自动添加到工作区。您仍可以在配置面板中直接使用它。", @@ -521,8 +512,6 @@ "xpack.lens.indexPattern.movingAverage.windowLimitations": "时间窗不包括当前值。", "xpack.lens.indexPattern.movingAverageOf": "{name} 的移动平均值", "xpack.lens.indexPattern.multipleDateHistogramsError": "“{dimensionLabel}”不是唯一的 Date Histogram。使用时间偏移时,请确保仅使用一个 Date Histogram。", - "xpack.lens.indexPattern.noPatternsDescription": "请创建索引模式或切换到其他数据源", - "xpack.lens.indexPattern.noPatternsLabel": "无索引模式", "xpack.lens.indexPattern.numberFormatLabel": "数字", "xpack.lens.indexPattern.ofDocumentsLabel": "文档", "xpack.lens.indexPattern.operationsNotFound": "未找到{operationLength, plural, other {运算}} {operationsList}", @@ -567,7 +556,6 @@ "xpack.lens.indexPattern.referenceFunctionPlaceholder": "子函数", "xpack.lens.indexPattern.removeColumnAriaLabel": "将字段添加或拖放到 {groupLabel}", "xpack.lens.indexPattern.removeColumnLabel": "从“{groupLabel}”中删除配置", - "xpack.lens.indexPattern.removeFieldLabel": "移除索引模式字段", "xpack.lens.indexPattern.sortField.invalid": "字段无效。检查索引模式或选取其他字段。", "xpack.lens.indexpattern.suggestions.nestingChangeLabel": "每个 {outerOperation} 的 {innerOperation}", "xpack.lens.indexpattern.suggestions.overallLabel": "总体 {operation}", @@ -613,13 +601,9 @@ "xpack.lens.indexPattern.timeShiftSmallWarning": "{label} 使用的时间偏移 {columnTimeShift} 小于 Date Histogram 时间间隔 {interval} 。要防止数据不匹配,请使用 {interval} 的倍数作为时间偏移。", "xpack.lens.indexPattern.uniqueLabel": "{label} [{num}]", "xpack.lens.indexPattern.useAsTopLevelAgg": "先按此字段分组", - "xpack.lens.indexPatterns.actionsPopoverLabel": "索引模式设置", - "xpack.lens.indexPatterns.addFieldButton": "将字段添加到索引模式", "xpack.lens.indexPatterns.clearFiltersLabel": "清除名称和类型筛选", "xpack.lens.indexPatterns.fieldFiltersLabel": "按类型筛选", "xpack.lens.indexPatterns.fieldSearchLiveRegion": "{availableFields} 个可用{availableFields, plural, other {字段}}。{emptyFields} 个空{emptyFields, plural, other {字段}}。{metaFields} 个元{metaFields, plural,other {字段}}。", - "xpack.lens.indexPatterns.filterByNameLabel": "搜索字段名称", - "xpack.lens.indexPatterns.manageFieldButton": "管理索引模式字段", "xpack.lens.indexPatterns.noAvailableDataLabel": "没有包含数据的可用字段。", "xpack.lens.indexPatterns.noDataLabel": "无字段。", "xpack.lens.indexPatterns.noEmptyDataLabel": "无空字段。", @@ -627,14 +611,12 @@ "xpack.lens.indexPatterns.noFields.fieldTypeFilterBullet": "使用不同的字段筛选", "xpack.lens.indexPatterns.noFields.globalFiltersBullet": "更改全局筛选", "xpack.lens.indexPatterns.noFields.tryText": "尝试:", - "xpack.lens.indexPatterns.noFieldsLabel": "在此索引模式中不存在任何字段。", "xpack.lens.indexPatterns.noFilteredFieldsLabel": "没有字段匹配选定筛选。", "xpack.lens.indexPatterns.noMetaDataLabel": "无元字段。", "xpack.lens.indexPatternSuggestion.removeLayerLabel": "仅显示 {indexPatternTitle}", "xpack.lens.indexPatternSuggestion.removeLayerPositionLabel": "仅显示图层 {layerNumber}", "xpack.lens.labelInput.label": "标签", "xpack.lens.layerPanel.layerVisualizationType": "图层可视化类型", - "xpack.lens.layerPanel.missingIndexPattern": "未找到索引模式", "xpack.lens.lensSavedObjectLabel": "Lens 可视化", "xpack.lens.metric.addLayer": "添加可视化图层", "xpack.lens.metric.groupLabel": "表和单值", From 9b7b3228ecc8050a021d2d0b1c5d8b5952e00871 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 4 Oct 2021 12:55:29 +0300 Subject: [PATCH 25/98] [TSVB] Removes less support from markdown editor (#110985) * Remove less from markdown * Fix migration script * Fix migration script * fix lint * Fix test * Fix comments * Fix lint * Fix comments * Fix yarn.lock file Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/user/dashboard/tsvb.asciidoc | 2 +- package.json | 1 - .../components/panel_config/markdown.tsx | 29 +-- .../components/vis_types/markdown/vis.js | 38 ++-- .../visualize_embeddable_factory.ts | 9 + .../visualization_common_migrations.ts | 29 +++ ...ualization_saved_object_migrations.test.ts | 32 +++ .../visualization_saved_object_migrations.ts | 25 +++ .../api_integration/apis/maps/migrations.js | 2 +- yarn.lock | 185 +----------------- 10 files changed, 123 insertions(+), 229 deletions(-) diff --git a/docs/user/dashboard/tsvb.asciidoc b/docs/user/dashboard/tsvb.asciidoc index 80138990c4f6e..0537677ee3ad9 100644 --- a/docs/user/dashboard/tsvb.asciidoc +++ b/docs/user/dashboard/tsvb.asciidoc @@ -122,7 +122,7 @@ To change this behavior, click *Panel options*, then specify a URL in the *Item [[tsvb-markdown]] ===== Markdown -The *Markdown* visualization supports Markdown with Handlebar (mustache) syntax to insert dynamic data, and supports custom CSS using the LESS syntax. +The *Markdown* visualization supports Markdown with Handlebar (mustache) syntax to insert dynamic data, and supports custom CSS. [float] [[tsvb-function-reference]] diff --git a/package.json b/package.json index c12e5ca9f060e..ac30b5de6f486 100644 --- a/package.json +++ b/package.json @@ -275,7 +275,6 @@ "jsonwebtoken": "^8.5.1", "jsts": "^1.6.2", "kea": "^2.4.2", - "less": "npm:@elastic/less@2.7.3-kibana", "load-json-file": "^6.2.0", "loader-utils": "^1.2.3", "lodash": "^4.17.21", diff --git a/src/plugins/vis_types/timeseries/public/application/components/panel_config/markdown.tsx b/src/plugins/vis_types/timeseries/public/application/components/panel_config/markdown.tsx index b099209af4348..c5d412f823d0f 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/panel_config/markdown.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/panel_config/markdown.tsx @@ -21,12 +21,8 @@ import { EuiTitle, EuiHorizontalRule, } from '@elastic/eui'; -// @ts-expect-error -import less from 'less/lib/less-browser'; -import 'brace/mode/less'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import type { Writable } from '@kbn/utility-types'; // @ts-expect-error not typed yet import { SeriesEditor } from '../series_editor'; @@ -41,11 +37,8 @@ import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { VisDataContext } from '../../contexts/vis_data_context'; import { PanelConfigProps, PANEL_CONFIG_TABS } from './types'; -import { TimeseriesVisParams } from '../../../types'; import { CodeEditor, CssLang } from '../../../../../../kibana_react/public'; -const lessC = less(window, { env: 'production' }); - export class MarkdownPanelConfig extends Component< PanelConfigProps, { selectedTab: PANEL_CONFIG_TABS } @@ -61,21 +54,7 @@ export class MarkdownPanelConfig extends Component< } handleCSSChange(value: string) { - const { model } = this.props; - const lessSrc = `#markdown-${model.id} {${value}}`; - lessC.render( - lessSrc, - { compress: true, javascriptEnabled: false }, - (e: unknown, output: any) => { - const parts: Writable> = { - markdown_less: value, - }; - if (output) { - parts.markdown_css = output.css; - } - this.props.onChange(parts); - } - ); + this.props.onChange({ markdown_css: value }); } render() { @@ -275,8 +254,8 @@ export class MarkdownPanelConfig extends Component< @@ -285,7 +264,7 @@ export class MarkdownPanelConfig extends Component< height="500px" languageId={CssLang.ID} options={{ fontSize: 14 }} - value={model.markdown_less ?? ''} + value={model.markdown_css ?? ''} onChange={this.handleCSSChange} /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/markdown/vis.js b/src/plugins/vis_types/timeseries/public/application/components/vis_types/markdown/vis.js index 49fdbcd98501c..17a293627b314 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/markdown/vis.js +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/markdown/vis.js @@ -9,8 +9,8 @@ import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; -import uuid from 'uuid'; import { get } from 'lodash'; +import { ClassNames } from '@emotion/react'; import { Markdown } from '../../../../../../../../plugins/kibana_react/public'; import { ErrorComponent } from '../../error'; @@ -18,19 +18,15 @@ import { replaceVars } from '../../lib/replace_vars'; import { convertSeriesToVars } from '../../lib/convert_series_to_vars'; import { isBackgroundInverted } from '../../../lib/set_is_reversed'; -const getMarkdownId = (id) => `markdown-${id}`; - function MarkdownVisualization(props) { const { backgroundColor, model, visData, getConfig, fieldFormatMap } = props; const series = get(visData, `${model.id}.series`, []); const variables = convertSeriesToVars(series, model, getConfig, fieldFormatMap); - const markdownElementId = getMarkdownId(uuid.v1()); const panelBackgroundColor = model.background_color || backgroundColor; const style = { backgroundColor: panelBackgroundColor }; let markdown; - let markdownCss = ''; if (model.markdown) { const markdownSource = replaceVars( @@ -42,13 +38,6 @@ function MarkdownVisualization(props) { } ); - if (model.markdown_css) { - markdownCss = model.markdown_css.replace( - new RegExp(getMarkdownId(model.id), 'g'), - markdownElementId - ); - } - const markdownClasses = classNames('kbnMarkdown__body', { 'kbnMarkdown__body--reversed': isBackgroundInverted(panelBackgroundColor), }); @@ -65,17 +54,20 @@ function MarkdownVisualization(props) { markdown = (
    {markdownError && } - -
    -
    - {!markdownError && ( - - )} -
    -
    + + {({ css, cx }) => ( +
    +
    + {!markdownError && ( + + )} +
    +
    + )} +
    ); } diff --git a/src/plugins/visualizations/server/embeddable/visualize_embeddable_factory.ts b/src/plugins/visualizations/server/embeddable/visualize_embeddable_factory.ts index 43a8ab3d507d8..f9fa2a09c47e9 100644 --- a/src/plugins/visualizations/server/embeddable/visualize_embeddable_factory.ts +++ b/src/plugins/visualizations/server/embeddable/visualize_embeddable_factory.ts @@ -17,6 +17,7 @@ import { commonAddEmptyValueColorRule, commonMigrateTagCloud, commonAddDropLastBucketIntoTSVBModel, + commonRemoveMarkdownLessFromTSVB, } from '../migrations/visualization_common_migrations'; const byValueAddSupportOfDualIndexSelectionModeInTSVB = (state: SerializableRecord) => { @@ -68,6 +69,13 @@ const byValueMigrateTagcloud = (state: SerializableRecord) => { }; }; +const byValueRemoveMarkdownLessFromTSVB = (state: SerializableRecord) => { + return { + ...state, + savedVis: commonRemoveMarkdownLessFromTSVB(state.savedVis), + }; +}; + export const visualizeEmbeddableFactory = (): EmbeddableRegistryDefinition => { return { id: 'visualization', @@ -86,6 +94,7 @@ export const visualizeEmbeddableFactory = (): EmbeddableRegistryDefinition => { byValueMigrateTagcloud, byValueAddDropLastBucketIntoTSVBModel )(state), + '8.0.0': (state) => flow(byValueRemoveMarkdownLessFromTSVB)(state), }, }; }; diff --git a/src/plugins/visualizations/server/migrations/visualization_common_migrations.ts b/src/plugins/visualizations/server/migrations/visualization_common_migrations.ts index 2503ac2c54b12..34bae3f279f97 100644 --- a/src/plugins/visualizations/server/migrations/visualization_common_migrations.ts +++ b/src/plugins/visualizations/server/migrations/visualization_common_migrations.ts @@ -157,3 +157,32 @@ export const commonMigrateTagCloud = (visState: any) => { return visState; }; + +export const commonRemoveMarkdownLessFromTSVB = (visState: any) => { + if (visState && visState.type === 'metrics') { + const params: any = get(visState, 'params') || {}; + + if (params.type === 'markdown') { + // remove less + if (params.markdown_less) { + delete params.markdown_less; + } + + // remove markdown id from css + if (params.markdown_css) { + params.markdown_css = params.markdown_css + .replace(new RegExp(`#markdown-${params.id}`, 'g'), '') + .trim(); + } + } + + return { + ...visState, + params: { + ...params, + }, + }; + } + + return visState; +}; diff --git a/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.test.ts b/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.test.ts index d9801b8a59504..1ef9018f3472b 100644 --- a/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.test.ts +++ b/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.test.ts @@ -2312,4 +2312,36 @@ describe('migration visualization', () => { expect(palette.name).toEqual('default'); }); }); + + describe('8.0.0 removeMarkdownLessFromTSVB', () => { + const migrate = (doc: any) => + visualizationSavedObjectTypeMigrations['8.0.0']( + doc as Parameters[0], + savedObjectMigrationContext + ); + const getTestDoc = () => ({ + attributes: { + title: 'My Vis', + description: 'This is my super cool vis.', + visState: JSON.stringify({ + type: 'metrics', + title: '[Flights] Delay Type', + params: { + id: 'test1', + type: 'markdown', + markdwon_less: 'test { color: red }', + markdown_css: '#markdown-test1 test { color: red }', + }, + }), + }, + }); + + it('should remove markdown_less and id from markdown_css', () => { + const migratedTestDoc = migrate(getTestDoc()); + const params = JSON.parse(migratedTestDoc.attributes.visState).params; + + expect(params.mardwon_less).toBeUndefined(); + expect(params.markdown_css).toEqual('test { color: red }'); + }); + }); }); diff --git a/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts b/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts index fd08ecd748668..b598d34943e6c 100644 --- a/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts +++ b/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts @@ -19,6 +19,7 @@ import { commonAddEmptyValueColorRule, commonMigrateTagCloud, commonAddDropLastBucketIntoTSVBModel, + commonRemoveMarkdownLessFromTSVB, } from './visualization_common_migrations'; const migrateIndexPattern: SavedObjectMigrationFn = (doc) => { @@ -1068,6 +1069,29 @@ export const replaceIndexPatternReference: SavedObjectMigrationFn = (d : doc.references, }); +export const removeMarkdownLessFromTSVB: SavedObjectMigrationFn = (doc) => { + const visStateJSON = get(doc, 'attributes.visState'); + let visState; + + if (visStateJSON) { + try { + visState = JSON.parse(visStateJSON); + } catch (e) { + // Let it go, the data is invalid and we'll leave it as is + } + + const newVisState = commonRemoveMarkdownLessFromTSVB(visState); + return { + ...doc, + attributes: { + ...doc.attributes, + visState: JSON.stringify(newVisState), + }, + }; + } + return doc; +}; + export const visualizationSavedObjectTypeMigrations = { /** * We need to have this migration twice, once with a version prior to 7.0.0 once with a version @@ -1121,4 +1145,5 @@ export const visualizationSavedObjectTypeMigrations = { replaceIndexPatternReference, addDropLastBucketIntoTSVBModel ), + '8.0.0': flow(removeMarkdownLessFromTSVB), }; diff --git a/x-pack/test/api_integration/apis/maps/migrations.js b/x-pack/test/api_integration/apis/maps/migrations.js index 37dc9c32958ff..47747467ae550 100644 --- a/x-pack/test/api_integration/apis/maps/migrations.js +++ b/x-pack/test/api_integration/apis/maps/migrations.js @@ -76,7 +76,7 @@ export default function ({ getService }) { } expect(panels.length).to.be(1); expect(panels[0].type).to.be('map'); - expect(panels[0].version).to.be('7.16.0'); + expect(panels[0].version).to.be('8.0.0'); }); }); }); diff --git a/yarn.lock b/yarn.lock index 6d491e4b8ba49..14cf34cae847b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7780,14 +7780,6 @@ ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.5.5: version "6.12.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" @@ -8402,11 +8394,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ= - assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" @@ -8627,21 +8614,11 @@ available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2: dependencies: array-filter "^1.0.0" -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8= - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= -aws4@^1.2.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" @@ -9438,13 +9415,6 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8= - dependencies: - hoek "2.x.x" - bottleneck@^2.15.3: version "2.18.0" resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.18.0.tgz#41fa63ae185b65435d789d1700334bc48222dacf" @@ -10907,7 +10877,7 @@ combine-source-map@^0.8.0, combine-source-map@~0.8.0: lodash.memoize "~3.0.3" source-map "~0.5.3" -combined-stream@^1.0.5, combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.5, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -11518,13 +11488,6 @@ crypt@~0.0.1: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g= - dependencies: - boom "2.x.x" - crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -13696,7 +13659,7 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -errno@^0.1.1, errno@^0.1.3, errno@~0.1.7: +errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== @@ -14603,7 +14566,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@~3.0.0, extend@~3.0.2: +extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -15316,15 +15279,6 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE= - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -16329,24 +16283,11 @@ handlebars@4.7.7, handlebars@^4.7.7: optionalDependencies: uglify-js "^3.1.4" -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - integrity sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4= - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - integrity sha1-M0gdDxu/9gDdID11gSpqX7oALio= - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - har-validator@~5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" @@ -16625,16 +16566,6 @@ hat@0.0.3: resolved "https://registry.yarnpkg.com/hat/-/hat-0.0.3.tgz#bb014a9e64b3788aed8005917413d4ff3d502d8a" integrity sha1-uwFKnmSzeIrtgAWRdBPU/z1QLYo= -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ= - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - hdr-histogram-js@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/hdr-histogram-js/-/hdr-histogram-js-1.2.0.tgz#1213c0b317f39b9c05bc4f208cb7931dbbc192ae" @@ -16694,11 +16625,6 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0= - hoist-non-react-statics@^2.3.1, 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.1, 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" @@ -16982,15 +16908,6 @@ http-proxy@^1.17.0, http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8= - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -17143,11 +17060,6 @@ image-size@^0.8.2: dependencies: queue "6.0.1" -image-size@~0.5.0: - version "0.5.5" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" - integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w= - immediate@~3.0.5: version "3.0.6" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" @@ -19545,20 +19457,6 @@ lead@^1.0.0: dependencies: flush-write-stream "^1.0.2" -"less@npm:@elastic/less@2.7.3-kibana": - version "2.7.3-kibana" - resolved "https://registry.yarnpkg.com/@elastic/less/-/less-2.7.3-kibana.tgz#3de5e0b06bb095b1cc1149043d67f8dc36272d23" - integrity sha512-Okm31ZKE28/m3bH0h0mNpQH0zqVWNFqRKDlsBd1AYHGdM1yBq4mzeO6IRUykB81XDGlqL0m4ThSA7mc3hy+LVg== - optionalDependencies: - errno "^0.1.1" - graceful-fs "^4.1.2" - image-size "~0.5.0" - mime "^1.2.11" - mkdirp "^0.5.0" - promise "^7.1.1" - request "2.81.0" - source-map "^0.5.3" - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -20746,11 +20644,6 @@ mime-db@1.44.0, mime-db@1.x.x, "mime-db@>= 1.40.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -mime-db@1.45.0: - version "1.45.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" - integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== - mime-db@^1.28.0: version "1.49.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" @@ -20763,14 +20656,7 @@ mime-types@^2.0.1, mime-types@^2.1.12, mime-types@^2.1.26, mime-types@^2.1.27, m dependencies: mime-db "1.44.0" -mime-types@~2.1.7: - version "2.1.28" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" - integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== - dependencies: - mime-db "1.45.0" - -mime@1.6.0, mime@^1.2.11, mime@^1.3.4, mime@^1.4.1: +mime@1.6.0, mime@^1.3.4, mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -21935,11 +21821,6 @@ nyc@^15.0.1: test-exclude "^6.0.0" yargs "^15.0.2" -oauth-sign@~0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" @@ -24027,7 +23908,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: +punycode@^1.2.4, punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -24109,11 +23990,6 @@ qs@^6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ== -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM= - qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -25757,34 +25633,6 @@ request-promise@^4.2.2: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - integrity sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA= - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - request@^2.44.0, request@^2.87.0, request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" @@ -26886,13 +26734,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^2.0.0" -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg= - dependencies: - hoek "2.x.x" - sockjs-client@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" @@ -27046,7 +26887,7 @@ source-map@^0.4.2: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -27675,11 +27516,6 @@ stringify-entities@^3.0.1: is-decimal "^1.0.2" is-hexadecimal "^1.0.0" -stringstream@~0.0.4: - version "0.0.6" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" - integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA== - strip-ansi@*, strip-ansi@5.2.0, strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -28824,13 +28660,6 @@ tough-cookie@^4.0.0: punycode "^2.1.1" universalify "^0.1.2" -tough-cookie@~2.3.0: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA== - dependencies: - punycode "^1.4.1" - tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" @@ -29904,7 +29733,7 @@ uuid@^2.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" integrity sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho= -uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0: +uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== From 8e25f5cc0fcb87abb73602176cb2f4723123b503 Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Mon, 4 Oct 2021 13:01:14 +0200 Subject: [PATCH 26/98] [Lens] Threshold: add padding to avoid axis label collision with threshold markers (#112952) * :bug: Add padding to the tick label to fit threshold markers * :bug: Better icon detection * :bug: Fix edge cases with no title or labels * :camera_flash: Update snapshots * :sparkles: Add icon placement flag * :sparkles: Sync padding computation with marker positioning * :ok_hand: Make disabled when no icon is selected * :bug: Fix some edge cases with auto positioning * Update x-pack/plugins/lens/public/xy_visualization/xy_config_panel/threshold_panel.tsx Co-authored-by: Michael Marcialis Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Michael Marcialis --- .../expressions/xy_chart/axis_config.ts | 7 + .../shared_components/tooltip_wrapper.tsx | 1 + .../__snapshots__/expression.test.tsx.snap | 35 +++++ .../public/xy_visualization/expression.tsx | 65 +++++++-- .../expression_thresholds.tsx | 131 +++++++++++++++++- .../public/xy_visualization/to_expression.ts | 1 + .../xy_config_panel/index.tsx | 2 +- .../xy_config_panel/threshold_panel.tsx | 115 ++++++++++++++- 8 files changed, 340 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/lens/common/expressions/xy_chart/axis_config.ts b/x-pack/plugins/lens/common/expressions/xy_chart/axis_config.ts index 29b0fb1352e5b..47bb1f91b4ab2 100644 --- a/x-pack/plugins/lens/common/expressions/xy_chart/axis_config.ts +++ b/x-pack/plugins/lens/common/expressions/xy_chart/axis_config.ts @@ -30,6 +30,7 @@ interface AxisConfig { export type YAxisMode = 'auto' | 'left' | 'right' | 'bottom'; export type LineStyle = 'solid' | 'dashed' | 'dotted'; export type FillStyle = 'none' | 'above' | 'below'; +export type IconPosition = 'auto' | 'left' | 'right' | 'above' | 'below'; export interface YConfig { forAccessor: string; @@ -39,6 +40,7 @@ export interface YConfig { lineWidth?: number; lineStyle?: LineStyle; fill?: FillStyle; + iconPosition?: IconPosition; } export type AxisTitlesVisibilityConfigResult = AxesSettingsConfig & { @@ -180,6 +182,11 @@ export const yAxisConfig: ExpressionFunctionDefinition< types: ['string'], help: 'An optional icon used for threshold lines', }, + iconPosition: { + types: ['string'], + options: ['auto', 'above', 'below', 'left', 'right'], + help: 'The placement of the icon for the threshold line', + }, fill: { types: ['string'], options: ['none', 'above', 'below'], diff --git a/x-pack/plugins/lens/public/shared_components/tooltip_wrapper.tsx b/x-pack/plugins/lens/public/shared_components/tooltip_wrapper.tsx index 0b361c8fa7f1e..5ab7800e05349 100644 --- a/x-pack/plugins/lens/public/shared_components/tooltip_wrapper.tsx +++ b/x-pack/plugins/lens/public/shared_components/tooltip_wrapper.tsx @@ -10,6 +10,7 @@ import { EuiToolTip, EuiToolTipProps } from '@elastic/eui'; export type TooltipWrapperProps = Partial> & { tooltipContent: string; + /** When the condition is truthy, the tooltip will be shown */ condition: boolean; }; diff --git a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/expression.test.tsx.snap b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/expression.test.tsx.snap index 6326d8680757e..fe3137c905ffb 100644 --- a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/expression.test.tsx.snap +++ b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/expression.test.tsx.snap @@ -28,6 +28,7 @@ exports[`xy_expression XYChart component it renders area 1`] = ` "color": undefined, }, "barSeriesStyle": Object {}, + "chartMargins": Object {}, "legend": Object { "labelOptions": Object { "maxLines": 0, @@ -55,9 +56,11 @@ exports[`xy_expression XYChart component it renders area 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": 0, "visible": true, }, @@ -86,9 +89,11 @@ exports[`xy_expression XYChart component it renders area 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": -90, "visible": false, }, @@ -252,6 +257,7 @@ exports[`xy_expression XYChart component it renders bar 1`] = ` "color": undefined, }, "barSeriesStyle": Object {}, + "chartMargins": Object {}, "legend": Object { "labelOptions": Object { "maxLines": 0, @@ -279,9 +285,11 @@ exports[`xy_expression XYChart component it renders bar 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": 0, "visible": true, }, @@ -310,9 +318,11 @@ exports[`xy_expression XYChart component it renders bar 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": -90, "visible": false, }, @@ -490,6 +500,7 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = ` "color": undefined, }, "barSeriesStyle": Object {}, + "chartMargins": Object {}, "legend": Object { "labelOptions": Object { "maxLines": 0, @@ -517,9 +528,11 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": 0, "visible": true, }, @@ -548,9 +561,11 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": -90, "visible": false, }, @@ -728,6 +743,7 @@ exports[`xy_expression XYChart component it renders line 1`] = ` "color": undefined, }, "barSeriesStyle": Object {}, + "chartMargins": Object {}, "legend": Object { "labelOptions": Object { "maxLines": 0, @@ -755,9 +771,11 @@ exports[`xy_expression XYChart component it renders line 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": 0, "visible": true, }, @@ -786,9 +804,11 @@ exports[`xy_expression XYChart component it renders line 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": -90, "visible": false, }, @@ -952,6 +972,7 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = ` "color": undefined, }, "barSeriesStyle": Object {}, + "chartMargins": Object {}, "legend": Object { "labelOptions": Object { "maxLines": 0, @@ -979,9 +1000,11 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": 0, "visible": true, }, @@ -1010,9 +1033,11 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": -90, "visible": false, }, @@ -1184,6 +1209,7 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = ` "color": undefined, }, "barSeriesStyle": Object {}, + "chartMargins": Object {}, "legend": Object { "labelOptions": Object { "maxLines": 0, @@ -1211,9 +1237,11 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": 0, "visible": true, }, @@ -1242,9 +1270,11 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = ` style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": -90, "visible": false, }, @@ -1430,6 +1460,7 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] = "color": undefined, }, "barSeriesStyle": Object {}, + "chartMargins": Object {}, "legend": Object { "labelOptions": Object { "maxLines": 0, @@ -1457,9 +1488,11 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] = style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": 0, "visible": true, }, @@ -1488,9 +1521,11 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] = style={ Object { "axisTitle": Object { + "padding": undefined, "visible": true, }, "tickLabel": Object { + "padding": undefined, "rotation": -90, "visible": false, }, diff --git a/x-pack/plugins/lens/public/xy_visualization/expression.tsx b/x-pack/plugins/lens/public/xy_visualization/expression.tsx index c4315b7ccea85..0cea52b5d3c9e 100644 --- a/x-pack/plugins/lens/public/xy_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/expression.tsx @@ -59,7 +59,11 @@ import { getAxesConfiguration, GroupsConfiguration, validateExtent } from './axe import { getColorAssignments } from './color_assignment'; import { getXDomain, XyEndzones } from './x_domain'; import { getLegendAction } from './get_legend_action'; -import { ThresholdAnnotations } from './expression_thresholds'; +import { + computeChartMargins, + getThresholdRequiredPaddings, + ThresholdAnnotations, +} from './expression_thresholds'; declare global { interface Window { @@ -314,6 +318,12 @@ export function XYChart({ Boolean(isHistogramViz) ); + const yAxesMap = { + left: yAxesConfiguration.find(({ groupId }) => groupId === 'left'), + right: yAxesConfiguration.find(({ groupId }) => groupId === 'right'), + }; + const thresholdPaddings = getThresholdRequiredPaddings(thresholdLayers, yAxesMap); + const getYAxesTitles = ( axisSeries: Array<{ layer: string; accessor: string }>, groupId: string @@ -330,23 +340,38 @@ export function XYChart({ ); }; - const getYAxesStyle = (groupId: string) => { + const getYAxesStyle = (groupId: 'left' | 'right') => { + const tickVisible = + groupId === 'right' + ? tickLabelsVisibilitySettings?.yRight + : tickLabelsVisibilitySettings?.yLeft; + const style = { tickLabel: { - visible: - groupId === 'right' - ? tickLabelsVisibilitySettings?.yRight - : tickLabelsVisibilitySettings?.yLeft, + visible: tickVisible, rotation: groupId === 'right' ? args.labelsOrientation?.yRight || 0 : args.labelsOrientation?.yLeft || 0, + padding: + thresholdPaddings[groupId] != null + ? { + inner: thresholdPaddings[groupId], + } + : undefined, }, axisTitle: { visible: groupId === 'right' ? axisTitlesVisibilitySettings?.yRight : axisTitlesVisibilitySettings?.yLeft, + // if labels are not visible add the padding to the title + padding: + !tickVisible && thresholdPaddings[groupId] != null + ? { + inner: thresholdPaddings[groupId], + } + : undefined, }, }; return style; @@ -510,6 +535,17 @@ export function XYChart({ legend: { labelOptions: { maxLines: legend.shouldTruncate ? legend?.maxLines ?? 1 : 0 }, }, + // if not title or labels are shown for axes, add some padding if required by threshold markers + chartMargins: { + ...chartTheme.chartPaddings, + ...computeChartMargins( + thresholdPaddings, + tickLabelsVisibilitySettings, + axisTitlesVisibilitySettings, + yAxesMap, + shouldRotate + ), + }, }} baseTheme={chartBaseTheme} tooltip={{ @@ -545,9 +581,15 @@ export function XYChart({ tickLabel: { visible: tickLabelsVisibilitySettings?.x, rotation: labelsOrientation?.x, + padding: + thresholdPaddings.bottom != null ? { inner: thresholdPaddings.bottom } : undefined, }, axisTitle: { visible: axisTitlesVisibilitySettings.x, + padding: + !tickLabelsVisibilitySettings?.x && thresholdPaddings.bottom != null + ? { inner: thresholdPaddings.bottom } + : undefined, }, }} /> @@ -568,7 +610,7 @@ export function XYChart({ }} hide={filteredLayers[0].hide} tickFormat={(d) => axis.formatter?.convert(d) || ''} - style={getYAxesStyle(axis.groupId)} + style={getYAxesStyle(axis.groupId as 'left' | 'right')} domain={getYAxisDomain(axis)} /> ); @@ -839,10 +881,15 @@ export function XYChart({ syncColors={syncColors} paletteService={paletteService} formatters={{ - left: yAxesConfiguration.find(({ groupId }) => groupId === 'left')?.formatter, - right: yAxesConfiguration.find(({ groupId }) => groupId === 'right')?.formatter, + left: yAxesMap.left?.formatter, + right: yAxesMap.right?.formatter, bottom: xAxisFormatter, }} + axesMap={{ + left: Boolean(yAxesMap.left), + right: Boolean(yAxesMap.right), + }} + isHorizontal={shouldRotate} /> ) : null} diff --git a/x-pack/plugins/lens/public/xy_visualization/expression_thresholds.tsx b/x-pack/plugins/lens/public/xy_visualization/expression_thresholds.tsx index d9c0b36702639..7532d41f091d1 100644 --- a/x-pack/plugins/lens/public/xy_visualization/expression_thresholds.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/expression_thresholds.tsx @@ -8,25 +8,144 @@ import React from 'react'; import { groupBy } from 'lodash'; import { EuiIcon } from '@elastic/eui'; -import { RectAnnotation, AnnotationDomainType, LineAnnotation } from '@elastic/charts'; +import { RectAnnotation, AnnotationDomainType, LineAnnotation, Position } from '@elastic/charts'; import type { PaletteRegistry } from 'src/plugins/charts/public'; import type { FieldFormat } from 'src/plugins/field_formats/common'; import { euiLightVars } from '@kbn/ui-shared-deps-src/theme'; -import type { LayerArgs } from '../../common/expressions'; +import type { LayerArgs, YConfig } from '../../common/expressions'; import type { LensMultiTable } from '../../common/types'; +const THRESHOLD_ICON_SIZE = 20; + +export const computeChartMargins = ( + thresholdPaddings: Partial>, + labelVisibility: Partial>, + titleVisibility: Partial>, + axesMap: Record<'left' | 'right', unknown>, + isHorizontal: boolean +) => { + const result: Partial> = {}; + if (!labelVisibility?.x && !titleVisibility?.x && thresholdPaddings.bottom) { + const placement = isHorizontal ? mapVerticalToHorizontalPlacement('bottom') : 'bottom'; + result[placement] = thresholdPaddings.bottom; + } + if ( + thresholdPaddings.left && + (isHorizontal || (!labelVisibility?.yLeft && !titleVisibility?.yLeft)) + ) { + const placement = isHorizontal ? mapVerticalToHorizontalPlacement('left') : 'left'; + result[placement] = thresholdPaddings.left; + } + if ( + thresholdPaddings.right && + (isHorizontal || !axesMap.right || (!labelVisibility?.yRight && !titleVisibility?.yRight)) + ) { + const placement = isHorizontal ? mapVerticalToHorizontalPlacement('right') : 'right'; + result[placement] = thresholdPaddings.right; + } + // there's no top axis, so just check if a margin has been computed + if (thresholdPaddings.top) { + const placement = isHorizontal ? mapVerticalToHorizontalPlacement('top') : 'top'; + result[placement] = thresholdPaddings.top; + } + return result; +}; + +function hasIcon(icon: string | undefined): icon is string { + return icon != null && icon !== 'none'; +} + +// Note: it does not take into consideration whether the threshold is in view or not +export const getThresholdRequiredPaddings = ( + thresholdLayers: LayerArgs[], + axesMap: Record<'left' | 'right', unknown> +) => { + const positions = Object.keys(Position); + return thresholdLayers.reduce((memo, layer) => { + if (positions.some((pos) => !(pos in memo))) { + layer.yConfig?.forEach(({ axisMode, icon, iconPosition }) => { + if (axisMode && hasIcon(icon)) { + const placement = getBaseIconPlacement(iconPosition, axisMode, axesMap); + memo[placement] = THRESHOLD_ICON_SIZE; + } + }); + } + return memo; + }, {} as Partial>); +}; + +function mapVerticalToHorizontalPlacement(placement: Position) { + switch (placement) { + case Position.Top: + return Position.Right; + case Position.Bottom: + return Position.Left; + case Position.Left: + return Position.Bottom; + case Position.Right: + return Position.Top; + } +} + +// if there's just one axis, put it on the other one +// otherwise use the same axis +// this function assume the chart is vertical +function getBaseIconPlacement( + iconPosition: YConfig['iconPosition'], + axisMode: YConfig['axisMode'], + axesMap: Record +) { + if (iconPosition === 'auto') { + if (axisMode === 'bottom') { + return Position.Top; + } + if (axisMode === 'left') { + return axesMap.right ? Position.Left : Position.Right; + } + return axesMap.left ? Position.Right : Position.Left; + } + + if (iconPosition === 'left') { + return Position.Left; + } + if (iconPosition === 'right') { + return Position.Right; + } + if (iconPosition === 'below') { + return Position.Bottom; + } + return Position.Top; +} + +function getIconPlacement( + iconPosition: YConfig['iconPosition'], + axisMode: YConfig['axisMode'], + axesMap: Record, + isHorizontal: boolean +) { + const vPosition = getBaseIconPlacement(iconPosition, axisMode, axesMap); + if (isHorizontal) { + return mapVerticalToHorizontalPlacement(vPosition); + } + return vPosition; +} + export const ThresholdAnnotations = ({ thresholdLayers, data, formatters, paletteService, syncColors, + axesMap, + isHorizontal, }: { thresholdLayers: LayerArgs[]; data: LensMultiTable; formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>; paletteService: PaletteRegistry; syncColors: boolean; + axesMap: Record<'left' | 'right', boolean>; + isHorizontal: boolean; }) => { return ( <> @@ -63,7 +182,13 @@ export const ThresholdAnnotations = ({ const props = { groupId, - marker: yConfig.icon ? : undefined, + marker: hasIcon(yConfig.icon) ? : undefined, + markerPosition: getIconPlacement( + yConfig.iconPosition, + yConfig.axisMode, + axesMap, + isHorizontal + ), }; const annotations = []; diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index b66f0ca4687b8..2fce7c6a612ae 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -340,6 +340,7 @@ export const buildExpression = ( lineWidth: [yConfig.lineWidth || 1], fill: [yConfig.fill || 'none'], icon: yConfig.icon ? [yConfig.icon] : [], + iconPosition: [yConfig.iconPosition || 'auto'], }, }, ], diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx index 1427a3d28ea39..41d00e2eef32a 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx @@ -565,7 +565,7 @@ export function DimensionEditor( } if (layer.layerType === 'threshold') { - return ; + return ; } return ( diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/threshold_panel.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/threshold_panel.tsx index 087eee9005c06..cdf5bb2cc2ef1 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/threshold_panel.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/threshold_panel.tsx @@ -14,11 +14,11 @@ import type { VisualizationDimensionEditorProps } from '../../types'; import { State, XYState } from '../types'; import { FormatFactory } from '../../../common'; import { YConfig } from '../../../common/expressions'; -import { LineStyle, FillStyle } from '../../../common/expressions/xy_chart'; +import { LineStyle, FillStyle, IconPosition } from '../../../common/expressions/xy_chart'; import { ColorPicker } from './color_picker'; import { updateLayer, idPrefix } from '.'; -import { useDebouncedValue } from '../../shared_components'; +import { TooltipWrapper, useDebouncedValue } from '../../shared_components'; const icons = [ { @@ -109,13 +109,82 @@ const IconSelect = ({ ); }; +function getIconPositionOptions({ + isHorizontal, + axisMode, +}: { + isHorizontal: boolean; + axisMode: YConfig['axisMode']; +}) { + const options = [ + { + id: `${idPrefix}auto`, + label: i18n.translate('xpack.lens.xyChart.thresholdMarker.auto', { + defaultMessage: 'Auto', + }), + 'data-test-subj': 'lnsXY_markerPosition_auto', + }, + ]; + const topLabel = i18n.translate('xpack.lens.xyChart.markerPosition.above', { + defaultMessage: 'Top', + }); + const bottomLabel = i18n.translate('xpack.lens.xyChart.markerPosition.below', { + defaultMessage: 'Bottom', + }); + const leftLabel = i18n.translate('xpack.lens.xyChart.markerPosition.left', { + defaultMessage: 'Left', + }); + const rightLabel = i18n.translate('xpack.lens.xyChart.markerPosition.right', { + defaultMessage: 'Right', + }); + if (axisMode === 'bottom') { + const bottomOptions = [ + { + id: `${idPrefix}above`, + label: isHorizontal ? rightLabel : topLabel, + 'data-test-subj': 'lnsXY_markerPosition_above', + }, + { + id: `${idPrefix}below`, + label: isHorizontal ? leftLabel : bottomLabel, + 'data-test-subj': 'lnsXY_markerPosition_below', + }, + ]; + if (isHorizontal) { + // above -> below + // left -> right + bottomOptions.reverse(); + } + return [...options, ...bottomOptions]; + } + const yOptions = [ + { + id: `${idPrefix}left`, + label: isHorizontal ? bottomLabel : leftLabel, + 'data-test-subj': 'lnsXY_markerPosition_left', + }, + { + id: `${idPrefix}right`, + label: isHorizontal ? topLabel : rightLabel, + 'data-test-subj': 'lnsXY_markerPosition_right', + }, + ]; + if (isHorizontal) { + // left -> right + // above -> below + yOptions.reverse(); + } + return [...options, ...yOptions]; +} + export const ThresholdPanel = ( props: VisualizationDimensionEditorProps & { formatFactory: FormatFactory; paletteService: PaletteRegistry; + isHorizontal: boolean; } ) => { - const { state, setState, layerId, accessor } = props; + const { state, setState, layerId, accessor, isHorizontal } = props; const { inputValue: localState, handleInputChange: setLocalState } = useDebouncedValue({ value: state, @@ -265,7 +334,7 @@ export const ThresholdPanel = ( @@ -276,6 +345,44 @@ export const ThresholdPanel = ( }} /> + + + { + const newMode = id.replace(idPrefix, '') as IconPosition; + setYConfig({ forAccessor: accessor, iconPosition: newMode }); + }} + /> + + ); }; From 6bfa2a4c2ce4a32fa6857cfb5b3393b2cf89da09 Mon Sep 17 00:00:00 2001 From: Marta Bondyra Date: Mon, 4 Oct 2021 13:32:36 +0200 Subject: [PATCH 27/98] [Lens] move from slice to reducers/actions and simplify loading (#113324) * structure changes * tests & fix for sessionId * share mocks in time_range_middleware * make switchVisualization and selectSuggestion one reducer as it's very similar * CR Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../lens/public/app_plugin/app.test.tsx | 48 +- .../config_panel/config_panel.test.tsx | 129 ++---- .../config_panel/layer_actions.test.ts | 10 +- .../editor_frame/editor_frame.test.tsx | 32 +- .../editor_frame/editor_frame.tsx | 2 +- .../editor_frame/suggestion_helpers.test.ts | 60 +-- .../editor_frame/suggestion_helpers.ts | 29 +- .../editor_frame/suggestion_panel.test.tsx | 13 +- .../workspace_panel/chart_switch.test.tsx | 62 ++- .../workspace_panel/chart_switch.tsx | 2 +- .../workspace_panel/workspace_panel.test.tsx | 63 +-- .../workspace_panel/workspace_panel.tsx | 2 +- x-pack/plugins/lens/public/mocks.tsx | 114 +++-- .../__snapshots__/load_initial.test.tsx.snap | 4 +- .../lens/public/state_management/index.ts | 14 +- .../init_middleware/load_initial.test.tsx | 410 ------------------ .../init_middleware/load_initial.ts | 119 ++--- .../state_management/lens_slice.test.ts | 26 +- .../public/state_management/lens_slice.ts | 276 ++++++++---- .../state_management/load_initial.test.tsx | 323 ++++++++++++++ .../time_range_middleware.test.ts | 115 +---- 21 files changed, 845 insertions(+), 1008 deletions(-) rename x-pack/plugins/lens/public/state_management/{init_middleware => }/__snapshots__/load_initial.test.tsx.snap (94%) delete mode 100644 x-pack/plugins/lens/public/state_management/init_middleware/load_initial.test.tsx create mode 100644 x-pack/plugins/lens/public/state_management/load_initial.test.tsx diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index d10fe42feb322..a2c7c67e1fc77 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -13,7 +13,13 @@ import { App } from './app'; import { LensAppProps, LensAppServices } from './types'; import { EditorFrameInstance, EditorFrameProps } from '../types'; import { Document } from '../persistence'; -import { visualizationMap, datasourceMap, makeDefaultServices, mountWithProvider } from '../mocks'; +import { + visualizationMap, + datasourceMap, + makeDefaultServices, + mountWithProvider, + mockStoreDeps, +} from '../mocks'; import { I18nProvider } from '@kbn/i18n/react'; import { SavedObjectSaveModal, @@ -92,9 +98,11 @@ describe('Lens App', () => { }; } + const makeDefaultServicesForApp = () => makeDefaultServices(sessionIdSubject, 'sessionId-1'); + async function mountWith({ props = makeDefaultProps(), - services = makeDefaultServices(sessionIdSubject), + services = makeDefaultServicesForApp(), preloadedState, }: { props?: jest.Mocked; @@ -110,11 +118,11 @@ describe('Lens App', () => { ); }; - + const storeDeps = mockStoreDeps({ lensServices: services }); const { instance, lensStore } = await mountWithProvider( , { - data: services.data, + storeDeps, preloadedState, }, { wrappingComponent } @@ -144,7 +152,7 @@ describe('Lens App', () => { }); it('updates global filters with store state', async () => { - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); const indexPattern = { id: 'index1' } as unknown as IndexPattern; const pinnedField = { name: 'pinnedField' } as unknown as FieldSpec; const pinnedFilter = esFilters.buildExistsFilter(pinnedField, indexPattern); @@ -216,7 +224,7 @@ describe('Lens App', () => { it('sets originatingApp breadcrumb when the document title changes', async () => { const props = makeDefaultProps(); - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); props.incomingState = { originatingApp: 'coolContainer' }; services.getOriginatingAppName = jest.fn(() => 'The Coolest Container Ever Made'); @@ -262,7 +270,7 @@ describe('Lens App', () => { describe('TopNavMenu#showDatePicker', () => { it('shows date picker if any used index pattern isTimeBased', async () => { - const customServices = makeDefaultServices(sessionIdSubject); + const customServices = makeDefaultServicesForApp(); customServices.data.indexPatterns.get = jest .fn() .mockImplementation((id) => @@ -275,7 +283,7 @@ describe('Lens App', () => { ); }); it('shows date picker if active datasource isTimeBased', async () => { - const customServices = makeDefaultServices(sessionIdSubject); + const customServices = makeDefaultServicesForApp(); customServices.data.indexPatterns.get = jest .fn() .mockImplementation((id) => @@ -290,7 +298,7 @@ describe('Lens App', () => { ); }); it('does not show date picker if index pattern nor active datasource is not time based', async () => { - const customServices = makeDefaultServices(sessionIdSubject); + const customServices = makeDefaultServicesForApp(); customServices.data.indexPatterns.get = jest .fn() .mockImplementation((id) => @@ -337,7 +345,7 @@ describe('Lens App', () => { ); }); it('handles rejected index pattern', async () => { - const customServices = makeDefaultServices(sessionIdSubject); + const customServices = makeDefaultServicesForApp(); customServices.data.indexPatterns.get = jest .fn() .mockImplementation((id) => Promise.reject({ reason: 'Could not locate that data view' })); @@ -385,7 +393,7 @@ describe('Lens App', () => { : undefined, }; - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); services.attributeService.wrapAttributes = jest .fn() .mockImplementation(async ({ savedObjectId }) => ({ @@ -419,7 +427,7 @@ describe('Lens App', () => { } it('shows a disabled save button when the user does not have permissions', async () => { - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); services.application = { ...services.application, capabilities: { @@ -469,7 +477,7 @@ describe('Lens App', () => { it('Shows Save and Return and Save As buttons in create by value mode with originating app', async () => { const props = makeDefaultProps(); - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); services.dashboardFeatureFlag = { allowByValueEmbeddables: true }; props.incomingState = { originatingApp: 'ultraDashboard', @@ -618,7 +626,7 @@ describe('Lens App', () => { const mockedConsoleDir = jest.spyOn(console, 'dir'); // mocked console.dir to avoid messages in the console when running tests mockedConsoleDir.mockImplementation(() => {}); - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); services.attributeService.wrapAttributes = jest .fn() .mockRejectedValue({ message: 'failed' }); @@ -692,7 +700,7 @@ describe('Lens App', () => { }); it('checks for duplicate title before saving', async () => { - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); services.attributeService.wrapAttributes = jest .fn() .mockReturnValue(Promise.resolve({ savedObjectId: '123' })); @@ -759,7 +767,7 @@ describe('Lens App', () => { }); it('should still be enabled even if the user is missing save permissions', async () => { - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); services.application = { ...services.application, capabilities: { @@ -799,7 +807,7 @@ describe('Lens App', () => { }); it('should open inspect panel', async () => { - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); const { instance } = await mountWith({ services, preloadedState: { isSaveable: true } }); await runInspect(instance); @@ -943,7 +951,7 @@ describe('Lens App', () => { describe('saved query handling', () => { it('does not allow saving when the user is missing the saveQuery permission', async () => { - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); services.application = { ...services.application, capabilities: { @@ -1136,7 +1144,7 @@ describe('Lens App', () => { it('updates the state if session id changes from the outside', async () => { const sessionIdS = new Subject(); - const services = makeDefaultServices(sessionIdS); + const services = makeDefaultServices(sessionIdS, 'sessionId-1'); const { lensStore } = await mountWith({ props: undefined, services }); act(() => { @@ -1180,7 +1188,7 @@ describe('Lens App', () => { }); it('does not confirm if the user is missing save permissions', async () => { - const services = makeDefaultServices(sessionIdSubject); + const services = makeDefaultServicesForApp(); services.application = { ...services.application, capabilities: { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx index 2668a31d70754..61d37d4cc9fed 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx @@ -7,12 +7,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { - createMockVisualization, - createMockFramePublicAPI, - createMockDatasource, - DatasourceMock, -} from '../../../mocks'; +import { createMockFramePublicAPI, visualizationMap, datasourceMap } from '../../../mocks'; import { Visualization } from '../../../types'; import { LayerPanels } from './config_panel'; import { LayerPanel } from './layer_panel'; @@ -43,32 +38,23 @@ afterEach(() => { }); describe('ConfigPanel', () => { - let mockVisualization: jest.Mocked; - let mockVisualization2: jest.Mocked; - let mockDatasource: DatasourceMock; const frame = createMockFramePublicAPI(); function getDefaultProps() { frame.datasourceLayers = { - first: mockDatasource.publicAPIMock, + first: datasourceMap.testDatasource.publicAPIMock, }; return { - activeVisualizationId: 'vis1', - visualizationMap: { - vis1: mockVisualization, - vis2: mockVisualization2, - }, - activeDatasourceId: 'mockindexpattern', - datasourceMap: { - mockindexpattern: mockDatasource, - }, + activeVisualizationId: 'testVis', + visualizationMap, + activeDatasourceId: 'testDatasource', + datasourceMap, activeVisualization: { - ...mockVisualization, + ...visualizationMap.testVis, getLayerIds: () => Object.keys(frame.datasourceLayers), - appendLayer: jest.fn(), } as unknown as Visualization, datasourceStates: { - mockindexpattern: { + testDatasource: { isLoading: false, state: 'state', }, @@ -85,38 +71,6 @@ describe('ConfigPanel', () => { }; } - beforeEach(() => { - mockVisualization = { - ...createMockVisualization(), - id: 'testVis', - visualizationTypes: [ - { - icon: 'empty', - id: 'testVis', - label: 'TEST1', - groupLabel: 'testVisGroup', - }, - ], - }; - - mockVisualization2 = { - ...createMockVisualization(), - - id: 'testVis2', - visualizationTypes: [ - { - icon: 'empty', - id: 'testVis2', - label: 'TEST2', - groupLabel: 'testVis2Group', - }, - ], - }; - - mockVisualization.getLayerIds.mockReturnValue(Object.keys(frame.datasourceLayers)); - mockDatasource = createMockDatasource('mockindexpattern'); - }); - // in what case is this test needed? it('should fail to render layerPanels if the public API is out of date', async () => { const props = getDefaultProps(); @@ -130,7 +84,7 @@ describe('ConfigPanel', () => { const { instance, lensStore } = await mountWithProvider(, { preloadedState: { datasourceStates: { - mockindexpattern: { + testDatasource: { isLoading: false, state: 'state', }, @@ -140,22 +94,22 @@ describe('ConfigPanel', () => { const { updateDatasource, updateAll } = instance.find(LayerPanel).props(); const updater = () => 'updated'; - updateDatasource('mockindexpattern', updater); + updateDatasource('testDatasource', updater); await waitMs(0); expect(lensStore.dispatch).toHaveBeenCalledTimes(1); expect( (lensStore.dispatch as jest.Mock).mock.calls[0][0].payload.updater( - props.datasourceStates.mockindexpattern.state + props.datasourceStates.testDatasource.state ) ).toEqual('updated'); - updateAll('mockindexpattern', updater, props.visualizationState); + updateAll('testDatasource', updater, props.visualizationState); // wait for one tick so async updater has a chance to trigger await waitMs(0); expect(lensStore.dispatch).toHaveBeenCalledTimes(2); expect( (lensStore.dispatch as jest.Mock).mock.calls[0][0].payload.updater( - props.datasourceStates.mockindexpattern.state + props.datasourceStates.testDatasource.state ) ).toEqual('updated'); }); @@ -167,7 +121,7 @@ describe('ConfigPanel', () => { { preloadedState: { datasourceStates: { - mockindexpattern: { + testDatasource: { isLoading: false, state: 'state', }, @@ -195,15 +149,15 @@ describe('ConfigPanel', () => { const defaultProps = getDefaultProps(); // overwriting datasourceLayers to test two layers frame.datasourceLayers = { - first: mockDatasource.publicAPIMock, - second: mockDatasource.publicAPIMock, + first: datasourceMap.testDatasource.publicAPIMock, + second: datasourceMap.testDatasource.publicAPIMock, }; const { instance } = await mountWithProvider( , { preloadedState: { datasourceStates: { - mockindexpattern: { + testDatasource: { isLoading: false, state: 'state', }, @@ -232,15 +186,15 @@ describe('ConfigPanel', () => { const defaultProps = getDefaultProps(); // overwriting datasourceLayers to test two layers frame.datasourceLayers = { - first: mockDatasource.publicAPIMock, - second: mockDatasource.publicAPIMock, + first: datasourceMap.testDatasource.publicAPIMock, + second: datasourceMap.testDatasource.publicAPIMock, }; const { instance } = await mountWithProvider( , { preloadedState: { datasourceStates: { - mockindexpattern: { + testDatasource: { isLoading: false, state: 'state', }, @@ -273,16 +227,16 @@ describe('ConfigPanel', () => { { preloadedState: { datasourceStates: { - mockindexpattern: { + testDatasource: { isLoading: false, state: 'state', }, }, - activeDatasourceId: 'mockindexpattern', + activeDatasourceId: 'testDatasource', }, dispatch: jest.fn((x) => { if (x.payload.subType === 'ADD_LAYER') { - frame.datasourceLayers.second = mockDatasource.publicAPIMock; + frame.datasourceLayers.second = datasourceMap.testDatasource.publicAPIMock; } }), }, @@ -303,16 +257,15 @@ describe('ConfigPanel', () => { (generateId as jest.Mock).mockReturnValue(`newId`); return mountWithProvider( , - { preloadedState: { datasourceStates: { - mockindexpattern: { + testDatasource: { isLoading: false, state: 'state', }, }, - activeDatasourceId: 'mockindexpattern', + activeDatasourceId: 'testDatasource', }, }, { @@ -352,13 +305,13 @@ describe('ConfigPanel', () => { label: 'Threshold layer', }, ]); - mockDatasource.initializeDimension = jest.fn(); + datasourceMap.testDatasource.initializeDimension = jest.fn(); const { instance, lensStore } = await prepareAndMountComponent(props); await clickToAddLayer(instance); expect(lensStore.dispatch).toHaveBeenCalledTimes(1); - expect(mockDatasource.initializeDimension).not.toHaveBeenCalled(); + expect(datasourceMap.testDatasource.initializeDimension).not.toHaveBeenCalled(); }); it('should not add an initial dimension when initialDimensions are not available for the given layer type', async () => { @@ -382,13 +335,13 @@ describe('ConfigPanel', () => { label: 'Threshold layer', }, ]); - mockDatasource.initializeDimension = jest.fn(); + datasourceMap.testDatasource.initializeDimension = jest.fn(); const { instance, lensStore } = await prepareAndMountComponent(props); await clickToAddLayer(instance); expect(lensStore.dispatch).toHaveBeenCalledTimes(1); - expect(mockDatasource.initializeDimension).not.toHaveBeenCalled(); + expect(datasourceMap.testDatasource.initializeDimension).not.toHaveBeenCalled(); }); it('should use group initial dimension value when adding a new layer if available', async () => { @@ -409,13 +362,13 @@ describe('ConfigPanel', () => { ], }, ]); - mockDatasource.initializeDimension = jest.fn(); + datasourceMap.testDatasource.initializeDimension = jest.fn(); const { instance, lensStore } = await prepareAndMountComponent(props); await clickToAddLayer(instance); expect(lensStore.dispatch).toHaveBeenCalledTimes(1); - expect(mockDatasource.initializeDimension).toHaveBeenCalledWith(undefined, 'newId', { + expect(datasourceMap.testDatasource.initializeDimension).toHaveBeenCalledWith({}, 'newId', { columnId: 'myColumn', dataType: 'number', groupId: 'testGroup', @@ -441,20 +394,24 @@ describe('ConfigPanel', () => { ], }, ]); - mockDatasource.initializeDimension = jest.fn(); + datasourceMap.testDatasource.initializeDimension = jest.fn(); const { instance, lensStore } = await prepareAndMountComponent(props); await clickToAddDimension(instance); expect(lensStore.dispatch).toHaveBeenCalledTimes(1); - expect(mockDatasource.initializeDimension).toHaveBeenCalledWith('state', 'first', { - groupId: 'a', - columnId: 'newId', - dataType: 'number', - label: 'Initial value', - staticValue: 100, - }); + expect(datasourceMap.testDatasource.initializeDimension).toHaveBeenCalledWith( + 'state', + 'first', + { + groupId: 'a', + columnId: 'newId', + dataType: 'number', + label: 'Initial value', + staticValue: 100, + } + ); }); }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_actions.test.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_actions.test.ts index 967e6e47c55f0..44cefb0bf8ec4 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_actions.test.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_actions.test.ts @@ -4,9 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { layerTypes } from '../../../../common'; -import { initialState } from '../../../state_management/lens_slice'; +import { LensAppState } from '../../../state_management/types'; import { removeLayer, appendLayer } from './layer_actions'; function createTestArgs(initialLayerIds: string[]) { @@ -44,15 +43,14 @@ function createTestArgs(initialLayerIds: string[]) { return { state: { - ...initialState, activeDatasourceId: 'ds1', datasourceStates, title: 'foo', visualization: { - activeId: 'vis1', + activeId: 'testVis', state: initialLayerIds, }, - }, + } as unknown as LensAppState, activeVisualization, datasourceMap: { ds1: testDatasource('ds1'), @@ -61,7 +59,7 @@ function createTestArgs(initialLayerIds: string[]) { trackUiEvent, stagedPreview: { visualization: { - activeId: 'vis1', + activeId: 'testVis', state: initialLayerIds, }, datasourceStates, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx index 4be9de78dedce..d289b69f4105e 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx @@ -146,7 +146,6 @@ describe('editor_frame', () => { }; const lensStore = ( await mountWithProvider(, { - data: props.plugins.data, preloadedState: { activeDatasourceId: 'testDatasource', datasourceStates: { @@ -196,7 +195,6 @@ describe('editor_frame', () => { }; await mountWithProvider(, { - data: props.plugins.data, preloadedState: { visualization: { activeId: 'testVis', state: initialState }, }, @@ -228,7 +226,6 @@ describe('editor_frame', () => { }; instance = ( await mountWithProvider(, { - data: props.plugins.data, preloadedState: { visualization: { activeId: 'testVis', state: {} }, datasourceStates: { @@ -283,7 +280,6 @@ describe('editor_frame', () => { instance = ( await mountWithProvider(, { - data: props.plugins.data, preloadedState: { visualization: { activeId: 'testVis', state: {} }, datasourceStates: { @@ -395,7 +391,6 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; await mountWithProvider(, { - data: props.plugins.data, preloadedState: { activeDatasourceId: 'testDatasource', visualization: { activeId: mockVisualization.id, state: {} }, @@ -437,7 +432,7 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; - await mountWithProvider(, { data: props.plugins.data }); + await mountWithProvider(); const setDatasourceState = (mockDatasource.renderDataPanel as jest.Mock).mock.calls[0][1] .setState; @@ -474,7 +469,6 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; await mountWithProvider(, { - data: props.plugins.data, preloadedState: { visualization: { activeId: mockVisualization.id, state: {} } }, }); @@ -523,7 +517,6 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; await mountWithProvider(, { - data: props.plugins.data, preloadedState: { datasourceStates: { testDatasource: { @@ -587,8 +580,7 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; - instance = (await mountWithProvider(, { data: props.plugins.data })) - .instance; + instance = (await mountWithProvider()).instance; // necessary to flush elements to dom synchronously instance.update(); @@ -692,7 +684,7 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; - await mountWithProvider(, { data: props.plugins.data }); + await mountWithProvider(); expect(mockDatasource.getDatasourceSuggestionsFromCurrentState).toHaveBeenCalled(); expect(mockDatasource2.getDatasourceSuggestionsFromCurrentState).not.toHaveBeenCalled(); @@ -725,7 +717,7 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; - await mountWithProvider(, { data: props.plugins.data }); + await mountWithProvider(); expect(mockVisualization.getSuggestions).toHaveBeenCalled(); expect(mockVisualization2.getSuggestions).toHaveBeenCalled(); @@ -793,8 +785,7 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; - instance = (await mountWithProvider(, { data: props.plugins.data })) - .instance; + instance = (await mountWithProvider()).instance; expect( instance @@ -840,8 +831,7 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; - instance = (await mountWithProvider(, { data: props.plugins.data })) - .instance; + instance = (await mountWithProvider()).instance; act(() => { instance.find('[data-test-subj="lnsSuggestion"]').at(2).simulate('click'); @@ -898,8 +888,7 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, }; - instance = (await mountWithProvider(, { data: props.plugins.data })) - .instance; + instance = (await mountWithProvider()).instance; act(() => { instance.find('[data-test-subj="lnsWorkspace"]').last().simulate('drop'); @@ -968,7 +957,6 @@ describe('editor_frame', () => { } as EditorFrameProps; instance = ( await mountWithProvider(, { - data: props.plugins.data, preloadedState: { datasourceStates: { testDatasource: { @@ -1080,11 +1068,7 @@ describe('editor_frame', () => { ExpressionRenderer: expressionRendererMock, } as EditorFrameProps; - instance = ( - await mountWithProvider(, { - data: props.plugins.data, - }) - ).instance; + instance = (await mountWithProvider()).instance; act(() => { instance.find(DragDrop).filter('[dataTestSubj="lnsWorkspace"]').prop('onDrop')!( diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx index 3b55c4923f967..c68c04b4b3e21 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx @@ -76,7 +76,7 @@ export function EditorFrame(props: EditorFrameProps) { const suggestion = getSuggestionForField.current!(field); if (suggestion) { trackUiEvent('drop_onto_workspace'); - switchToSuggestion(dispatchLens, suggestion, 'SWITCH_VISUALIZATION'); + switchToSuggestion(dispatchLens, suggestion, true); } }, [getSuggestionForField, dispatchLens] diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts index 90fa2ab080dd2..0d68e2d72e73b 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts @@ -46,7 +46,7 @@ describe('suggestion helpers', () => { ]); const suggestedState = {}; const visualizationMap = { - vis1: { + testVis: { ...mockVisualization, getSuggestions: () => [ { @@ -60,7 +60,7 @@ describe('suggestion helpers', () => { }; const suggestions = getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -76,7 +76,7 @@ describe('suggestion helpers', () => { generateSuggestion(), ]); const visualizationMap = { - vis1: { + testVis: { ...mockVisualization1, getSuggestions: () => [ { @@ -107,7 +107,7 @@ describe('suggestion helpers', () => { }; const suggestions = getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -119,11 +119,11 @@ describe('suggestion helpers', () => { datasourceMap.mock.getDatasourceSuggestionsForField.mockReturnValue([generateSuggestion()]); const droppedField = {}; const visualizationMap = { - vis1: createMockVisualization(), + testVis: createMockVisualization(), }; getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -153,12 +153,12 @@ describe('suggestion helpers', () => { mock3: createMockDatasource('a'), }; const visualizationMap = { - vis1: createMockVisualization(), + testVis: createMockVisualization(), }; const droppedField = {}; getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap: multiDatasourceMap, datasourceStates: multiDatasourceStates, @@ -183,12 +183,12 @@ describe('suggestion helpers', () => { ]); const visualizationMap = { - vis1: createMockVisualization(), + testVis: createMockVisualization(), }; getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -226,11 +226,11 @@ describe('suggestion helpers', () => { }; const visualizationMap = { - vis1: createMockVisualization(), + testVis: createMockVisualization(), }; getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap: multiDatasourceMap, datasourceStates: multiDatasourceStates, @@ -258,7 +258,7 @@ describe('suggestion helpers', () => { generateSuggestion(), ]); const visualizationMap = { - vis1: { + testVis: { ...mockVisualization1, getSuggestions: () => [ { @@ -289,7 +289,7 @@ describe('suggestion helpers', () => { }; const suggestions = getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -319,12 +319,12 @@ describe('suggestion helpers', () => { { state: {}, table: table2, keptLayerIds: ['first'] }, ]); const visualizationMap = { - vis1: mockVisualization1, + testVis: mockVisualization1, vis2: mockVisualization2, }; getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -372,7 +372,7 @@ describe('suggestion helpers', () => { }, ]); const visualizationMap = { - vis1: { + testVis: { ...mockVisualization1, getSuggestions: vis1Suggestions, }, @@ -384,7 +384,7 @@ describe('suggestion helpers', () => { const suggestions = getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -407,13 +407,13 @@ describe('suggestion helpers', () => { ]); const visualizationMap = { - vis1: mockVisualization1, + testVis: mockVisualization1, vis2: mockVisualization2, }; getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -439,12 +439,12 @@ describe('suggestion helpers', () => { generateSuggestion(1), ]); const visualizationMap = { - vis1: mockVisualization1, + testVis: mockVisualization1, vis2: mockVisualization2, }; getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -472,13 +472,13 @@ describe('suggestion helpers', () => { generateSuggestion(1), ]); const visualizationMap = { - vis1: mockVisualization1, + testVis: mockVisualization1, vis2: mockVisualization2, }; getSuggestions({ visualizationMap, - activeVisualization: visualizationMap.vis1, + activeVisualization: visualizationMap.testVis, visualizationState: {}, datasourceMap, datasourceStates, @@ -542,9 +542,9 @@ describe('suggestion helpers', () => { getOperationForColumnId: jest.fn(), }, }, - { activeId: 'vis1', state: {} }, - { mockindexpattern: { state: mockDatasourceState, isLoading: false } }, - { vis1: mockVisualization1 }, + { activeId: 'testVis', state: {} }, + { testDatasource: { state: mockDatasourceState, isLoading: false } }, + { testVis: mockVisualization1 }, datasourceMap.mock, { id: 'myfield', humanData: { label: 'myfieldLabel' } }, ]; @@ -574,7 +574,7 @@ describe('suggestion helpers', () => { it('should return nothing if datasource does not produce suggestions', () => { datasourceMap.mock.getDatasourceSuggestionsForField.mockReturnValue([]); defaultParams[3] = { - vis1: { ...mockVisualization1, getSuggestions: () => [] }, + testVis: { ...mockVisualization1, getSuggestions: () => [] }, vis2: mockVisualization2, }; const result = getTopSuggestionForField(...defaultParams); @@ -583,7 +583,7 @@ describe('suggestion helpers', () => { it('should not consider suggestion from other visualization if there is data', () => { defaultParams[3] = { - vis1: { ...mockVisualization1, getSuggestions: () => [] }, + testVis: { ...mockVisualization1, getSuggestions: () => [] }, vis2: mockVisualization2, }; const result = getTopSuggestionForField(...defaultParams); @@ -609,7 +609,7 @@ describe('suggestion helpers', () => { }, ]); defaultParams[3] = { - vis1: mockVisualization1, + testVis: mockVisualization1, vis2: mockVisualization2, vis3: mockVisualization3, }; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts index a5c7871f33dfc..7f1e4aa58dba3 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts @@ -25,7 +25,6 @@ import { LayerType, layerTypes } from '../../../common'; import { getLayerType } from './config_panel/add_layer'; import { LensDispatch, - selectSuggestion, switchVisualization, DatasourceStates, VisualizationState, @@ -164,24 +163,21 @@ export function getVisualizeFieldSuggestions({ datasourceMap, datasourceStates, visualizationMap, - activeVisualization, - visualizationState, visualizeTriggerFieldContext, }: { datasourceMap: DatasourceMap; datasourceStates: DatasourceStates; visualizationMap: VisualizationMap; - activeVisualization: Visualization; subVisualizationId?: string; - visualizationState: unknown; visualizeTriggerFieldContext?: VisualizeFieldContext; }): Suggestion | undefined { + const activeVisualization = visualizationMap?.[Object.keys(visualizationMap)[0]] || null; const suggestions = getSuggestions({ datasourceMap, datasourceStates, visualizationMap, activeVisualization, - visualizationState, + visualizationState: undefined, visualizeTriggerFieldContext, }); if (suggestions.length) { @@ -230,19 +226,18 @@ export function switchToSuggestion( Suggestion, 'visualizationId' | 'visualizationState' | 'datasourceState' | 'datasourceId' >, - type: 'SWITCH_VISUALIZATION' | 'SELECT_SUGGESTION' = 'SELECT_SUGGESTION' + clearStagedPreview?: boolean ) { - const pickedSuggestion = { - newVisualizationId: suggestion.visualizationId, - initialState: suggestion.visualizationState, - datasourceState: suggestion.datasourceState, - datasourceId: suggestion.datasourceId!, - }; - dispatchLens( - type === 'SELECT_SUGGESTION' - ? selectSuggestion(pickedSuggestion) - : switchVisualization(pickedSuggestion) + switchVisualization({ + suggestion: { + newVisualizationId: suggestion.visualizationId, + visualizationState: suggestion.visualizationState, + datasourceState: suggestion.datasourceState, + datasourceId: suggestion.datasourceId!, + }, + clearStagedPreview, + }) ); } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx index b63d2956cfe6b..26e0be3555714 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx @@ -214,16 +214,17 @@ describe('suggestion_panel', () => { act(() => { instance.find('button[data-test-subj="lnsSuggestion"]').at(1).simulate('click'); }); - // instance.update(); expect(lensStore.dispatch).toHaveBeenCalledWith( expect.objectContaining({ - type: 'lens/selectSuggestion', + type: 'lens/switchVisualization', payload: { - datasourceId: undefined, - datasourceState: {}, - initialState: { suggestion1: true }, - newVisualizationId: 'testVis', + suggestion: { + datasourceId: undefined, + datasourceState: {}, + visualizationState: { suggestion1: true }, + newVisualizationId: 'testVis', + }, }, }) ); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx index e7abf291b6eba..7cb97882a5e03 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx @@ -200,10 +200,13 @@ describe('chart_switch', () => { expect(lensStore.dispatch).toHaveBeenCalledWith({ type: 'lens/switchVisualization', payload: { - initialState: 'suggestion visB', - newVisualizationId: 'visB', - datasourceId: 'testDatasource', - datasourceState: {}, + suggestion: { + visualizationState: 'suggestion visB', + newVisualizationId: 'visB', + datasourceId: 'testDatasource', + datasourceState: {}, + }, + clearStagedPreview: true, }, }); }); @@ -238,8 +241,11 @@ describe('chart_switch', () => { expect(lensStore.dispatch).toHaveBeenCalledWith({ type: 'lens/switchVisualization', payload: { - initialState: 'visB initial state', - newVisualizationId: 'visB', + suggestion: { + visualizationState: 'visB initial state', + newVisualizationId: 'visB', + }, + clearStagedPreview: true, }, }); expect(lensStore.dispatch).toHaveBeenCalledWith({ @@ -522,10 +528,13 @@ describe('chart_switch', () => { expect(lensStore.dispatch).toHaveBeenCalledWith({ type: 'lens/switchVisualization', payload: { - datasourceId: undefined, - datasourceState: undefined, - initialState: 'visB initial state', - newVisualizationId: 'visB', + suggestion: { + datasourceId: undefined, + datasourceState: undefined, + visualizationState: 'visB initial state', + newVisualizationId: 'visB', + }, + clearStagedPreview: true, }, }); }); @@ -598,10 +607,13 @@ describe('chart_switch', () => { expect(lensStore.dispatch).toHaveBeenCalledWith({ type: 'lens/switchVisualization', payload: { - datasourceId: 'testDatasource', - datasourceState: {}, - initialState: 'switched', - newVisualizationId: 'visC', + suggestion: { + datasourceId: 'testDatasource', + datasourceState: {}, + visualizationState: 'switched', + newVisualizationId: 'visC', + }, + clearStagedPreview: true, }, }); expect(datasourceMap.testDatasource.removeLayer).not.toHaveBeenCalled(); @@ -694,10 +706,13 @@ describe('chart_switch', () => { expect(lensStore.dispatch).toHaveBeenCalledWith({ type: 'lens/switchVisualization', payload: { - newVisualizationId: 'visB', - datasourceId: 'testDatasource', - datasourceState: 'testDatasource suggestion', - initialState: 'suggestion visB', + suggestion: { + newVisualizationId: 'visB', + datasourceId: 'testDatasource', + datasourceState: 'testDatasource suggestion', + visualizationState: 'suggestion visB', + }, + clearStagedPreview: true, }, }); }); @@ -731,10 +746,13 @@ describe('chart_switch', () => { expect(lensStore.dispatch).toHaveBeenCalledWith({ type: 'lens/switchVisualization', payload: { - initialState: 'suggestion visB visB', - newVisualizationId: 'visB', - datasourceId: 'testDatasource', - datasourceState: {}, + suggestion: { + visualizationState: 'suggestion visB visB', + newVisualizationId: 'visB', + datasourceId: 'testDatasource', + datasourceState: {}, + }, + clearStagedPreview: true, }, }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx index 51d4f2955a52b..a5ba12941cf7f 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx @@ -166,7 +166,7 @@ export const ChartSwitch = memo(function ChartSwitch(props: Props) { ...selection, visualizationState: selection.getVisualizationState(), }, - 'SWITCH_VISUALIZATION' + true ); if ( diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx index 4df3632c7f7da..2ed65d3b0f146 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx @@ -103,7 +103,6 @@ describe('workspace_panel', () => { />, { - data: defaultProps.plugins.data, preloadedState: { visualization: { activeId: null, state: {} }, datasourceStates: {} }, } ); @@ -121,7 +120,7 @@ describe('workspace_panel', () => { }} />, - { data: defaultProps.plugins.data, preloadedState: { datasourceStates: {} } } + { preloadedState: { datasourceStates: {} } } ); instance = mounted.instance; @@ -138,7 +137,7 @@ describe('workspace_panel', () => { }} />, - { data: defaultProps.plugins.data, preloadedState: { datasourceStates: {} } } + { preloadedState: { datasourceStates: {} } } ); instance = mounted.instance; @@ -165,8 +164,7 @@ describe('workspace_panel', () => { testVis: { ...mockVisualization, toExpression: () => 'testVis' }, }} ExpressionRenderer={expressionRendererMock} - />, - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; @@ -199,9 +197,7 @@ describe('workspace_panel', () => { }} ExpressionRenderer={expressionRendererMock} plugins={{ ...props.plugins, uiActions: uiActionsMock }} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; @@ -233,9 +229,7 @@ describe('workspace_panel', () => { testVis: { ...mockVisualization, toExpression: () => 'testVis' }, }} ExpressionRenderer={expressionRendererMock} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; @@ -279,7 +273,6 @@ describe('workspace_panel', () => { />, { - data: defaultProps.plugins.data, preloadedState: { datasourceStates: { testDatasource: { @@ -360,9 +353,7 @@ describe('workspace_panel', () => { testVis: { ...mockVisualization, toExpression: () => 'testVis' }, }} ExpressionRenderer={expressionRendererMock} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; }); @@ -408,9 +399,7 @@ describe('workspace_panel', () => { testVis: { ...mockVisualization, toExpression: () => 'testVis' }, }} ExpressionRenderer={expressionRendererMock} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; }); @@ -456,7 +445,6 @@ describe('workspace_panel', () => { />, { - data: defaultProps.plugins.data, preloadedState: { datasourceStates: { testDatasource: { @@ -499,7 +487,6 @@ describe('workspace_panel', () => { />, { - data: defaultProps.plugins.data, preloadedState: { datasourceStates: { testDatasource: { @@ -543,7 +530,6 @@ describe('workspace_panel', () => { />, { - data: defaultProps.plugins.data, preloadedState: { datasourceStates: { testDatasource: { @@ -582,9 +568,7 @@ describe('workspace_panel', () => { visualizationMap={{ testVis: { ...mockVisualization, toExpression: () => 'testVis' }, }} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; @@ -614,9 +598,7 @@ describe('workspace_panel', () => { visualizationMap={{ testVis: mockVisualization, }} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; @@ -648,9 +630,7 @@ describe('workspace_panel', () => { visualizationMap={{ testVis: mockVisualization, }} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; @@ -679,9 +659,7 @@ describe('workspace_panel', () => { visualizationMap={{ testVis: { ...mockVisualization, toExpression: () => 'testVis' }, }} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; @@ -709,9 +687,7 @@ describe('workspace_panel', () => { testVis: { ...mockVisualization, toExpression: () => 'testVis' }, }} ExpressionRenderer={expressionRendererMock} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; }); @@ -745,9 +721,7 @@ describe('workspace_panel', () => { testVis: { ...mockVisualization, toExpression: () => 'testVis' }, }} ExpressionRenderer={expressionRendererMock} - />, - - { data: defaultProps.plugins.data } + /> ); instance = mounted.instance; lensStore = mounted.lensStore; @@ -832,10 +806,13 @@ describe('workspace_panel', () => { expect(lensStore.dispatch).toHaveBeenCalledWith({ type: 'lens/switchVisualization', payload: { - newVisualizationId: 'testVis', - initialState: {}, - datasourceState: {}, - datasourceId: 'testDatasource', + suggestion: { + newVisualizationId: 'testVis', + visualizationState: {}, + datasourceState: {}, + datasourceId: 'testDatasource', + }, + clearStagedPreview: true, }, }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx index b3b9345344116..f1161b83c228e 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx @@ -275,7 +275,7 @@ export const InnerWorkspacePanel = React.memo(function InnerWorkspacePanel({ if (suggestionForDraggedField) { trackUiEvent('drop_onto_workspace'); trackUiEvent(expressionExists ? 'drop_non_empty' : 'drop_empty'); - switchToSuggestion(dispatchLens, suggestionForDraggedField, 'SWITCH_VISUALIZATION'); + switchToSuggestion(dispatchLens, suggestionForDraggedField, true); } }, [suggestionForDraggedField, expressionExists, dispatchLens]); diff --git a/x-pack/plugins/lens/public/mocks.tsx b/x-pack/plugins/lens/public/mocks.tsx index 402440f3302f6..cb9ab11998105 100644 --- a/x-pack/plugins/lens/public/mocks.tsx +++ b/x-pack/plugins/lens/public/mocks.tsx @@ -39,7 +39,12 @@ import { fieldFormatsServiceMock } from '../../../../src/plugins/field_formats/p import type { LensAttributeService } from './lens_attribute_service'; import type { EmbeddableStateTransfer } from '../../../../src/plugins/embeddable/public'; -import { makeConfigureStore, LensAppState, LensState } from './state_management/index'; +import { + makeConfigureStore, + LensAppState, + LensState, + LensStoreDeps, +} from './state_management/index'; import { getResolvedDateRange } from './utils'; import { presentationUtilPluginMock } from '../../../../src/plugins/presentation_util/public/mocks'; import { @@ -48,6 +53,8 @@ import { Visualization, FramePublicAPI, FrameDatasourceAPI, + DatasourceMap, + VisualizationMap, } from './types'; export function mockDatasourceStates() { @@ -59,7 +66,7 @@ export function mockDatasourceStates() { }; } -export function createMockVisualization(id = 'vis1'): jest.Mocked { +export function createMockVisualization(id = 'testVis'): jest.Mocked { return { id, clearLayer: jest.fn((state, _layerId) => state), @@ -75,11 +82,12 @@ export function createMockVisualization(id = 'vis1'): jest.Mocked groupLabel: `${id}Group`, }, ], + appendLayer: jest.fn(), getVisualizationTypeId: jest.fn((_state) => 'empty'), getDescription: jest.fn((_state) => ({ label: '' })), switchVisualizationType: jest.fn((_, x) => x), getSuggestions: jest.fn((_options) => []), - initialize: jest.fn((_frame, _state?) => ({})), + initialize: jest.fn((_frame, _state?) => ({ newState: 'newState' })), getConfiguration: jest.fn((props) => ({ groups: [ { @@ -120,7 +128,7 @@ export function createMockDatasource(id: string): DatasourceMock { }; return { - id: 'mockindexpattern', + id: 'testDatasource', clearLayer: jest.fn((state, _layerId) => state), getDatasourceSuggestionsForField: jest.fn((_state, _item, filterFn) => []), getDatasourceSuggestionsForVisualizeField: jest.fn((_state, _indexpatternId, _fieldName) => []), @@ -134,7 +142,7 @@ export function createMockDatasource(id: string): DatasourceMock { renderDataPanel: jest.fn(), renderLayerPanel: jest.fn(), toExpression: jest.fn((_frame, _state) => null), - insertLayer: jest.fn((_state, _newLayerId) => {}), + insertLayer: jest.fn((_state, _newLayerId) => ({})), removeLayer: jest.fn((_state, _layerId) => {}), removeColumn: jest.fn((props) => {}), getLayers: jest.fn((_state) => []), @@ -153,8 +161,9 @@ export function createMockDatasource(id: string): DatasourceMock { }; } -const mockDatasource: DatasourceMock = createMockDatasource('testDatasource'); -const mockDatasource2: DatasourceMock = createMockDatasource('testDatasource2'); +export const mockDatasource: DatasourceMock = createMockDatasource('testDatasource'); +export const mockDatasource2: DatasourceMock = createMockDatasource('testDatasource2'); + export const datasourceMap = { testDatasource2: mockDatasource2, testDatasource: mockDatasource, @@ -251,14 +260,41 @@ export function createMockTimefilter() { }; } -export function mockDataPlugin(sessionIdSubject = new Subject()) { +export const exactMatchDoc = { + ...defaultDoc, + sharingSavedObjectProps: { + outcome: 'exactMatch', + }, +}; + +export const mockStoreDeps = (deps?: { + lensServices?: LensAppServices; + datasourceMap?: DatasourceMap; + visualizationMap?: VisualizationMap; +}) => { + return { + datasourceMap: deps?.datasourceMap || datasourceMap, + visualizationMap: deps?.visualizationMap || visualizationMap, + lensServices: deps?.lensServices || makeDefaultServices(), + }; +}; + +export function mockDataPlugin( + sessionIdSubject = new Subject(), + initialSessionId?: string +) { function createMockSearchService() { - let sessionIdCounter = 1; + let sessionIdCounter = initialSessionId ? 1 : 0; + let currentSessionId: string | undefined = initialSessionId; + const start = () => { + currentSessionId = `sessionId-${++sessionIdCounter}`; + return currentSessionId; + }; return { session: { - start: jest.fn(() => `sessionId-${sessionIdCounter++}`), + start: jest.fn(start), clear: jest.fn(), - getSessionId: jest.fn(() => `sessionId-${sessionIdCounter}`), + getSessionId: jest.fn(() => currentSessionId), getSession$: jest.fn(() => sessionIdSubject.asObservable()), }, }; @@ -296,7 +332,6 @@ export function mockDataPlugin(sessionIdSubject = new Subject()) { }, }; } - function createMockQueryString() { return { getQuery: jest.fn(() => ({ query: '', language: 'lucene' })), @@ -328,6 +363,7 @@ export function mockDataPlugin(sessionIdSubject = new Subject()) { export function makeDefaultServices( sessionIdSubject = new Subject(), + sessionId: string | undefined = undefined, doc = defaultDoc ): jest.Mocked { const core = coreMock.createStart({ basePath: '/testbasepath' }); @@ -365,13 +401,7 @@ export function makeDefaultServices( }, core ); - - attributeServiceMock.unwrapAttributes = jest.fn().mockResolvedValue({ - ...doc, - sharingSavedObjectProps: { - outcome: 'exactMatch', - }, - }); + attributeServiceMock.unwrapAttributes = jest.fn().mockResolvedValue(exactMatchDoc); attributeServiceMock.wrapAttributes = jest.fn().mockResolvedValue({ savedObjectId: (doc as unknown as LensByReferenceInput).savedObjectId, }); @@ -402,7 +432,7 @@ export function makeDefaultServices( }, getUrlForApp: jest.fn((appId: string) => `/testbasepath/app/${appId}#/`), }, - data: mockDataPlugin(sessionIdSubject), + data: mockDataPlugin(sessionIdSubject, sessionId), fieldFormats: fieldFormatsServiceMock.createStartContract(), storage: { get: jest.fn(), @@ -432,44 +462,34 @@ export const defaultState = { }; export function makeLensStore({ - data, preloadedState, dispatch, + storeDeps = mockStoreDeps(), }: { - data?: DataPublicPluginStart; + storeDeps?: LensStoreDeps; preloadedState?: Partial; dispatch?: jest.Mock; }) { - if (!data) { - data = mockDataPlugin(); - } - const lensStore = makeConfigureStore( - { - lensServices: { ...makeDefaultServices(), data }, - datasourceMap, - visualizationMap, + const data = storeDeps.lensServices.data; + const store = makeConfigureStore(storeDeps, { + lens: { + ...defaultState, + query: data.query.queryString.getQuery(), + filters: data.query.filterManager.getGlobalFilters(), + resolvedDateRange: getResolvedDateRange(data.query.timefilter.timefilter), + ...preloadedState, }, - { - lens: { - ...defaultState, - searchSessionId: data.search.session.start(), - query: data.query.queryString.getQuery(), - filters: data.query.filterManager.getGlobalFilters(), - resolvedDateRange: getResolvedDateRange(data.query.timefilter.timefilter), - ...preloadedState, - }, - } as DeepPartial - ); + } as DeepPartial); - const origDispatch = lensStore.dispatch; - lensStore.dispatch = jest.fn(dispatch || origDispatch); - return lensStore; + const origDispatch = store.dispatch; + store.dispatch = jest.fn(dispatch || origDispatch); + return { store, deps: storeDeps }; } export const mountWithProvider = async ( component: React.ReactElement, store?: { - data?: DataPublicPluginStart; + storeDeps?: LensStoreDeps; preloadedState?: Partial; dispatch?: jest.Mock; }, @@ -480,7 +500,7 @@ export const mountWithProvider = async ( attachTo?: HTMLElement; } ) => { - const lensStore = makeLensStore(store || {}); + const { store: lensStore, deps } = makeLensStore(store || {}); let wrappingComponent: React.FC<{ children: React.ReactNode; @@ -510,5 +530,5 @@ export const mountWithProvider = async ( ...restOptions, } as unknown as ReactWrapper); }); - return { instance, lensStore }; + return { instance, lensStore, deps }; }; diff --git a/x-pack/plugins/lens/public/state_management/init_middleware/__snapshots__/load_initial.test.tsx.snap b/x-pack/plugins/lens/public/state_management/__snapshots__/load_initial.test.tsx.snap similarity index 94% rename from x-pack/plugins/lens/public/state_management/init_middleware/__snapshots__/load_initial.test.tsx.snap rename to x-pack/plugins/lens/public/state_management/__snapshots__/load_initial.test.tsx.snap index 32d221e14730b..57da18d9dc92f 100644 --- a/x-pack/plugins/lens/public/state_management/init_middleware/__snapshots__/load_initial.test.tsx.snap +++ b/x-pack/plugins/lens/public/state_management/__snapshots__/load_initial.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`init_middleware should initialize all datasources with state from doc 1`] = ` +exports[`Initializing the store should initialize all datasources with state from doc 1`] = ` Object { "lens": Object { "activeDatasourceId": "testDatasource", @@ -82,7 +82,7 @@ Object { "fromDate": "2021-01-10T04:00:00.000Z", "toDate": "2021-01-10T08:00:00.000Z", }, - "searchSessionId": "sessionId-2", + "searchSessionId": "sessionId-1", "sharingSavedObjectProps": Object { "aliasTargetId": undefined, "outcome": undefined, diff --git a/x-pack/plugins/lens/public/state_management/index.ts b/x-pack/plugins/lens/public/state_management/index.ts index 1d8f4fdffa730..cc83cc612f32d 100644 --- a/x-pack/plugins/lens/public/state_management/index.ts +++ b/x-pack/plugins/lens/public/state_management/index.ts @@ -8,7 +8,7 @@ import { configureStore, getDefaultMiddleware, DeepPartial } from '@reduxjs/toolkit'; import { createLogger } from 'redux-logger'; import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux'; -import { lensSlice } from './lens_slice'; +import { makeLensReducer, lensActions } from './lens_slice'; import { timeRangeMiddleware } from './time_range_middleware'; import { optimizingMiddleware } from './optimizing_middleware'; import { LensState, LensStoreDeps } from './types'; @@ -16,10 +16,6 @@ import { initMiddleware } from './init_middleware'; export * from './types'; export * from './selectors'; -export const reducer = { - lens: lensSlice.reducer, -}; - export const { loadInitial, navigateAway, @@ -31,12 +27,12 @@ export const { updateVisualizationState, updateLayer, switchVisualization, - selectSuggestion, rollbackSuggestion, submitSuggestion, switchDatasource, setToggleFullscreen, -} = lensSlice.actions; + initEmpty, +} = lensActions; export const makeConfigureStore = ( storeDeps: LensStoreDeps, @@ -60,7 +56,9 @@ export const makeConfigureStore = ( } return configureStore({ - reducer, + reducer: { + lens: makeLensReducer(storeDeps), + }, middleware, preloadedState, }); diff --git a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.test.tsx b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.test.tsx deleted file mode 100644 index 342490e5360a5..0000000000000 --- a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.test.tsx +++ /dev/null @@ -1,410 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { - makeDefaultServices, - makeLensStore, - defaultDoc, - createMockVisualization, - createMockDatasource, -} from '../../mocks'; -import { Location, History } from 'history'; -import { act } from 'react-dom/test-utils'; -import { loadInitial } from './load_initial'; -import { LensEmbeddableInput } from '../../embeddable'; -import { getPreloadedState } from '../lens_slice'; -import { LensAppState } from '..'; -import { LensAppServices } from '../../app_plugin/types'; -import { DatasourceMap, VisualizationMap } from '../../types'; - -const defaultSavedObjectId = '1234'; -const preloadedState = { - isLoading: true, - visualization: { - state: null, - activeId: 'testVis', - }, -}; - -const exactMatchDoc = { - ...defaultDoc, - sharingSavedObjectProps: { - outcome: 'exactMatch', - }, -}; - -const getDefaultLensServices = () => { - const lensServices = makeDefaultServices(); - lensServices.attributeService.unwrapAttributes = jest.fn().mockResolvedValue(exactMatchDoc); - return lensServices; -}; - -const getStoreDeps = (deps?: { - lensServices?: LensAppServices; - datasourceMap?: DatasourceMap; - visualizationMap?: VisualizationMap; -}) => { - const lensServices = deps?.lensServices || getDefaultLensServices(); - const datasourceMap = deps?.datasourceMap || { - testDatasource2: createMockDatasource('testDatasource2'), - testDatasource: createMockDatasource('testDatasource'), - }; - const visualizationMap = deps?.visualizationMap || { - testVis: { - ...createMockVisualization(), - id: 'testVis', - visualizationTypes: [ - { - icon: 'empty', - id: 'testVis', - label: 'TEST1', - groupLabel: 'testVisGroup', - }, - ], - }, - testVis2: { - ...createMockVisualization(), - id: 'testVis2', - visualizationTypes: [ - { - icon: 'empty', - id: 'testVis2', - label: 'TEST2', - groupLabel: 'testVis2Group', - }, - ], - }, - }; - return { - datasourceMap, - visualizationMap, - lensServices, - }; -}; - -describe('init_middleware', () => { - it('should initialize initial datasource', async () => { - const storeDeps = getStoreDeps(); - const { lensServices, datasourceMap } = storeDeps; - - const lensStore = await makeLensStore({ - data: lensServices.data, - preloadedState, - }); - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: { savedObjectId: defaultSavedObjectId } as unknown as LensEmbeddableInput, - }); - }); - expect(datasourceMap.testDatasource.initialize).toHaveBeenCalled(); - }); - - it('should have initialized the initial datasource and visualization', async () => { - const storeDeps = getStoreDeps(); - const { lensServices, datasourceMap, visualizationMap } = storeDeps; - - const lensStore = await makeLensStore({ data: lensServices.data, preloadedState }); - await act(async () => { - await loadInitial(lensStore, storeDeps, { redirectCallback: jest.fn() }); - }); - expect(datasourceMap.testDatasource.initialize).toHaveBeenCalled(); - expect(datasourceMap.testDatasource2.initialize).not.toHaveBeenCalled(); - expect(visualizationMap.testVis.initialize).toHaveBeenCalled(); - expect(visualizationMap.testVis2.initialize).not.toHaveBeenCalled(); - }); - - it('should initialize all datasources with state from doc', async () => { - const datasource1State = { datasource1: '' }; - const datasource2State = { datasource2: '' }; - const services = makeDefaultServices(); - services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({ - exactMatchDoc, - visualizationType: 'testVis', - title: '', - state: { - datasourceStates: { - testDatasource: datasource1State, - testDatasource2: datasource2State, - }, - visualization: {}, - query: { query: '', language: 'lucene' }, - filters: [], - }, - references: [], - }); - - const storeDeps = getStoreDeps({ - lensServices: services, - visualizationMap: { - testVis: { - ...createMockVisualization(), - id: 'testVis', - visualizationTypes: [ - { - icon: 'empty', - id: 'testVis', - label: 'TEST1', - groupLabel: 'testVisGroup', - }, - ], - }, - }, - datasourceMap: { - testDatasource: createMockDatasource('testDatasource'), - testDatasource2: createMockDatasource('testDatasource2'), - testDatasource3: createMockDatasource('testDatasource3'), - }, - }); - const { datasourceMap } = storeDeps; - - const lensStore = await makeLensStore({ - data: services.data, - preloadedState, - }); - - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: { savedObjectId: defaultSavedObjectId } as unknown as LensEmbeddableInput, - }); - }); - expect(datasourceMap.testDatasource.initialize).toHaveBeenCalled(); - - expect(datasourceMap.testDatasource.initialize).toHaveBeenCalledWith( - datasource1State, - [], - undefined, - { - isFullEditor: true, - } - ); - expect(datasourceMap.testDatasource2.initialize).toHaveBeenCalledWith( - datasource2State, - [], - undefined, - { - isFullEditor: true, - } - ); - expect(datasourceMap.testDatasource3.initialize).not.toHaveBeenCalled(); - expect(lensStore.getState()).toMatchSnapshot(); - }); - - describe('loadInitial', () => { - it('does not load a document if there is no initial input', async () => { - const storeDeps = getStoreDeps(); - const { lensServices } = storeDeps; - - const lensStore = makeLensStore({ data: lensServices.data, preloadedState }); - await loadInitial(lensStore, storeDeps, { redirectCallback: jest.fn() }); - expect(lensServices.attributeService.unwrapAttributes).not.toHaveBeenCalled(); - }); - - it('cleans datasource and visualization state properly when reloading', async () => { - const storeDeps = getStoreDeps(); - const lensStore = await makeLensStore({ - data: storeDeps.lensServices.data, - preloadedState: { - ...preloadedState, - visualization: { - activeId: 'testVis', - state: {}, - }, - datasourceStates: { testDatasource: { isLoading: false, state: {} } }, - }, - }); - - expect(lensStore.getState()).toEqual({ - lens: expect.objectContaining({ - visualization: { - activeId: 'testVis', - state: {}, - }, - activeDatasourceId: 'testDatasource', - datasourceStates: { - testDatasource: { isLoading: false, state: {} }, - }, - }), - }); - - const emptyState = getPreloadedState(storeDeps) as LensAppState; - storeDeps.lensServices.attributeService.unwrapAttributes = jest.fn(); - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: undefined, - emptyState, - }); - }); - - expect(lensStore.getState()).toEqual({ - lens: expect.objectContaining({ - visualization: { - activeId: 'testVis', - state: null, // resets to null - }, - activeDatasourceId: 'testDatasource2', // resets to first on the list - datasourceStates: { - testDatasource: { isLoading: false, state: undefined }, // state resets to undefined - }, - }), - }); - }); - - it('loads a document and uses query and filters if initial input is provided', async () => { - const storeDeps = getStoreDeps(); - const { lensServices } = storeDeps; - const emptyState = getPreloadedState(storeDeps) as LensAppState; - - const lensStore = await makeLensStore({ data: lensServices.data, preloadedState }); - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: { - savedObjectId: defaultSavedObjectId, - } as unknown as LensEmbeddableInput, - emptyState, - }); - }); - - expect(lensServices.attributeService.unwrapAttributes).toHaveBeenCalledWith({ - savedObjectId: defaultSavedObjectId, - }); - - expect(lensServices.data.query.filterManager.setAppFilters).toHaveBeenCalledWith([ - { query: { match_phrase: { src: 'test' } } }, - ]); - - expect(lensStore.getState()).toEqual({ - lens: expect.objectContaining({ - persistedDoc: { ...defaultDoc, type: 'lens' }, - query: 'kuery', - isLoading: false, - activeDatasourceId: 'testDatasource', - }), - }); - }); - - it('does not load documents on sequential renders unless the id changes', async () => { - const storeDeps = getStoreDeps(); - const { lensServices } = storeDeps; - - const lensStore = makeLensStore({ data: lensServices.data, preloadedState }); - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: { - savedObjectId: defaultSavedObjectId, - } as unknown as LensEmbeddableInput, - }); - }); - - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: { - savedObjectId: defaultSavedObjectId, - } as unknown as LensEmbeddableInput, - }); - }); - - expect(lensServices.attributeService.unwrapAttributes).toHaveBeenCalledTimes(1); - - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: { savedObjectId: '5678' } as unknown as LensEmbeddableInput, - }); - }); - - expect(lensServices.attributeService.unwrapAttributes).toHaveBeenCalledTimes(2); - }); - - it('handles document load errors', async () => { - const services = makeDefaultServices(); - services.attributeService.unwrapAttributes = jest.fn().mockRejectedValue('failed to load'); - - const storeDeps = getStoreDeps({ lensServices: services }); - const { lensServices } = storeDeps; - - const redirectCallback = jest.fn(); - - const lensStore = makeLensStore({ data: lensServices.data, preloadedState }); - - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback, - initialInput: { - savedObjectId: defaultSavedObjectId, - } as unknown as LensEmbeddableInput, - }); - }); - expect(lensServices.attributeService.unwrapAttributes).toHaveBeenCalledWith({ - savedObjectId: defaultSavedObjectId, - }); - expect(lensServices.notifications.toasts.addDanger).toHaveBeenCalled(); - expect(redirectCallback).toHaveBeenCalled(); - }); - - it('redirects if saved object is an aliasMatch', async () => { - const services = makeDefaultServices(); - services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({ - ...defaultDoc, - sharingSavedObjectProps: { - outcome: 'aliasMatch', - aliasTargetId: 'id2', - }, - }); - - const storeDeps = getStoreDeps({ lensServices: services }); - const lensStore = makeLensStore({ data: storeDeps.lensServices.data, preloadedState }); - - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: { - savedObjectId: defaultSavedObjectId, - } as unknown as LensEmbeddableInput, - history: { - location: { - search: '?search', - } as Location, - } as History, - }); - }); - expect(storeDeps.lensServices.attributeService.unwrapAttributes).toHaveBeenCalledWith({ - savedObjectId: defaultSavedObjectId, - }); - - expect(storeDeps.lensServices.spaces.ui.redirectLegacyUrl).toHaveBeenCalledWith( - '#/edit/id2?search', - 'Lens visualization' - ); - }); - - it('adds to the recently accessed list on load', async () => { - const storeDeps = getStoreDeps(); - const { lensServices } = storeDeps; - - const lensStore = makeLensStore({ data: lensServices.data, preloadedState }); - await act(async () => { - await loadInitial(lensStore, storeDeps, { - redirectCallback: jest.fn(), - initialInput: { - savedObjectId: defaultSavedObjectId, - } as unknown as LensEmbeddableInput, - }); - }); - - expect(lensServices.chrome.recentlyAccessed.add).toHaveBeenCalledWith( - '/app/lens#/edit/1234', - 'An extremely cool default document!', - '1234' - ); - }); - }); -}); diff --git a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts index 7db03a17a3a8f..314434a16af8c 100644 --- a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts +++ b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts @@ -9,17 +9,11 @@ import { MiddlewareAPI } from '@reduxjs/toolkit'; import { isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; import { History } from 'history'; -import { LensAppState, setState } from '..'; -import { updateLayer, updateVisualizationState, LensStoreDeps } from '..'; +import { LensAppState, setState, initEmpty, LensStoreDeps } from '..'; import { SharingSavedObjectProps } from '../../types'; import { LensEmbeddableInput, LensByReferenceInput } from '../../embeddable/embeddable'; import { getInitialDatasourceId } from '../../utils'; import { initializeDatasources } from '../../editor_frame_service/editor_frame'; -import { generateId } from '../../id_generator'; -import { - getVisualizeFieldSuggestions, - switchToSuggestion, -} from '../../editor_frame_service/editor_frame/suggestion_helpers'; import { LensAppServices } from '../../app_plugin/types'; import { getEditPath, getFullPath, LENS_EMBEDDABLE_TYPE } from '../../../common/constants'; import { Document, injectFilterReferences } from '../../persistence'; @@ -89,13 +83,7 @@ export const getPersisted = async ({ export function loadInitial( store: MiddlewareAPI, - { - lensServices, - datasourceMap, - visualizationMap, - embeddableEditorIncomingState, - initialContext, - }: LensStoreDeps, + { lensServices, datasourceMap, embeddableEditorIncomingState, initialContext }: LensStoreDeps, { redirectCallback, initialInput, @@ -108,78 +96,39 @@ export function loadInitial( history?: History; } ) { - const { getState, dispatch } = store; const { attributeService, notifications, data, dashboardFeatureFlag } = lensServices; - const { persistedDoc } = getState().lens; + const currentSessionId = data.search.session.getSessionId(); + const { lens } = store.getState(); if ( !initialInput || (attributeService.inputIsRefType(initialInput) && - initialInput.savedObjectId === persistedDoc?.savedObjectId) + initialInput.savedObjectId === lens.persistedDoc?.savedObjectId) ) { - return initializeDatasources( - datasourceMap, - getState().lens.datasourceStates, - undefined, - initialContext, - { - isFullEditor: true, - } - ) + return initializeDatasources(datasourceMap, lens.datasourceStates, undefined, initialContext, { + isFullEditor: true, + }) .then((result) => { - const datasourceStates = Object.entries(result).reduce( - (state, [datasourceId, datasourceState]) => ({ - ...state, - [datasourceId]: { - ...datasourceState, + store.dispatch( + initEmpty({ + newState: { + ...emptyState, + searchSessionId: currentSessionId || data.search.session.start(), + datasourceStates: Object.entries(result).reduce( + (state, [datasourceId, datasourceState]) => ({ + ...state, + [datasourceId]: { + ...datasourceState, + isLoading: false, + }, + }), + {} + ), isLoading: false, }, - }), - {} - ); - dispatch( - setState({ - ...emptyState, - datasourceStates, - isLoading: false, + initialContext, }) ); - if (initialContext) { - const selectedSuggestion = getVisualizeFieldSuggestions({ - datasourceMap, - datasourceStates, - visualizationMap, - activeVisualization: visualizationMap?.[Object.keys(visualizationMap)[0]] || null, - visualizationState: null, - visualizeTriggerFieldContext: initialContext, - }); - if (selectedSuggestion) { - switchToSuggestion(dispatch, selectedSuggestion, 'SWITCH_VISUALIZATION'); - } - } - const activeDatasourceId = getInitialDatasourceId(datasourceMap); - const visualization = getState().lens.visualization; - const activeVisualization = - visualization.activeId && visualizationMap[visualization.activeId]; - - if (visualization.state === null && activeVisualization) { - const newLayerId = generateId(); - - const initialVisualizationState = activeVisualization.initialize(() => newLayerId); - dispatch( - updateLayer({ - datasourceId: activeDatasourceId!, - layerId: newLayerId, - updater: datasourceMap[activeDatasourceId!].insertLayer, - }) - ); - dispatch( - updateVisualizationState({ - visualizationId: activeVisualization.id, - updater: initialVisualizationState, - }) - ); - } }) .catch((e: { message: string }) => { notifications.toasts.addDanger({ @@ -188,6 +137,7 @@ export function loadInitial( redirectCallback(); }); } + getPersisted({ initialInput, lensServices, history }) .then( (persisted) => { @@ -226,11 +176,7 @@ export function loadInitial( } ) .then((result) => { - const activeDatasourceId = getInitialDatasourceId(datasourceMap, doc); - - const currentSessionId = data.search.session.getSessionId(); - - dispatch( + store.dispatch( setState({ sharingSavedObjectProps, query: doc.state.query, @@ -241,8 +187,8 @@ export function loadInitial( currentSessionId ? currentSessionId : data.search.session.start(), - ...(!isEqual(persistedDoc, doc) ? { persistedDoc: doc } : null), - activeDatasourceId, + ...(!isEqual(lens.persistedDoc, doc) ? { persistedDoc: doc } : null), + activeDatasourceId: getInitialDatasourceId(datasourceMap, doc), visualization: { activeId: doc.visualizationType, state: doc.state.visualization, @@ -271,7 +217,7 @@ export function loadInitial( } }, () => { - dispatch( + store.dispatch( setState({ isLoading: false, }) @@ -279,9 +225,10 @@ export function loadInitial( redirectCallback(); } ) - .catch((e: { message: string }) => + .catch((e: { message: string }) => { notifications.toasts.addDanger({ title: e.message, - }) - ); + }); + redirectCallback(); + }); } diff --git a/x-pack/plugins/lens/public/state_management/lens_slice.test.ts b/x-pack/plugins/lens/public/state_management/lens_slice.test.ts index cce0376707143..7d88e6ceb616c 100644 --- a/x-pack/plugins/lens/public/state_management/lens_slice.test.ts +++ b/x-pack/plugins/lens/public/state_management/lens_slice.test.ts @@ -17,13 +17,9 @@ import { import { makeLensStore, defaultState } from '../mocks'; describe('lensSlice', () => { - const store = makeLensStore({}); + const { store } = makeLensStore({}); const customQuery = { query: 'custom' } as Query; - // TODO: need to move some initialization logic from mounter - // describe('initialization', () => { - // }) - describe('state update', () => { it('setState: updates state ', () => { const lensState = store.getState().lens; @@ -79,8 +75,11 @@ describe('lensSlice', () => { const newVisState = {}; store.dispatch( switchVisualization({ - newVisualizationId: 'testVis2', - initialState: newVisState, + suggestion: { + newVisualizationId: 'testVis2', + visualizationState: newVisState, + }, + clearStagedPreview: true, }) ); @@ -93,10 +92,13 @@ describe('lensSlice', () => { store.dispatch( switchVisualization({ - newVisualizationId: 'testVis2', - initialState: newVisState, - datasourceState: newDatasourceState, - datasourceId: 'testDatasource', + suggestion: { + newVisualizationId: 'testVis2', + visualizationState: newVisState, + datasourceState: newDatasourceState, + datasourceId: 'testDatasource', + }, + clearStagedPreview: true, }) ); @@ -117,7 +119,7 @@ describe('lensSlice', () => { it('not initialize already initialized datasource on switch', () => { const datasource2State = {}; - const customStore = makeLensStore({ + const { store: customStore } = makeLensStore({ preloadedState: { datasourceStates: { testDatasource: { diff --git a/x-pack/plugins/lens/public/state_management/lens_slice.ts b/x-pack/plugins/lens/public/state_management/lens_slice.ts index 6cf0529b34575..0461070020055 100644 --- a/x-pack/plugins/lens/public/state_management/lens_slice.ts +++ b/x-pack/plugins/lens/public/state_management/lens_slice.ts @@ -5,12 +5,18 @@ * 2.0. */ -import { createSlice, current, PayloadAction } from '@reduxjs/toolkit'; +import { createAction, createReducer, current, PayloadAction } from '@reduxjs/toolkit'; +import { VisualizeFieldContext } from 'src/plugins/ui_actions/public'; import { History } from 'history'; import { LensEmbeddableInput } from '..'; import { TableInspectorAdapter } from '../editor_frame_service/types'; import { getInitialDatasourceId, getResolvedDateRange } from '../utils'; import { LensAppState, LensStoreDeps } from './types'; +import { generateId } from '../id_generator'; +import { + getVisualizeFieldSuggestions, + Suggestion, +} from '../editor_frame_service/editor_frame/suggestion_helpers'; export const initialState: LensAppState = { persistedDoc: undefined, @@ -68,29 +74,105 @@ export const getPreloadedState = ({ return state; }; -export const lensSlice = createSlice({ - name: 'lens', - initialState, - reducers: { - setState: (state, { payload }: PayloadAction>) => { +export const setState = createAction>('lens/setState'); +export const onActiveDataChange = createAction('lens/onActiveDataChange'); +export const setSaveable = createAction('lens/setSaveable'); +export const updateState = createAction<{ + subType: string; + updater: (prevState: LensAppState) => LensAppState; +}>('lens/updateState'); +export const updateDatasourceState = createAction<{ + updater: unknown | ((prevState: unknown) => unknown); + datasourceId: string; + clearStagedPreview?: boolean; +}>('lens/updateDatasourceState'); +export const updateVisualizationState = createAction<{ + visualizationId: string; + updater: unknown; + clearStagedPreview?: boolean; +}>('lens/updateVisualizationState'); + +export const updateLayer = createAction<{ + layerId: string; + datasourceId: string; + updater: (state: unknown, layerId: string) => unknown; +}>('lens/updateLayer'); + +export const switchVisualization = createAction<{ + suggestion: { + newVisualizationId: string; + visualizationState: unknown; + datasourceState?: unknown; + datasourceId?: string; + }; + clearStagedPreview?: boolean; +}>('lens/switchVisualization'); +export const rollbackSuggestion = createAction('lens/rollbackSuggestion'); +export const setToggleFullscreen = createAction('lens/setToggleFullscreen'); +export const submitSuggestion = createAction('lens/submitSuggestion'); +export const switchDatasource = createAction<{ + newDatasourceId: string; +}>('lens/switchDatasource'); +export const navigateAway = createAction('lens/navigateAway'); +export const loadInitial = createAction<{ + initialInput?: LensEmbeddableInput; + redirectCallback: (savedObjectId?: string) => void; + emptyState: LensAppState; + history: History; +}>('lens/loadInitial'); +export const initEmpty = createAction( + 'initEmpty', + function prepare({ + newState, + initialContext, + }: { + newState: Partial; + initialContext?: VisualizeFieldContext; + }) { + return { payload: { layerId: generateId(), newState, initialContext } }; + } +); + +export const lensActions = { + setState, + onActiveDataChange, + setSaveable, + updateState, + updateDatasourceState, + updateVisualizationState, + updateLayer, + switchVisualization, + rollbackSuggestion, + setToggleFullscreen, + submitSuggestion, + switchDatasource, + navigateAway, + loadInitial, + initEmpty, +}; + +export const makeLensReducer = (storeDeps: LensStoreDeps) => { + const { datasourceMap, visualizationMap } = storeDeps; + return createReducer(initialState, { + [setState.type]: (state, { payload }: PayloadAction>) => { return { ...state, ...payload, }; }, - onActiveDataChange: (state, { payload }: PayloadAction) => { + [onActiveDataChange.type]: (state, { payload }: PayloadAction) => { return { ...state, activeData: payload, }; }, - setSaveable: (state, { payload }: PayloadAction) => { + [setSaveable.type]: (state, { payload }: PayloadAction) => { return { ...state, isSaveable: payload, }; }, - updateState: ( + [updateState.type]: ( state, action: { payload: { @@ -101,7 +183,7 @@ export const lensSlice = createSlice({ ) => { return action.payload.updater(current(state) as LensAppState); }, - updateDatasourceState: ( + [updateDatasourceState.type]: ( state, { payload, @@ -128,7 +210,7 @@ export const lensSlice = createSlice({ stagedPreview: payload.clearStagedPreview ? undefined : state.stagedPreview, }; }, - updateVisualizationState: ( + [updateVisualizationState.type]: ( state, { payload, @@ -161,7 +243,7 @@ export const lensSlice = createSlice({ stagedPreview: payload.clearStagedPreview ? undefined : state.stagedPreview, }; }, - updateLayer: ( + [updateLayer.type]: ( state, { payload, @@ -188,92 +270,65 @@ export const lensSlice = createSlice({ }; }, - switchVisualization: ( - state, - { - payload, - }: { - payload: { - newVisualizationId: string; - initialState: unknown; - datasourceState?: unknown; - datasourceId?: string; - }; - } - ) => { - return { - ...state, - datasourceStates: - 'datasourceId' in payload && payload.datasourceId - ? { - ...state.datasourceStates, - [payload.datasourceId]: { - ...state.datasourceStates[payload.datasourceId], - state: payload.datasourceState, - }, - } - : state.datasourceStates, - visualization: { - ...state.visualization, - activeId: payload.newVisualizationId, - state: payload.initialState, - }, - stagedPreview: undefined, - }; - }, - selectSuggestion: ( + [switchVisualization.type]: ( state, { payload, }: { payload: { - newVisualizationId: string; - initialState: unknown; - datasourceState: unknown; - datasourceId: string; + suggestion: { + newVisualizationId: string; + visualizationState: unknown; + datasourceState?: unknown; + datasourceId?: string; + }; + clearStagedPreview?: boolean; }; } ) => { + const { newVisualizationId, visualizationState, datasourceState, datasourceId } = + payload.suggestion; return { ...state, - datasourceStates: - 'datasourceId' in payload && payload.datasourceId - ? { - ...state.datasourceStates, - [payload.datasourceId]: { - ...state.datasourceStates[payload.datasourceId], - state: payload.datasourceState, - }, - } - : state.datasourceStates, + datasourceStates: datasourceId + ? { + ...state.datasourceStates, + [datasourceId]: { + ...state.datasourceStates[datasourceId], + state: datasourceState, + }, + } + : state.datasourceStates, visualization: { ...state.visualization, - activeId: payload.newVisualizationId, - state: payload.initialState, - }, - stagedPreview: state.stagedPreview || { - datasourceStates: state.datasourceStates, - visualization: state.visualization, + activeId: newVisualizationId, + state: visualizationState, }, + stagedPreview: payload.clearStagedPreview + ? undefined + : state.stagedPreview || { + datasourceStates: state.datasourceStates, + visualization: state.visualization, + }, }; }, - rollbackSuggestion: (state) => { + [rollbackSuggestion.type]: (state) => { return { ...state, ...(state.stagedPreview || {}), stagedPreview: undefined, }; }, - setToggleFullscreen: (state) => { + [setToggleFullscreen.type]: (state) => { return { ...state, isFullscreenDatasource: !state.isFullscreenDatasource }; }, - submitSuggestion: (state) => { + [submitSuggestion.type]: (state) => { return { ...state, stagedPreview: undefined, }; }, - switchDatasource: ( + [switchDatasource.type]: ( state, { payload, @@ -295,8 +350,8 @@ export const lensSlice = createSlice({ activeDatasourceId: payload.newDatasourceId, }; }, - navigateAway: (state) => state, - loadInitial: ( + [navigateAway.type]: (state) => state, + [loadInitial.type]: ( state, payload: PayloadAction<{ initialInput?: LensEmbeddableInput; @@ -305,9 +360,78 @@ export const lensSlice = createSlice({ history: History; }> ) => state, - }, -}); + [initEmpty.type]: ( + state, + { + payload, + }: { + payload: { + newState: Partial; + initialContext: VisualizeFieldContext | undefined; + layerId: string; + }; + } + ) => { + const newState = { + ...state, + ...payload.newState, + }; + const suggestion: Suggestion | undefined = getVisualizeFieldSuggestions({ + datasourceMap, + datasourceStates: newState.datasourceStates, + visualizationMap, + visualizeTriggerFieldContext: payload.initialContext, + }); + if (suggestion) { + return { + ...newState, + datasourceStates: { + ...newState.datasourceStates, + [suggestion.datasourceId!]: { + ...newState.datasourceStates[suggestion.datasourceId!], + state: suggestion.datasourceState, + }, + }, + visualization: { + ...newState.visualization, + activeId: suggestion.visualizationId, + state: suggestion.visualizationState, + }, + stagedPreview: undefined, + }; + } + + const visualization = newState.visualization; + + if (!visualization.activeId) { + throw new Error('Invariant: visualization state got updated without active visualization'); + } -export const reducer = { - lens: lensSlice.reducer, + const activeVisualization = visualizationMap[visualization.activeId]; + if (visualization.state === null && activeVisualization) { + const activeDatasourceId = getInitialDatasourceId(datasourceMap)!; + const newVisState = activeVisualization.initialize(() => payload.layerId); + const activeDatasource = datasourceMap[activeDatasourceId]; + return { + ...newState, + activeDatasourceId, + datasourceStates: { + ...newState.datasourceStates, + [activeDatasourceId]: { + ...newState.datasourceStates[activeDatasourceId], + state: activeDatasource.insertLayer( + newState.datasourceStates[activeDatasourceId]?.state, + payload.layerId + ), + }, + }, + visualization: { + ...visualization, + state: newVisState, + }, + }; + } + return newState; + }, + }); }; diff --git a/x-pack/plugins/lens/public/state_management/load_initial.test.tsx b/x-pack/plugins/lens/public/state_management/load_initial.test.tsx new file mode 100644 index 0000000000000..fe4c553ce4bd7 --- /dev/null +++ b/x-pack/plugins/lens/public/state_management/load_initial.test.tsx @@ -0,0 +1,323 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { + makeDefaultServices, + makeLensStore, + defaultDoc, + createMockVisualization, + createMockDatasource, + mockStoreDeps, + exactMatchDoc, +} from '../mocks'; +import { Location, History } from 'history'; +import { act } from 'react-dom/test-utils'; +import { LensEmbeddableInput } from '../embeddable'; +import { getPreloadedState, initialState, loadInitial } from './lens_slice'; +import { LensAppState } from '.'; + +const history = { + location: { + search: '?search', + } as Location, +} as History; + +const defaultSavedObjectId = '1234'; +const preloadedState = { + isLoading: true, + visualization: { + state: null, + activeId: 'testVis', + }, +}; + +const defaultProps = { + redirectCallback: jest.fn(), + initialInput: { savedObjectId: defaultSavedObjectId } as unknown as LensEmbeddableInput, + history, + emptyState: initialState, +}; + +describe('Initializing the store', () => { + it('should initialize initial datasource', async () => { + const { store, deps } = await makeLensStore({ preloadedState }); + await act(async () => { + await store.dispatch(loadInitial(defaultProps)); + }); + expect(deps.datasourceMap.testDatasource.initialize).toHaveBeenCalled(); + }); + + it('should have initialized the initial datasource and visualization', async () => { + const { store, deps } = await makeLensStore({ preloadedState }); + const emptyState = getPreloadedState(deps) as LensAppState; + await act(async () => { + await store.dispatch(loadInitial({ ...defaultProps, initialInput: undefined, emptyState })); + }); + expect(deps.datasourceMap.testDatasource.initialize).toHaveBeenCalled(); + expect(deps.datasourceMap.testDatasource2.initialize).not.toHaveBeenCalled(); + expect(deps.visualizationMap.testVis.initialize).toHaveBeenCalled(); + expect(deps.visualizationMap.testVis2.initialize).not.toHaveBeenCalled(); + }); + + it('should initialize all datasources with state from doc', async () => { + const datasource1State = { datasource1: '' }; + const datasource2State = { datasource2: '' }; + const services = makeDefaultServices(); + services.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({ + exactMatchDoc, + visualizationType: 'testVis', + title: '', + state: { + datasourceStates: { + testDatasource: datasource1State, + testDatasource2: datasource2State, + }, + visualization: {}, + query: { query: '', language: 'lucene' }, + filters: [], + }, + references: [], + }); + + const storeDeps = mockStoreDeps({ + lensServices: services, + visualizationMap: { + testVis: { + ...createMockVisualization(), + id: 'testVis', + visualizationTypes: [ + { + icon: 'empty', + id: 'testVis', + label: 'TEST1', + groupLabel: 'testVisGroup', + }, + ], + }, + }, + datasourceMap: { + testDatasource: createMockDatasource('testDatasource'), + testDatasource2: createMockDatasource('testDatasource2'), + testDatasource3: createMockDatasource('testDatasource3'), + }, + }); + + const { store, deps } = await makeLensStore({ + storeDeps, + preloadedState, + }); + + await act(async () => { + await store.dispatch(loadInitial(defaultProps)); + }); + const { datasourceMap } = deps; + expect(datasourceMap.testDatasource.initialize).toHaveBeenCalled(); + + expect(datasourceMap.testDatasource.initialize).toHaveBeenCalledWith( + datasource1State, + [], + undefined, + { + isFullEditor: true, + } + ); + expect(datasourceMap.testDatasource2.initialize).toHaveBeenCalledWith( + datasource2State, + [], + undefined, + { + isFullEditor: true, + } + ); + expect(datasourceMap.testDatasource3.initialize).not.toHaveBeenCalled(); + expect(store.getState()).toMatchSnapshot(); + }); + + describe('loadInitial', () => { + it('does not load a document if there is no initial input', async () => { + const { deps, store } = makeLensStore({ preloadedState }); + await act(async () => { + await store.dispatch( + loadInitial({ + ...defaultProps, + initialInput: undefined, + }) + ); + }); + expect(deps.lensServices.attributeService.unwrapAttributes).not.toHaveBeenCalled(); + }); + + it('starts new searchSessionId', async () => { + const { store } = await makeLensStore({ preloadedState }); + await act(async () => { + await store.dispatch(loadInitial(defaultProps)); + }); + expect(store.getState()).toEqual({ + lens: expect.objectContaining({ + searchSessionId: 'sessionId-1', + }), + }); + }); + + it('cleans datasource and visualization state properly when reloading', async () => { + const { store, deps } = await makeLensStore({ + preloadedState: { + ...preloadedState, + visualization: { + activeId: 'testVis', + state: {}, + }, + datasourceStates: { testDatasource: { isLoading: false, state: {} } }, + }, + }); + + expect(store.getState()).toEqual({ + lens: expect.objectContaining({ + visualization: { + activeId: 'testVis', + state: {}, + }, + activeDatasourceId: 'testDatasource', + datasourceStates: { + testDatasource: { isLoading: false, state: {} }, + }, + }), + }); + + const emptyState = getPreloadedState(deps) as LensAppState; + + await act(async () => { + await store.dispatch( + loadInitial({ + ...defaultProps, + emptyState, + initialInput: undefined, + }) + ); + }); + + expect(deps.visualizationMap.testVis.initialize).toHaveBeenCalled(); + expect(store.getState()).toEqual({ + lens: expect.objectContaining({ + visualization: { + state: { newState: 'newState' }, // new vis gets initialized + activeId: 'testVis', + }, + activeDatasourceId: 'testDatasource2', // resets to first on the list + datasourceStates: { + testDatasource: { isLoading: false, state: undefined }, // state resets to undefined + testDatasource2: { + state: {}, // initializes first in the map + }, + }, + }), + }); + }); + + it('loads a document and uses query and filters if initial input is provided', async () => { + const { store, deps } = await makeLensStore({ preloadedState }); + await act(async () => { + await store.dispatch(loadInitial(defaultProps)); + }); + + expect(deps.lensServices.attributeService.unwrapAttributes).toHaveBeenCalledWith({ + savedObjectId: defaultSavedObjectId, + }); + + expect(deps.lensServices.data.query.filterManager.setAppFilters).toHaveBeenCalledWith([ + { query: { match_phrase: { src: 'test' } } }, + ]); + + expect(store.getState()).toEqual({ + lens: expect.objectContaining({ + persistedDoc: { ...defaultDoc, type: 'lens' }, + query: 'kuery', + isLoading: false, + activeDatasourceId: 'testDatasource', + }), + }); + }); + + it('does not load documents on sequential renders unless the id changes', async () => { + const { store, deps } = makeLensStore({ preloadedState }); + + await act(async () => { + await store.dispatch(loadInitial(defaultProps)); + }); + + await act(async () => { + await store.dispatch(loadInitial(defaultProps)); + }); + + expect(deps.lensServices.attributeService.unwrapAttributes).toHaveBeenCalledTimes(1); + + await act(async () => { + await store.dispatch( + loadInitial({ + ...defaultProps, + initialInput: { savedObjectId: '5678' } as unknown as LensEmbeddableInput, + }) + ); + }); + + expect(deps.lensServices.attributeService.unwrapAttributes).toHaveBeenCalledTimes(2); + }); + + it('handles document load errors', async () => { + const { store, deps } = makeLensStore({ preloadedState }); + + deps.lensServices.attributeService.unwrapAttributes = jest + .fn() + .mockRejectedValue('failed to load'); + const redirectCallback = jest.fn(); + await act(async () => { + await store.dispatch(loadInitial({ ...defaultProps, redirectCallback })); + }); + + expect(deps.lensServices.attributeService.unwrapAttributes).toHaveBeenCalledWith({ + savedObjectId: defaultSavedObjectId, + }); + expect(deps.lensServices.notifications.toasts.addDanger).toHaveBeenCalled(); + expect(redirectCallback).toHaveBeenCalled(); + }); + + it('redirects if saved object is an aliasMatch', async () => { + const { store, deps } = makeLensStore({ preloadedState }); + deps.lensServices.attributeService.unwrapAttributes = jest.fn().mockResolvedValue({ + ...defaultDoc, + sharingSavedObjectProps: { + outcome: 'aliasMatch', + aliasTargetId: 'id2', + }, + }); + + await act(async () => { + await store.dispatch(loadInitial(defaultProps)); + }); + + expect(deps.lensServices.attributeService.unwrapAttributes).toHaveBeenCalledWith({ + savedObjectId: defaultSavedObjectId, + }); + expect(deps.lensServices.spaces.ui.redirectLegacyUrl).toHaveBeenCalledWith( + '#/edit/id2?search', + 'Lens visualization' + ); + }); + + it('adds to the recently accessed list on load', async () => { + const { store, deps } = makeLensStore({ preloadedState }); + await act(async () => { + await store.dispatch(loadInitial(defaultProps)); + }); + + expect(deps.lensServices.chrome.recentlyAccessed.add).toHaveBeenCalledWith( + '/app/lens#/edit/1234', + 'An extremely cool default document!', + '1234' + ); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/state_management/time_range_middleware.test.ts b/x-pack/plugins/lens/public/state_management/time_range_middleware.test.ts index ddf50f6fd0d82..8ad6a300beaa4 100644 --- a/x-pack/plugins/lens/public/state_management/time_range_middleware.test.ts +++ b/x-pack/plugins/lens/public/state_management/time_range_middleware.test.ts @@ -14,117 +14,12 @@ import { timeRangeMiddleware } from './time_range_middleware'; -import { Observable, Subject } from 'rxjs'; -import { DataPublicPluginStart, esFilters } from '../../../../../src/plugins/data/public'; +import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; import moment from 'moment'; import { initialState } from './lens_slice'; import { LensAppState } from './types'; import { PayloadAction } from '@reduxjs/toolkit'; - -const sessionIdSubject = new Subject(); - -function createMockSearchService() { - let sessionIdCounter = 1; - return { - session: { - start: jest.fn(() => `sessionId-${sessionIdCounter++}`), - clear: jest.fn(), - getSessionId: jest.fn(() => `sessionId-${sessionIdCounter}`), - getSession$: jest.fn(() => sessionIdSubject.asObservable()), - }, - }; -} - -function createMockFilterManager() { - const unsubscribe = jest.fn(); - - let subscriber: () => void; - let filters: unknown = []; - - return { - getUpdates$: () => ({ - subscribe: ({ next }: { next: () => void }) => { - subscriber = next; - return unsubscribe; - }, - }), - setFilters: jest.fn((newFilters: unknown[]) => { - filters = newFilters; - if (subscriber) subscriber(); - }), - setAppFilters: jest.fn((newFilters: unknown[]) => { - filters = newFilters; - if (subscriber) subscriber(); - }), - getFilters: () => filters, - getGlobalFilters: () => { - // @ts-ignore - return filters.filter(esFilters.isFilterPinned); - }, - removeAll: () => { - filters = []; - subscriber(); - }, - }; -} - -function createMockQueryString() { - return { - getQuery: jest.fn(() => ({ query: '', language: 'kuery' })), - setQuery: jest.fn(), - getDefaultQuery: jest.fn(() => ({ query: '', language: 'kuery' })), - }; -} - -function createMockTimefilter() { - const unsubscribe = jest.fn(); - - let timeFilter = { from: 'now-7d', to: 'now' }; - let subscriber: () => void; - return { - getTime: jest.fn(() => timeFilter), - setTime: jest.fn((newTimeFilter) => { - timeFilter = newTimeFilter; - if (subscriber) { - subscriber(); - } - }), - getTimeUpdate$: () => ({ - subscribe: ({ next }: { next: () => void }) => { - subscriber = next; - return unsubscribe; - }, - }), - calculateBounds: jest.fn(() => ({ - min: moment('2021-01-10T04:00:00.000Z'), - max: moment('2021-01-10T08:00:00.000Z'), - })), - getBounds: jest.fn(() => timeFilter), - getRefreshInterval: () => {}, - getRefreshIntervalDefaults: () => {}, - getAutoRefreshFetch$: () => new Observable(), - }; -} - -function makeDefaultData(): jest.Mocked { - return { - query: { - filterManager: createMockFilterManager(), - timefilter: { - timefilter: createMockTimefilter(), - }, - queryString: createMockQueryString(), - state$: new Observable(), - }, - indexPatterns: { - get: jest.fn().mockImplementation((id) => Promise.resolve({ id, isTimeBased: () => true })), - }, - search: createMockSearchService(), - nowProvider: { - get: jest.fn(), - }, - } as unknown as DataPublicPluginStart; -} +import { mockDataPlugin } from '../mocks'; const createMiddleware = (data: DataPublicPluginStart) => { const middleware = timeRangeMiddleware(data); @@ -142,7 +37,7 @@ const createMiddleware = (data: DataPublicPluginStart) => { describe('timeRangeMiddleware', () => { describe('time update', () => { it('does update the searchSessionId when the state changes and too much time passed', () => { - const data = makeDefaultData(); + const data = mockDataPlugin(); (data.nowProvider.get as jest.Mock).mockReturnValue(new Date(Date.now() - 30000)); (data.query.timefilter.timefilter.getTime as jest.Mock).mockReturnValue({ from: 'now-2m', @@ -176,7 +71,7 @@ describe('timeRangeMiddleware', () => { expect(next).toHaveBeenCalledWith(action); }); it('does not update the searchSessionId when the state changes and too little time has passed', () => { - const data = makeDefaultData(); + const data = mockDataPlugin(); // time range is 100,000ms ago to 300ms ago (that's a lag of .3 percent, not enough to trigger a session update) (data.nowProvider.get as jest.Mock).mockReturnValue(new Date(Date.now() - 300)); (data.query.timefilter.timefilter.getTime as jest.Mock).mockReturnValue({ @@ -202,7 +97,7 @@ describe('timeRangeMiddleware', () => { expect(next).toHaveBeenCalledWith(action); }); it('does not trigger another update when the update already contains searchSessionId', () => { - const data = makeDefaultData(); + const data = mockDataPlugin(); (data.nowProvider.get as jest.Mock).mockReturnValue(new Date(Date.now() - 30000)); (data.query.timefilter.timefilter.getTime as jest.Mock).mockReturnValue({ from: 'now-2m', From 36ce6bda672c55551a175888fac0cf5131f5fd7f Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Mon, 4 Oct 2021 07:48:24 -0400 Subject: [PATCH 28/98] [Security Solution][Endpoint] Show list of trusted application on the Policy Details (#112182) * New Artifact Collapsible card and Grid generic components * Fleet setup test data loader - ignore 409 concurrent installs in data loader for fleet setup * Adds `ContextMenuWithRouterSupport` prop for `maxWidth` and `truncateText` prop for `ContextMenuItemNaByRouter` * trustedApps generator loader - use existing policies (if any) when loading TAs * `CardCompressedHeaderLayout` support for `flushTop` prop --- .../data_loaders/setup_fleet_for_endpoint.ts | 13 +- .../common/endpoint/types/trusted_apps.ts | 2 +- .../actions_context_menu.tsx | 2 +- .../artifact_card_grid.test.tsx | 123 +++++++++++ .../artifact_card_grid/artifact_card_grid.tsx | 143 +++++++++++++ .../components/grid_header.tsx | 71 +++++++ .../components/artifact_card_grid/index.ts | 8 + .../artifact_entry_card.test.tsx | 2 +- .../artifact_entry_card.tsx | 72 ++----- .../artifact_entry_collapsible_card.tsx | 65 ++++++ .../components/card_actions_flex_item.tsx | 26 +++ .../components/card_compressed_header.tsx | 183 +++++++++++++++++ .../components/card_container_panel.tsx | 32 +++ .../components/card_expand_button.tsx | 29 +++ .../components/card_header.tsx | 18 +- .../components/card_section_panel.tsx | 19 ++ .../components/card_sub_header.tsx | 2 +- .../components/effect_scope.tsx | 8 +- .../components/text_value_display.tsx | 18 +- .../components/translations.ts | 14 ++ .../hooks/use_collapsed_css_class_names.ts | 21 ++ .../hooks/use_normalized_artifact.ts | 43 +--- .../hooks/use_policy_nav_links.ts | 33 +++ .../components/artifact_entry_card/index.ts | 4 + .../components/artifact_entry_card/types.ts | 5 + .../artifact_entry_card/utils/index.ts | 9 + .../utils/is_trusted_app.ts | 17 ++ .../utils/map_to_artifact_info.ts | 40 ++++ ...sx => context_menu_item_nav_by_router.tsx} | 22 +- .../context_menu_with_router_support.tsx | 30 ++- .../view/components/table_row_actions.tsx | 2 +- .../view/details/components/actions_menu.tsx | 2 +- .../view/hooks/use_endpoint_action_items.tsx | 2 +- .../action/policy_trusted_apps_action.ts | 28 ++- .../store/policy_details/middleware/index.ts | 13 +- .../middleware/policy_settings_middleware.ts | 2 +- .../policy_trusted_apps_middleware.ts | 183 ++++++++++++++--- .../reducer/initial_policy_details_state.ts | 2 + .../reducer/trusted_apps_reducer.test.ts | 12 +- .../reducer/trusted_apps_reducer.ts | 37 ++++ .../store/policy_details/selectors/index.ts | 1 + .../selectors/policy_common_selectors.ts | 50 +++++ .../selectors/policy_settings_selectors.ts | 16 +- .../selectors/trusted_apps_selectors.test.ts | 9 +- .../selectors/trusted_apps_selectors.ts | 118 +++++++++-- .../pages/policy/test_utils/index.ts | 4 +- .../public/management/pages/policy/types.ts | 64 +++--- .../policy_artifacts_assignable_list.tsx | 4 +- .../pages/policy/view/tabs/policy_tabs.tsx | 8 +- .../pages/policy/view/trusted_apps/index.ts | 8 + .../layout/policy_trusted_apps_layout.tsx | 4 +- .../list/policy_trusted_apps_list.tsx | 192 ++++++++++++++++++ .../pages/trusted_apps/service/index.ts | 6 +- .../__snapshots__/index.test.tsx.snap | 120 +++++------ .../view/trusted_apps_page.test.tsx | 8 +- .../scripts/endpoint/trusted_apps/index.ts | 49 +++-- .../endpoint/routes/trusted_apps/service.ts | 4 +- 57 files changed, 1695 insertions(+), 327 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.test.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_card_grid/components/grid_header.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_card_grid/index.ts create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_collapsible_card.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_actions_flex_item.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_compressed_header.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_container_panel.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_expand_button.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_section_panel.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_collapsed_css_class_names.ts create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_policy_nav_links.ts create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/index.ts create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/is_trusted_app.ts create mode 100644 x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/map_to_artifact_info.ts rename x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/{context_menu_item_nav_by_rotuer.tsx => context_menu_item_nav_by_router.tsx} (65%) create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_common_selectors.ts create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/index.ts create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.tsx diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/setup_fleet_for_endpoint.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/setup_fleet_for_endpoint.ts index 985fa2c4aadcf..e19cffb808464 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/setup_fleet_for_endpoint.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/setup_fleet_for_endpoint.ts @@ -110,15 +110,20 @@ export const installOrUpgradeEndpointFleetPackage = async ( ); } - if (isFleetBulkInstallError(bulkResp[0])) { - if (bulkResp[0].error instanceof Error) { + const firstError = bulkResp[0]; + + if (isFleetBulkInstallError(firstError)) { + if (firstError.error instanceof Error) { throw new EndpointDataLoadingError( - `Installing the Endpoint package failed: ${bulkResp[0].error.message}, exiting`, + `Installing the Endpoint package failed: ${firstError.error.message}, exiting`, bulkResp ); } - throw new EndpointDataLoadingError(bulkResp[0].error, bulkResp); + // Ignore `409` (conflicts due to Concurrent install or upgrades of package) errors + if (firstError.statusCode !== 409) { + throw new EndpointDataLoadingError(firstError.error, bulkResp); + } } return bulkResp[0] as BulkInstallPackageInfo; diff --git a/x-pack/plugins/security_solution/common/endpoint/types/trusted_apps.ts b/x-pack/plugins/security_solution/common/endpoint/types/trusted_apps.ts index 4c6d2f6037356..9815bc3535de4 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/trusted_apps.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/trusted_apps.ts @@ -32,7 +32,7 @@ export type GetTrustedAppsListRequest = TypeOf; -export interface GetTrustedListAppsResponse { +export interface GetTrustedAppsListResponse { per_page: number; page: number; total: number; diff --git a/x-pack/plugins/security_solution/public/management/components/actions_context_menu/actions_context_menu.tsx b/x-pack/plugins/security_solution/public/management/components/actions_context_menu/actions_context_menu.tsx index 7d46c7c80677d..c2f9e32f61afb 100644 --- a/x-pack/plugins/security_solution/public/management/components/actions_context_menu/actions_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/management/components/actions_context_menu/actions_context_menu.tsx @@ -18,7 +18,7 @@ import { i18n } from '@kbn/i18n'; import { ContextMenuItemNavByRouter, ContextMenuItemNavByRouterProps, -} from '../context_menu_with_router_support/context_menu_item_nav_by_rotuer'; +} from '../context_menu_with_router_support/context_menu_item_nav_by_router'; import { useTestIdGenerator } from '../hooks/use_test_id_generator'; export interface ActionsContextMenuProps { diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.test.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.test.tsx new file mode 100644 index 0000000000000..a44076c8ad112 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.test.tsx @@ -0,0 +1,123 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TrustedAppGenerator } from '../../../../common/endpoint/data_generators/trusted_app_generator'; +import { cloneDeep } from 'lodash'; +import { getExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_item_schema.mock'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../../common/mock/endpoint'; +import React from 'react'; +import { ArtifactCardGrid, ArtifactCardGridProps } from './artifact_card_grid'; + +// FIXME:PT refactor helpers below after merge of PR https://github.com/elastic/kibana/pull/113363 + +const getCommonItemDataOverrides = () => { + return { + name: 'some internal app', + description: 'this app is trusted by the company', + created_at: new Date('2021-07-01').toISOString(), + }; +}; + +const getTrustedAppProvider = () => + new TrustedAppGenerator('seed').generate(getCommonItemDataOverrides()); + +const getExceptionProvider = () => { + // cloneDeep needed because exception mock generator uses state across instances + return cloneDeep( + getExceptionListItemSchemaMock({ + ...getCommonItemDataOverrides(), + os_types: ['windows'], + updated_at: new Date().toISOString(), + created_by: 'Justa', + updated_by: 'Mara', + entries: [ + { + field: 'process.hash.*', + operator: 'included', + type: 'match', + value: '1234234659af249ddf3e40864e9fb241', + }, + { + field: 'process.executable.caseless', + operator: 'included', + type: 'match', + value: '/one/two/three', + }, + ], + tags: ['policy:all'], + }) + ); +}; + +describe.each([ + ['trusted apps', getTrustedAppProvider], + ['exceptions/event filters', getExceptionProvider], +])('when using the ArtifactCardGrid component %s', (_, generateItem) => { + let appTestContext: AppContextTestRender; + let renderResult: ReturnType; + let render: ( + props?: Partial + ) => ReturnType; + let items: ArtifactCardGridProps['items']; + let pageChangeHandler: jest.Mock; + let expandCollapseHandler: jest.Mock; + let cardComponentPropsProvider: Required['cardComponentProps']; + + beforeEach(() => { + items = Array.from({ length: 5 }, () => generateItem()); + pageChangeHandler = jest.fn(); + expandCollapseHandler = jest.fn(); + cardComponentPropsProvider = jest.fn().mockReturnValue({}); + + appTestContext = createAppRootMockRenderer(); + render = (props = {}) => { + renderResult = appTestContext.render( + + ); + return renderResult; + }; + }); + + it('should render the cards', () => { + render(); + + expect(renderResult.getAllByTestId('testGrid-card')).toHaveLength(5); + }); + + it.each([ + ['header', 'testGrid-header'], + ['expand/collapse placeholder', 'testGrid-header-expandCollapsePlaceHolder'], + ['name column', 'testGrid-header-layout-title'], + ['description column', 'testGrid-header-layout-description'], + ['description column', 'testGrid-header-layout-cardActionsPlaceholder'], + ])('should display the Grid Header - %s', (__, selector) => { + render(); + + expect(renderResult.getByTestId(selector)).not.toBeNull(); + }); + + it.todo('should call onPageChange callback when paginating'); + + it.todo('should use the props provided by cardComponentProps callback'); + + describe('and when cards are expanded/collapsed', () => { + it.todo('should call onExpandCollapse callback'); + + it.todo('should provide list of cards that are expanded and collapsed'); + + it.todo('should show card expanded if card props defined it as such'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.tsx new file mode 100644 index 0000000000000..9e9082ccc54e7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.tsx @@ -0,0 +1,143 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { ComponentType, memo, useCallback, useMemo } from 'react'; +import { + AnyArtifact, + ArtifactEntryCollapsibleCard, + ArtifactEntryCollapsibleCardProps, +} from '../artifact_entry_card'; +import { PaginatedContent as _PaginatedContent, PaginatedContentProps } from '../paginated_content'; +import { GridHeader } from './components/grid_header'; +import { MaybeImmutable } from '../../../../common/endpoint/types'; +import { useTestIdGenerator } from '../hooks/use_test_id_generator'; + +const PaginatedContent: ArtifactsPaginatedComponent = _PaginatedContent; + +type ArtifactsPaginatedContentProps = PaginatedContentProps< + AnyArtifact, + typeof ArtifactEntryCollapsibleCard +>; + +type ArtifactsPaginatedComponent = ComponentType; + +interface CardExpandCollapseState { + expanded: MaybeImmutable; + collapsed: MaybeImmutable; +} + +export type ArtifactCardGridCardComponentProps = Omit< + ArtifactEntryCollapsibleCardProps, + 'onExpandCollapse' | 'item' +>; +export type ArtifactCardGridProps = Omit< + ArtifactsPaginatedContentProps, + 'ItemComponent' | 'itemComponentProps' | 'items' | 'onChange' +> & { + items: MaybeImmutable; + + /** Callback to handle pagination changes */ + onPageChange: ArtifactsPaginatedContentProps['onChange']; + + /** callback for handling changes to the card's expand/collapse state */ + onExpandCollapse: (state: CardExpandCollapseState) => void; + + /** + * Callback to provide additional props for the `ArtifactEntryCollapsibleCard` + */ + cardComponentProps?: (item: MaybeImmutable) => ArtifactCardGridCardComponentProps; +}; + +export const ArtifactCardGrid = memo( + ({ + items: _items, + cardComponentProps, + onPageChange, + onExpandCollapse, + 'data-test-subj': dataTestSubj, + ...paginatedContentProps + }) => { + const getTestId = useTestIdGenerator(dataTestSubj); + + const items = _items as AnyArtifact[]; + + // The list of card props that the caller can define + type PartialCardProps = Map; + const callerDefinedCardProps = useMemo(() => { + const cardProps: PartialCardProps = new Map(); + + for (const artifact of items) { + cardProps.set(artifact, cardComponentProps ? cardComponentProps(artifact) : {}); + } + + return cardProps; + }, [cardComponentProps, items]); + + // Handling of what is expanded or collapsed is done by looking at the at what the caller card's + // `expanded` prop value was and then invert it for the card that the user clicked expand/collapse + const handleCardExpandCollapse = useCallback( + (item: AnyArtifact) => { + const expanded = []; + const collapsed = []; + + for (const [artifact, currentCardProps] of callerDefinedCardProps) { + const currentExpandedState = Boolean(currentCardProps.expanded); + const newExpandedState = artifact === item ? !currentExpandedState : currentExpandedState; + + if (newExpandedState) { + expanded.push(artifact); + } else { + collapsed.push(artifact); + } + } + + onExpandCollapse({ expanded, collapsed }); + }, + [callerDefinedCardProps, onExpandCollapse] + ); + + // Full list of card props that includes the actual artifact and the callbacks + type FullCardProps = Map; + const fullCardProps = useMemo(() => { + const newFullCardProps: FullCardProps = new Map(); + + for (const [artifact, cardProps] of callerDefinedCardProps) { + newFullCardProps.set(artifact, { + ...cardProps, + item: artifact, + onExpandCollapse: () => handleCardExpandCollapse(artifact), + 'data-test-subj': cardProps['data-test-subj'] ?? getTestId('card'), + }); + } + + return newFullCardProps; + }, [callerDefinedCardProps, getTestId, handleCardExpandCollapse]); + + const handleItemComponentProps = useCallback( + (item: AnyArtifact): ArtifactEntryCollapsibleCardProps => { + return fullCardProps.get(item)!; + }, + [fullCardProps] + ); + + return ( + <> + + + + + ); + } +); +ArtifactCardGrid.displayName = 'ArtifactCardGrid'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/components/grid_header.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/components/grid_header.tsx new file mode 100644 index 0000000000000..03fde724b89a5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/components/grid_header.tsx @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo, useMemo } from 'react'; +import { CommonProps, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import styled from 'styled-components'; +import { CardCompressedHeaderLayout, CardSectionPanel } from '../../artifact_entry_card'; +import { useTestIdGenerator } from '../../hooks/use_test_id_generator'; + +const GridHeaderContainer = styled(CardSectionPanel)` + padding-top: 0; + padding-bottom: ${({ theme }) => theme.eui.paddingSizes.s}; +`; + +export type GridHeaderProps = Pick; +export const GridHeader = memo(({ 'data-test-subj': dataTestSubj }) => { + const getTestId = useTestIdGenerator(dataTestSubj); + + const expandToggleElement = useMemo( + () =>
    , + [getTestId] + ); + + return ( + + + + + + + } + description={ + + + + + + } + effectScope={ + + + + + + } + actionMenu={false} + /> + + ); +}); +GridHeader.displayName = 'GridHeader'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/index.ts b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/index.ts new file mode 100644 index 0000000000000..3c29df28a82df --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/index.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './artifact_card_grid'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx index 31e49aef0ac19..52f0eb5fc8982 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.test.tsx @@ -10,7 +10,7 @@ import { AppContextTestRender, createAppRootMockRenderer } from '../../../common import { ArtifactEntryCard, ArtifactEntryCardProps } from './artifact_entry_card'; import { act, fireEvent, getByTestId } from '@testing-library/react'; import { AnyArtifact } from './types'; -import { isTrustedApp } from './hooks/use_normalized_artifact'; +import { isTrustedApp } from './utils'; import { getTrustedAppProvider, getExceptionProvider } from './test_utils'; describe.each([ diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.tsx index 4adb81411395a..d9709c64e092d 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.tsx @@ -5,27 +5,22 @@ * 2.0. */ -import React, { memo, useMemo } from 'react'; -import { CommonProps, EuiHorizontalRule, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; -import styled from 'styled-components'; +import React, { memo } from 'react'; +import { CommonProps, EuiHorizontalRule, EuiSpacer, EuiText } from '@elastic/eui'; import { CardHeader, CardHeaderProps } from './components/card_header'; import { CardSubHeader } from './components/card_sub_header'; import { getEmptyValue } from '../../../common/components/empty_value'; import { CriteriaConditions, CriteriaConditionsProps } from './components/criteria_conditions'; -import { EffectScopeProps } from './components/effect_scope'; -import { ContextMenuItemNavByRouterProps } from '../context_menu_with_router_support/context_menu_item_nav_by_rotuer'; -import { AnyArtifact } from './types'; +import { AnyArtifact, MenuItemPropsByPolicyId } from './types'; import { useNormalizedArtifact } from './hooks/use_normalized_artifact'; import { useTestIdGenerator } from '../hooks/use_test_id_generator'; - -const CardContainerPanel = styled(EuiPanel)` - &.artifactEntryCard + &.artifactEntryCard { - margin-top: ${({ theme }) => theme.eui.spacerSizes.l}; - } -`; +import { CardContainerPanel } from './components/card_container_panel'; +import { CardSectionPanel } from './components/card_section_panel'; +import { usePolicyNavLinks } from './hooks/use_policy_nav_links'; +import { MaybeImmutable } from '../../../../common/endpoint/types'; export interface ArtifactEntryCardProps extends CommonProps { - item: AnyArtifact; + item: MaybeImmutable; /** * The list of actions for the card. Will display an icon with the actions in a menu if defined. */ @@ -33,52 +28,25 @@ export interface ArtifactEntryCardProps extends CommonProps { /** * Information about the policies that are assigned to the `item`'s `effectScope` and that will be - * use to create a navigation link + * used to create the items in the popup context menu. This is a + * `Record`. */ - policies?: { - [policyId: string]: ContextMenuItemNavByRouterProps; - }; + policies?: MenuItemPropsByPolicyId; } /** * Display Artifact Items (ex. Trusted App, Event Filter, etc) as a card. * This component is a TS Generic that allows you to set what the Item type is */ -export const ArtifactEntryCard = memo( - ({ - item, - policies, - actions, - 'data-test-subj': dataTestSubj, - ...commonProps - }: ArtifactEntryCardProps) => { - const artifact = useNormalizedArtifact(item); +export const ArtifactEntryCard = memo( + ({ item, policies, actions, 'data-test-subj': dataTestSubj, ...commonProps }) => { + const artifact = useNormalizedArtifact(item as AnyArtifact); const getTestId = useTestIdGenerator(dataTestSubj); - - // create the policy links for each policy listed in the artifact record by grabbing the - // navigation data from the `policies` prop (if any) - const policyNavLinks = useMemo(() => { - return artifact.effectScope.type === 'policy' - ? artifact?.effectScope.policies.map((id) => { - return policies && policies[id] - ? policies[id] - : // else, unable to build a nav link, so just show id - { - children: id, - }; - }) - : undefined; - }, [artifact.effectScope, policies]); + const policyNavLinks = usePolicyNavLinks(artifact, policies); return ( - - + + - + - + - + ); } diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_collapsible_card.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_collapsible_card.tsx new file mode 100644 index 0000000000000..43572ea234d31 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_collapsible_card.tsx @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo } from 'react'; +import { EuiHorizontalRule } from '@elastic/eui'; +import { ArtifactEntryCardProps } from './artifact_entry_card'; +import { CardContainerPanel } from './components/card_container_panel'; +import { useNormalizedArtifact } from './hooks/use_normalized_artifact'; +import { useTestIdGenerator } from '../hooks/use_test_id_generator'; +import { CardSectionPanel } from './components/card_section_panel'; +import { CriteriaConditions, CriteriaConditionsProps } from './components/criteria_conditions'; +import { CardCompressedHeader } from './components/card_compressed_header'; + +export interface ArtifactEntryCollapsibleCardProps extends ArtifactEntryCardProps { + onExpandCollapse: () => void; + expanded?: boolean; +} + +export const ArtifactEntryCollapsibleCard = memo( + ({ + item, + onExpandCollapse, + policies, + actions, + expanded = false, + 'data-test-subj': dataTestSubj, + ...commonProps + }) => { + const artifact = useNormalizedArtifact(item); + const getTestId = useTestIdGenerator(dataTestSubj); + + return ( + + + + + {expanded && ( + <> + + + + + + + )} + + ); + } +); +ArtifactEntryCollapsibleCard.displayName = 'ArtifactEntryCollapsibleCard'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_actions_flex_item.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_actions_flex_item.tsx new file mode 100644 index 0000000000000..4758eaec4e923 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_actions_flex_item.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo } from 'react'; +import { CommonProps, EuiFlexItem } from '@elastic/eui'; +import { ActionsContextMenu, ActionsContextMenuProps } from '../../actions_context_menu'; + +export interface CardActionsFlexItemProps extends Pick { + /** If defined, then an overflow menu will be shown with the actions provided */ + actions?: ActionsContextMenuProps['items']; +} + +export const CardActionsFlexItem = memo( + ({ actions, 'data-test-subj': dataTestSubj }) => { + return actions && actions.length > 0 ? ( + + + + ) : null; + } +); +CardActionsFlexItem.displayName = 'CardActionsFlexItem'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_compressed_header.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_compressed_header.tsx new file mode 100644 index 0000000000000..6141437779d7d --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_compressed_header.tsx @@ -0,0 +1,183 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo, ReactNode, useCallback } from 'react'; +import { CommonProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import styled from 'styled-components'; +import { CardExpandButton } from './card_expand_button'; +import { TextValueDisplay } from './text_value_display'; +import { EffectScope } from './effect_scope'; +import { CardActionsFlexItem } from './card_actions_flex_item'; +import { ArtifactInfo } from '../types'; +import { ArtifactEntryCollapsibleCardProps } from '../artifact_entry_collapsible_card'; +import { useTestIdGenerator } from '../../hooks/use_test_id_generator'; +import { useCollapsedCssClassNames } from '../hooks/use_collapsed_css_class_names'; +import { usePolicyNavLinks } from '../hooks/use_policy_nav_links'; +import { getEmptyValue } from '../../../../common/components/empty_value'; + +export interface CardCompressedHeaderProps + extends Pick, + Pick< + ArtifactEntryCollapsibleCardProps, + 'onExpandCollapse' | 'expanded' | 'actions' | 'policies' + > { + artifact: ArtifactInfo; +} + +export const CardCompressedHeader = memo( + ({ + artifact, + onExpandCollapse, + policies, + actions, + expanded = false, + 'data-test-subj': dataTestSubj, + }) => { + const getTestId = useTestIdGenerator(dataTestSubj); + const cssClassNames = useCollapsedCssClassNames(expanded); + const policyNavLinks = usePolicyNavLinks(artifact, policies); + + const handleExpandCollapseClick = useCallback(() => { + onExpandCollapse(); + }, [onExpandCollapse]); + + return ( + + + + + + + + + {artifact.name} + + + + + {artifact.description || getEmptyValue()} + + + + + + + + + + ); + } +); +CardCompressedHeader.displayName = 'CardCompressedHeader'; + +const ButtonIconPlaceHolder = styled.div` + display: inline-block; + // Sizes below should match that of the Eui's Button Icon, so that it holds the same space. + width: ${({ theme }) => theme.eui.euiIconSizes.large}; + height: ${({ theme }) => theme.eui.euiIconSizes.large}; +`; + +const StyledEuiFlexGroup = styled(EuiFlexGroup)` + &.flushTop, + .flushTop { + padding-top: 0; + margin-top: 0; + } +`; + +/** + * Layout used for the compressed card header. Used also in the ArtifactGrid for creating the grid header row + */ +export interface CardCompressedHeaderLayoutProps extends Pick { + expanded: boolean; + expandToggle: ReactNode; + name: ReactNode; + description: ReactNode; + effectScope: ReactNode; + /** If no menu is shown, but you want the space for it be preserved, set prop to `false` */ + actionMenu?: ReactNode | false; + /** + * When set to `true`, all padding and margin values will be set to zero for the top of the header + * layout, so that all content is flushed to the top + */ + flushTop?: boolean; +} + +export const CardCompressedHeaderLayout = memo( + ({ + expanded, + name, + expandToggle, + effectScope, + actionMenu, + description, + 'data-test-subj': dataTestSubj, + flushTop, + }) => { + const getTestId = useTestIdGenerator(dataTestSubj); + const cssClassNames = useCollapsedCssClassNames(expanded); + const flushTopCssClassname = flushTop ? ' flushTop' : ''; + + return ( + + + {expandToggle} + + + + + {name} + + + {description} + + + {effectScope} + + + + {actionMenu === false ? ( + + + + ) : ( + actionMenu + )} + + ); + } +); +CardCompressedHeaderLayout.displayName = 'CardCompressedHeaderLayout'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_container_panel.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_container_panel.tsx new file mode 100644 index 0000000000000..0a64670a9de12 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_container_panel.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import styled from 'styled-components'; +import { EuiPanel } from '@elastic/eui'; +import { EuiPanelProps } from '@elastic/eui/src/components/panel/panel'; +import React, { memo } from 'react'; + +export const EuiPanelStyled = styled(EuiPanel)` + &.artifactEntryCard + &.artifactEntryCard { + margin-top: ${({ theme }) => theme.eui.spacerSizes.l}; + } +`; + +export type CardContainerPanelProps = Exclude; + +export const CardContainerPanel = memo(({ className, ...props }) => { + return ( + + ); +}); + +CardContainerPanel.displayName = 'CardContainerPanel'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_expand_button.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_expand_button.tsx new file mode 100644 index 0000000000000..a7c0c39321660 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_expand_button.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo } from 'react'; +import { CommonProps, EuiButtonIcon, EuiButtonIconPropsForButton } from '@elastic/eui'; +import { COLLAPSE_ACTION, EXPAND_ACTION } from './translations'; + +export interface CardExpandButtonProps extends Pick { + expanded: boolean; + onClick: EuiButtonIconPropsForButton['onClick']; +} + +export const CardExpandButton = memo( + ({ expanded, onClick, 'data-test-subj': dataTestSubj }) => { + return ( + + ); + } +); +CardExpandButton.displayName = 'CardExpandButton'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_header.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_header.tsx index ca82c97d8b820..6964f5b339312 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_header.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_header.tsx @@ -8,15 +8,15 @@ import React, { memo } from 'react'; import { CommonProps, EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { DateFieldValue } from './date_field_value'; -import { ActionsContextMenu, ActionsContextMenuProps } from '../../actions_context_menu'; import { useTestIdGenerator } from '../../hooks/use_test_id_generator'; +import { CardActionsFlexItem, CardActionsFlexItemProps } from './card_actions_flex_item'; -export interface CardHeaderProps extends Pick { +export interface CardHeaderProps + extends CardActionsFlexItemProps, + Pick { name: string; createdDate: string; updatedDate: string; - /** If defined, then an overflow menu will be shown with the actions provided */ - actions?: ActionsContextMenuProps['items']; } export const CardHeader = memo( @@ -52,15 +52,7 @@ export const CardHeader = memo( - {actions && actions.length > 0 && ( - - - - )} + ); } diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_section_panel.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_section_panel.tsx new file mode 100644 index 0000000000000..1d694ab1771d3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_section_panel.tsx @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo } from 'react'; +import { EuiPanel, EuiPanelProps } from '@elastic/eui'; + +export type CardSectionPanelProps = Exclude< + EuiPanelProps, + 'hasBorder' | 'hasShadow' | 'paddingSize' +>; + +export const CardSectionPanel = memo((props) => { + return ; +}); +CardSectionPanel.displayName = 'CardSectionPanel'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_sub_header.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_sub_header.tsx index 4bd86b9af0650..fd787c01e50ff 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_sub_header.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/card_sub_header.tsx @@ -20,7 +20,7 @@ export const CardSubHeader = memo( const getTestId = useTestIdGenerator(dataTestSubj); return ( - + 0 policies, but no menu +// the intent in this component was to also support to be able to display only text for artifacts +// by policy (>0), but **NOT** show the menu. +// So something like: `` +// This should dispaly it as "Applied t o 3 policies", but NOT as a menu with links + export interface EffectScopeProps extends Pick { /** If set (even if empty), then effect scope will be policy specific. Else, it shows as global */ policies?: ContextMenuItemNavByRouterProps[]; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/text_value_display.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/text_value_display.tsx index f1d92f4c09778..3843d7992bdf2 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/text_value_display.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/text_value_display.tsx @@ -5,18 +5,30 @@ * 2.0. */ -import React, { memo, PropsWithChildren } from 'react'; +import React, { memo, PropsWithChildren, useMemo } from 'react'; import { EuiText } from '@elastic/eui'; +import classNames from 'classnames'; export type TextValueDisplayProps = PropsWithChildren<{ bold?: boolean; + truncate?: boolean; }>; /** * Common component for displaying consistent text across the card. Changes here could impact all of * display of values on the card */ -export const TextValueDisplay = memo(({ bold, children }) => { - return {bold ? {children} : children}; +export const TextValueDisplay = memo(({ bold, truncate, children }) => { + const cssClassNames = useMemo(() => { + return classNames({ + 'eui-textTruncate': truncate, + }); + }, [truncate]); + + return ( + + {bold ? {children} : children} + + ); }); TextValueDisplay.displayName = 'TextValueDisplay'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/translations.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/translations.ts index dce922e7e3cef..d98f4589027d4 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/translations.ts +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/components/translations.ts @@ -100,3 +100,17 @@ export const OS_LINUX = i18n.translate('xpack.securitySolution.artifactCard.cond export const OS_MAC = i18n.translate('xpack.securitySolution.artifactCard.conditions.macos', { defaultMessage: 'Mac', }); + +export const EXPAND_ACTION = i18n.translate( + 'xpack.securitySolution.artifactExpandableCard.expand', + { + defaultMessage: 'Expand', + } +); + +export const COLLAPSE_ACTION = i18n.translate( + 'xpack.securitySolution.artifactExpandableCard.collpase', + { + defaultMessage: 'Collapse', + } +); diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_collapsed_css_class_names.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_collapsed_css_class_names.ts new file mode 100644 index 0000000000000..2b9fe1c76fbac --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_collapsed_css_class_names.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import classNames from 'classnames'; + +/** + * Returns the css classnames that should be applied when the collapsible card is NOT expanded + * @param expanded + */ +export const useCollapsedCssClassNames = (expanded?: boolean): string => { + return useMemo(() => { + return classNames({ + 'eui-textTruncate': !expanded, + }); + }, [expanded]); +}; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_normalized_artifact.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_normalized_artifact.ts index 7b3fb07bf10ac..4ea8d4aa6ee7c 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_normalized_artifact.ts +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_normalized_artifact.ts @@ -5,53 +5,18 @@ * 2.0. */ -/* eslint-disable @typescript-eslint/naming-convention */ - import { useMemo } from 'react'; -import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { AnyArtifact, ArtifactInfo } from '../types'; -import { EffectScope, TrustedApp } from '../../../../../common/endpoint/types'; -import { tagsToEffectScope } from '../../../../../common/endpoint/service/trusted_apps/mapping'; +import { mapToArtifactInfo } from '../utils'; +import { MaybeImmutable } from '../../../../../common/endpoint/types'; /** * Takes in any artifact and return back a new data structure used internally with by the card's components * * @param item */ -export const useNormalizedArtifact = (item: AnyArtifact): ArtifactInfo => { +export const useNormalizedArtifact = (item: MaybeImmutable): ArtifactInfo => { return useMemo(() => { - const { - name, - created_by, - created_at, - updated_at, - updated_by, - description = '', - entries, - } = item; - return { - name, - created_by, - created_at, - updated_at, - updated_by, - description, - entries: entries as unknown as ArtifactInfo['entries'], - os: isTrustedApp(item) ? item.os : getOsFromExceptionItem(item), - effectScope: isTrustedApp(item) ? item.effectScope : getEffectScopeFromExceptionItem(item), - }; + return mapToArtifactInfo(item); }, [item]); }; - -export const isTrustedApp = (item: AnyArtifact): item is TrustedApp => { - return 'effectScope' in item; -}; - -const getOsFromExceptionItem = (item: ExceptionListItemSchema): string => { - // FYI: Exceptions seem to allow for items to be assigned to more than one OS, unlike Event Filters and Trusted Apps - return item.os_types.join(', '); -}; - -const getEffectScopeFromExceptionItem = (item: ExceptionListItemSchema): EffectScope => { - return tagsToEffectScope(item.tags); -}; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_policy_nav_links.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_policy_nav_links.ts new file mode 100644 index 0000000000000..dd403ebaf448c --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/hooks/use_policy_nav_links.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import { EffectScopeProps } from '../components/effect_scope'; +import { ArtifactInfo, MenuItemPropsByPolicyId } from '../types'; +import { ContextMenuItemNavByRouterProps } from '../../context_menu_with_router_support/context_menu_item_nav_by_router'; + +/** + * creates the policy links for each policy listed in the artifact record by grabbing the + * navigation data from the `policies` prop (if any) + */ +export const usePolicyNavLinks = ( + artifact: ArtifactInfo, + policies?: MenuItemPropsByPolicyId +): ContextMenuItemNavByRouterProps[] | undefined => { + return useMemo(() => { + return artifact.effectScope.type === 'policy' + ? artifact?.effectScope.policies.map((id) => { + return policies && policies[id] + ? policies[id] + : // else, unable to build a nav link, so just show id + { + children: id, + }; + }) + : undefined; + }, [artifact.effectScope, policies]); +}; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/index.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/index.ts index f37d5d4e650e1..71a1230889559 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/index.ts +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/index.ts @@ -7,3 +7,7 @@ export * from './artifact_entry_card'; export * from './artifact_entry_card_minified'; +export * from './artifact_entry_collapsible_card'; +export * from './components/card_section_panel'; +export * from './types'; +export { CardCompressedHeaderLayout } from './components/card_compressed_header'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/types.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/types.ts index c59a2bde94589..c506c62ac4351 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/types.ts +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/types.ts @@ -7,6 +7,7 @@ import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { EffectScope, TrustedApp } from '../../../../common/endpoint/types'; +import { ContextMenuItemNavByRouterProps } from '../context_menu_with_router_support/context_menu_item_nav_by_router'; export type AnyArtifact = ExceptionListItemSchema | TrustedApp; @@ -27,3 +28,7 @@ export interface ArtifactInfo value: string; }>; } + +export interface MenuItemPropsByPolicyId { + [policyId: string]: ContextMenuItemNavByRouterProps; +} diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/index.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/index.ts new file mode 100644 index 0000000000000..a7bb9a7f43336 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/index.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './is_trusted_app'; +export * from './map_to_artifact_info'; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/is_trusted_app.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/is_trusted_app.ts new file mode 100644 index 0000000000000..a14ff293d05e8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/is_trusted_app.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AnyArtifact } from '../types'; +import { TrustedApp } from '../../../../../common/endpoint/types'; + +/** + * Type guard for `AnyArtifact` to check if it is a trusted app entry + * @param item + */ +export const isTrustedApp = (item: AnyArtifact): item is TrustedApp => { + return 'effectScope' in item; +}; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/map_to_artifact_info.ts b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/map_to_artifact_info.ts new file mode 100644 index 0000000000000..dd9e90db327ee --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/utils/map_to_artifact_info.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { AnyArtifact, ArtifactInfo } from '../types'; +import { EffectScope, MaybeImmutable } from '../../../../../common/endpoint/types'; +import { tagsToEffectScope } from '../../../../../common/endpoint/service/trusted_apps/mapping'; +import { isTrustedApp } from './is_trusted_app'; + +export const mapToArtifactInfo = (_item: MaybeImmutable): ArtifactInfo => { + const item = _item as AnyArtifact; + + // eslint-disable-next-line @typescript-eslint/naming-convention + const { name, created_by, created_at, updated_at, updated_by, description = '', entries } = item; + + return { + name, + created_by, + created_at, + updated_at, + updated_by, + description, + entries: entries as unknown as ArtifactInfo['entries'], + os: isTrustedApp(item) ? item.os : getOsFromExceptionItem(item), + effectScope: isTrustedApp(item) ? item.effectScope : getEffectScopeFromExceptionItem(item), + }; +}; + +const getOsFromExceptionItem = (item: ExceptionListItemSchema): string => { + // FYI: Exceptions seem to allow for items to be assigned to more than one OS, unlike Event Filters and Trusted Apps + return item.os_types.join(', '); +}; + +const getEffectScopeFromExceptionItem = (item: ExceptionListItemSchema): EffectScope => { + return tagsToEffectScope(item.tags); +}; diff --git a/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_item_nav_by_rotuer.tsx b/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_item_nav_by_router.tsx similarity index 65% rename from x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_item_nav_by_rotuer.tsx rename to x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_item_nav_by_router.tsx index cc95235831c2e..fd087f267a9b5 100644 --- a/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_item_nav_by_rotuer.tsx +++ b/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_item_nav_by_router.tsx @@ -15,6 +15,12 @@ export interface ContextMenuItemNavByRouterProps extends EuiContextMenuItemProps navigateAppId?: string; /** Additional options for the navigation action via react-router */ navigateOptions?: NavigateToAppOptions; + /** + * if `true`, the `children` will be wrapped in a `div` that contains CSS Classname `eui-textTruncate`. + * **NOTE**: When this component is used in combination with `ContextMenuWithRouterSupport` and `maxWidth` + * is set on the menu component, this prop will be overridden + */ + textTruncate?: boolean; children: React.ReactNode; } @@ -23,7 +29,7 @@ export interface ContextMenuItemNavByRouterProps extends EuiContextMenuItemProps * allow navigation to a URL path via React Router */ export const ContextMenuItemNavByRouter = memo( - ({ navigateAppId, navigateOptions, onClick, children, ...otherMenuItemProps }) => { + ({ navigateAppId, navigateOptions, onClick, textTruncate, children, ...otherMenuItemProps }) => { const handleOnClickViaNavigateToApp = useNavigateToAppEventHandler(navigateAppId ?? '', { ...navigateOptions, onClick, @@ -34,7 +40,19 @@ export const ContextMenuItemNavByRouter = memo( {...otherMenuItemProps} onClick={navigateAppId ? handleOnClickViaNavigateToApp : onClick} > - {children} + {textTruncate ? ( +
    + {children} +
    + ) : ( + children + )} ); } diff --git a/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_with_router_support.tsx b/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_with_router_support.tsx index 8fbb7eca60a38..3f21f3995ac5b 100644 --- a/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_with_router_support.tsx +++ b/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_with_router_support.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { memo, useCallback, useMemo, useState } from 'react'; +import React, { CSSProperties, HTMLAttributes, memo, useCallback, useMemo, useState } from 'react'; import { CommonProps, EuiContextMenuPanel, @@ -16,13 +16,19 @@ import { import { ContextMenuItemNavByRouter, ContextMenuItemNavByRouterProps, -} from './context_menu_item_nav_by_rotuer'; +} from './context_menu_item_nav_by_router'; import { useTestIdGenerator } from '../hooks/use_test_id_generator'; export interface ContextMenuWithRouterSupportProps extends CommonProps, Pick { items: ContextMenuItemNavByRouterProps[]; + /** + * The max width for the popup menu. Default is `32ch`. + * **Note** that when used (default behaviour), all menu item's `truncateText` prop will be + * overwritten to `true`. Setting this prop's value to `undefined` will suppress the default behaviour. + */ + maxWidth?: CSSProperties['maxWidth']; } /** @@ -31,7 +37,7 @@ export interface ContextMenuWithRouterSupportProps * Menu also supports automatically closing the popup when an item is clicked. */ export const ContextMenuWithRouterSupport = memo( - ({ items, button, panelPaddingSize, anchorPosition, ...commonProps }) => { + ({ items, button, panelPaddingSize, anchorPosition, maxWidth = '32ch', ...commonProps }) => { const getTestId = useTestIdGenerator(commonProps['data-test-subj']); const [isOpen, setIsOpen] = useState(false); @@ -47,6 +53,7 @@ export const ContextMenuWithRouterSupport = memo { handleCloseMenu(); if (itemProps.onClick) { @@ -56,7 +63,20 @@ export const ContextMenuWithRouterSupport = memo ); }); - }, [handleCloseMenu, items]); + }, [handleCloseMenu, items, maxWidth]); + + type AdditionalPanelProps = Partial>; + const additionalContextMenuPanelProps = useMemo(() => { + const newAdditionalProps: AdditionalPanelProps = { + style: {}, + }; + + if (maxWidth) { + newAdditionalProps.style!.maxWidth = maxWidth; + } + + return newAdditionalProps; + }, [maxWidth]); return ( - + ); } diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/table_row_actions.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/table_row_actions.tsx index 6df5413c1eb3c..d97524894d5f8 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/table_row_actions.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/table_row_actions.tsx @@ -14,7 +14,7 @@ import { EuiPopoverProps, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ContextMenuItemNavByRouter } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_rotuer'; +import { ContextMenuItemNavByRouter } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_router'; import { HostMetadata } from '../../../../../../common/endpoint/types'; import { useEndpointActionItems } from '../hooks'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/actions_menu.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/actions_menu.tsx index 412db3dc2a63e..71060577e3a34 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/actions_menu.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/actions_menu.tsx @@ -10,7 +10,7 @@ import { EuiContextMenuPanel, EuiButton, EuiPopover } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { useEndpointActionItems, useEndpointSelector } from '../../hooks'; import { detailsData } from '../../../store/selectors'; -import { ContextMenuItemNavByRouter } from '../../../../../components/context_menu_with_router_support/context_menu_item_nav_by_rotuer'; +import { ContextMenuItemNavByRouter } from '../../../../../components/context_menu_with_router_support/context_menu_item_nav_by_router'; export const ActionsMenu = React.memo<{}>(() => { const endpointDetails = useEndpointSelector(detailsData); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx index 8f19fea818fc6..81432edbdd5fe 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx @@ -14,7 +14,7 @@ import { HostMetadata, MaybeImmutable } from '../../../../../../common/endpoint/ import { useEndpointSelector } from './hooks'; import { agentPolicies, uiQueryParams } from '../../store/selectors'; import { useAppUrl } from '../../../../../common/lib/kibana/hooks'; -import { ContextMenuItemNavByRouterProps } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_rotuer'; +import { ContextMenuItemNavByRouterProps } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_router'; import { isEndpointHostIsolated } from '../../../../../common/utils/validators'; import { useLicense } from '../../../../../common/hooks/use_license'; import { isIsolationSupported } from '../../../../../../common/endpoint/service/host_isolation/utils'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/action/policy_trusted_apps_action.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/action/policy_trusted_apps_action.ts index c7bc142eb78c5..fc32d42db647d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/action/policy_trusted_apps_action.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/action/policy_trusted_apps_action.ts @@ -5,14 +5,17 @@ * 2.0. */ +import { Action } from 'redux'; import { AsyncResourceState } from '../../../../../state'; import { PostTrustedAppCreateResponse, - GetTrustedListAppsResponse, + GetTrustedAppsListResponse, } from '../../../../../../../common/endpoint/types'; +import { PolicyArtifactsState } from '../../../types'; + export interface PolicyArtifactsAssignableListPageDataChanged { type: 'policyArtifactsAssignableListPageDataChanged'; - payload: AsyncResourceState; + payload: AsyncResourceState; } export interface PolicyArtifactsUpdateTrustedApps { @@ -37,9 +40,28 @@ export interface PolicyArtifactsAssignableListPageDataFilter { payload: { filter: string }; } +export interface AssignedTrustedAppsListStateChanged + extends Action<'assignedTrustedAppsListStateChanged'> { + payload: PolicyArtifactsState['assignedList']; +} + +export interface PolicyDetailsListOfAllPoliciesStateChanged + extends Action<'policyDetailsListOfAllPoliciesStateChanged'> { + payload: PolicyArtifactsState['policies']; +} + +export type PolicyDetailsTrustedAppsForceListDataRefresh = + Action<'policyDetailsTrustedAppsForceListDataRefresh'>; + +/** + * All of the possible actions for Trusted Apps under the Policy Details store + */ export type PolicyTrustedAppsAction = | PolicyArtifactsAssignableListPageDataChanged | PolicyArtifactsUpdateTrustedApps | PolicyArtifactsUpdateTrustedAppsChanged | PolicyArtifactsAssignableListExistDataChanged - | PolicyArtifactsAssignableListPageDataFilter; + | PolicyArtifactsAssignableListPageDataFilter + | AssignedTrustedAppsListStateChanged + | PolicyDetailsListOfAllPoliciesStateChanged + | PolicyDetailsTrustedAppsForceListDataRefresh; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/index.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/index.ts index 6b7e4e7d541c8..acc94f3383a84 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/index.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/index.ts @@ -6,9 +6,10 @@ */ import { ImmutableMiddlewareFactory } from '../../../../../../common/store'; -import { PolicyDetailsState } from '../../../types'; +import { MiddlewareRunnerContext, PolicyDetailsState } from '../../../types'; import { policyTrustedAppsMiddlewareRunner } from './policy_trusted_apps_middleware'; import { policySettingsMiddlewareRunner } from './policy_settings_middleware'; +import { TrustedAppsHttpService } from '../../../../trusted_apps/service'; export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory = ( coreStart @@ -16,7 +17,13 @@ export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory (next) => async (action) => { next(action); - policySettingsMiddlewareRunner(coreStart, store, action); - policyTrustedAppsMiddlewareRunner(coreStart, store, action); + const trustedAppsService = new TrustedAppsHttpService(coreStart.http); + const middlewareContext: MiddlewareRunnerContext = { + coreStart, + trustedAppsService, + }; + + policySettingsMiddlewareRunner(middlewareContext, store, action); + policyTrustedAppsMiddlewareRunner(middlewareContext, store, action); }; }; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts index 73b244944e502..5f612f4f4e6f6 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_settings_middleware.ts @@ -27,7 +27,7 @@ import { NewPolicyData, PolicyData } from '../../../../../../../common/endpoint/ import { getPolicyDataForUpdate } from '../../../../../../../common/endpoint/service/policy'; export const policySettingsMiddlewareRunner: MiddlewareRunner = async ( - coreStart, + { coreStart }, { dispatch, getState }, action ) => { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_trusted_apps_middleware.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_trusted_apps_middleware.ts index 532e39b482401..32968e4de116f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_trusted_apps_middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/middleware/policy_trusted_apps_middleware.ts @@ -7,30 +7,95 @@ import pMap from 'p-map'; import { find, isEmpty } from 'lodash/fp'; -import { PolicyDetailsState, MiddlewareRunner } from '../../../types'; +import { + PolicyDetailsState, + MiddlewareRunner, + GetPolicyListResponse, + MiddlewareRunnerContext, + PolicyAssignedTrustedApps, + PolicyDetailsStore, +} from '../../../types'; import { policyIdFromParams, - isOnPolicyTrustedAppsPage, - getCurrentArtifactsLocation, getAssignableArtifactsList, + doesPolicyTrustedAppsListNeedUpdate, + getCurrentPolicyAssignedTrustedAppsState, + getLatestLoadedPolicyAssignedTrustedAppsState, + getTrustedAppsPolicyListState, + isPolicyTrustedAppListLoading, + getCurrentArtifactsLocation, + isOnPolicyTrustedAppsView, + getCurrentUrlLocationPaginationParams, } from '../selectors'; import { ImmutableArray, ImmutableObject, PostTrustedAppCreateRequest, TrustedApp, + Immutable, } from '../../../../../../../common/endpoint/types'; import { ImmutableMiddlewareAPI } from '../../../../../../common/store'; -import { TrustedAppsHttpService, TrustedAppsService } from '../../../../trusted_apps/service'; +import { TrustedAppsService } from '../../../../trusted_apps/service'; import { createLoadedResourceState, createLoadingResourceState, createUninitialisedResourceState, createFailedResourceState, + isLoadingResourceState, + isUninitialisedResourceState, } from '../../../../../state'; import { parseQueryFilterToKQL } from '../../../../../common/utils'; import { SEARCHABLE_FIELDS } from '../../../../trusted_apps/constants'; import { PolicyDetailsAction } from '../action'; +import { ServerApiError } from '../../../../../../common/types'; + +/** Runs all middleware actions associated with the Trusted Apps view in Policy Details */ +export const policyTrustedAppsMiddlewareRunner: MiddlewareRunner = async ( + context, + store, + action +) => { + const state = store.getState(); + + /* ----------------------------------------------------------- + If not on the Trusted Apps Policy view, then just return + ----------------------------------------------------------- */ + if (!isOnPolicyTrustedAppsView(state)) { + return; + } + + const { trustedAppsService } = context; + + switch (action.type) { + case 'userChangedUrl': + fetchPolicyTrustedAppsIfNeeded(context, store); + fetchAllPoliciesIfNeeded(context, store); + + if (action.type === 'userChangedUrl' && getCurrentArtifactsLocation(state).show === 'list') { + await searchTrustedApps(store, trustedAppsService); + } + + break; + + case 'policyDetailsTrustedAppsForceListDataRefresh': + fetchPolicyTrustedAppsIfNeeded(context, store, true); + break; + + case 'policyArtifactsUpdateTrustedApps': + if (getCurrentArtifactsLocation(state).show === 'list') { + await updateTrustedApps(store, trustedAppsService, action.payload.trustedAppIds); + } + + break; + + case 'policyArtifactsAssignableListPageDataFilter': + if (getCurrentArtifactsLocation(state).show === 'list') { + await searchTrustedApps(store, trustedAppsService, action.payload.filter); + } + + break; + } +}; const checkIfThereAreAssignableTrustedApps = async ( store: ImmutableMiddlewareAPI, @@ -172,6 +237,8 @@ const updateTrustedApps = async ( type: 'policyArtifactsUpdateTrustedAppsChanged', payload: createLoadedResourceState(updatedTrustedApps), }); + + store.dispatch({ type: 'policyDetailsTrustedAppsForceListDataRefresh' }); } catch (err) { store.dispatch({ type: 'policyArtifactsUpdateTrustedAppsChanged', @@ -182,31 +249,89 @@ const updateTrustedApps = async ( } }; -export const policyTrustedAppsMiddlewareRunner: MiddlewareRunner = async ( - coreStart, - store, - action +const fetchPolicyTrustedAppsIfNeeded = async ( + { trustedAppsService }: MiddlewareRunnerContext, + { getState, dispatch }: PolicyDetailsStore, + forceFetch: boolean = false ) => { - const http = coreStart.http; - const trustedAppsService = new TrustedAppsHttpService(http); - const state = store.getState(); - if ( - action.type === 'userChangedUrl' && - isOnPolicyTrustedAppsPage(state) && - getCurrentArtifactsLocation(state).show === 'list' - ) { - await searchTrustedApps(store, trustedAppsService); - } else if ( - action.type === 'policyArtifactsUpdateTrustedApps' && - isOnPolicyTrustedAppsPage(state) && - getCurrentArtifactsLocation(state).show === 'list' - ) { - await updateTrustedApps(store, trustedAppsService, action.payload.trustedAppIds); - } else if ( - action.type === 'policyArtifactsAssignableListPageDataFilter' && - isOnPolicyTrustedAppsPage(state) && - getCurrentArtifactsLocation(state).show === 'list' - ) { - await searchTrustedApps(store, trustedAppsService, action.payload.filter); + const state = getState(); + + if (isPolicyTrustedAppListLoading(state)) { + return; + } + + if (forceFetch || doesPolicyTrustedAppsListNeedUpdate(state)) { + dispatch({ + type: 'assignedTrustedAppsListStateChanged', + // @ts-ignore will be fixed when AsyncResourceState is refactored (#830) + payload: createLoadingResourceState(getCurrentPolicyAssignedTrustedAppsState(state)), + }); + + try { + const urlLocationData = getCurrentUrlLocationPaginationParams(state); + const policyId = policyIdFromParams(state); + const fetchResponse = await trustedAppsService.getTrustedAppsList({ + page: urlLocationData.page_index + 1, + per_page: urlLocationData.page_size, + kuery: `((exception-list-agnostic.attributes.tags:"policy:${policyId}") OR (exception-list-agnostic.attributes.tags:"policy:all"))${ + urlLocationData.filter ? ` AND (${urlLocationData.filter})` : '' + }`, + }); + + dispatch({ + type: 'assignedTrustedAppsListStateChanged', + payload: createLoadedResourceState>({ + location: urlLocationData, + artifacts: fetchResponse, + }), + }); + } catch (error) { + dispatch({ + type: 'assignedTrustedAppsListStateChanged', + payload: createFailedResourceState>( + error as ServerApiError, + getLatestLoadedPolicyAssignedTrustedAppsState(getState()) + ), + }); + } + } +}; + +const fetchAllPoliciesIfNeeded = async ( + { trustedAppsService }: MiddlewareRunnerContext, + { getState, dispatch }: PolicyDetailsStore +) => { + const state = getState(); + const currentPoliciesState = getTrustedAppsPolicyListState(state); + const isLoading = isLoadingResourceState(currentPoliciesState); + const hasBeenLoaded = !isUninitialisedResourceState(currentPoliciesState); + + if (isLoading || hasBeenLoaded) { + return; + } + + dispatch({ + type: 'policyDetailsListOfAllPoliciesStateChanged', + // @ts-ignore will be fixed when AsyncResourceState is refactored (#830) + payload: createLoadingResourceState(currentPoliciesState), + }); + + try { + const policyList = await trustedAppsService.getPolicyList({ + query: { + page: 1, + perPage: 1000, + }, + }); + + dispatch({ + type: 'policyDetailsListOfAllPoliciesStateChanged', + payload: createLoadedResourceState(policyList), + }); + } catch (error) { + dispatch({ + type: 'policyDetailsListOfAllPoliciesStateChanged', + payload: createFailedResourceState(error.body || error), + }); } }; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/initial_policy_details_state.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/initial_policy_details_state.ts index 93108e6f376ae..3c279e696ee51 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/initial_policy_details_state.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/initial_policy_details_state.ts @@ -37,5 +37,7 @@ export const initialPolicyDetailsState: () => Immutable = () assignableList: createUninitialisedResourceState(), trustedAppsToUpdate: createUninitialisedResourceState(), assignableListEntriesExist: createUninitialisedResourceState(), + assignedList: createUninitialisedResourceState(), + policies: createUninitialisedResourceState(), }, }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/trusted_apps_reducer.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/trusted_apps_reducer.test.ts index 26efcaa68686d..e1d2fab6dcdb6 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/trusted_apps_reducer.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/trusted_apps_reducer.test.ts @@ -5,7 +5,7 @@ * 2.0. */ import { PolicyDetailsState } from '../../../types'; -import { initialPolicyDetailsState } from '../reducer/initial_policy_details_state'; +import { initialPolicyDetailsState } from './initial_policy_details_state'; import { policyTrustedAppsReducer } from './trusted_apps_reducer'; import { ImmutableObject } from '../../../../../../../common/endpoint/types'; @@ -16,12 +16,20 @@ import { createFailedResourceState, } from '../../../../../state'; import { getMockListResponse, getAPIError, getMockCreateResponse } from '../../../test_utils'; +import { getPolicyDetailsArtifactsListPath } from '../../../../../common/routing'; describe('policy trusted apps reducer', () => { let initialState: ImmutableObject; beforeEach(() => { - initialState = initialPolicyDetailsState(); + initialState = { + ...initialPolicyDetailsState(), + location: { + pathname: getPolicyDetailsArtifactsListPath('abc'), + search: '', + hash: '', + }, + }; }); describe('PolicyTrustedApps', () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/trusted_apps_reducer.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/trusted_apps_reducer.ts index e2843ec83ee2a..fdf15f0d67825 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/trusted_apps_reducer.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/reducer/trusted_apps_reducer.ts @@ -9,11 +9,28 @@ import { ImmutableReducer } from '../../../../../../common/store'; import { PolicyDetailsState } from '../../../types'; import { AppAction } from '../../../../../../common/store/actions'; import { initialPolicyDetailsState } from './initial_policy_details_state'; +import { isUninitialisedResourceState } from '../../../../../state'; +import { getCurrentPolicyAssignedTrustedAppsState, isOnPolicyTrustedAppsView } from '../selectors'; export const policyTrustedAppsReducer: ImmutableReducer = ( state = initialPolicyDetailsState(), action ) => { + /* ---------------------------------------------------------- + If not on the Trusted Apps Policy view, then just return + ---------------------------------------------------------- */ + if (!isOnPolicyTrustedAppsView(state)) { + // If the artifacts state namespace needs resetting, then do it now + if (!isUninitialisedResourceState(getCurrentPolicyAssignedTrustedAppsState(state))) { + return { + ...state, + artifacts: initialPolicyDetailsState().artifacts, + }; + } + + return state; + } + if (action.type === 'policyArtifactsAssignableListPageDataChanged') { return { ...state, @@ -44,5 +61,25 @@ export const policyTrustedAppsReducer: ImmutableReducer = (state) => state.artifacts.location; + +export const getUrlLocationPathname: PolicyDetailsSelector = (state) => + state.location?.pathname; + +/** Returns a boolean of whether the user is on the policy form page or not */ +export const isOnPolicyFormView: PolicyDetailsSelector = createSelector( + getUrlLocationPathname, + (pathname) => { + return ( + matchPath(pathname ?? '', { + path: MANAGEMENT_ROUTING_POLICY_DETAILS_FORM_PATH, + exact: true, + }) !== null + ); + } +); + +/** Returns a boolean of whether the user is on the policy details page or not */ +export const isOnPolicyTrustedAppsView: PolicyDetailsSelector = createSelector( + getUrlLocationPathname, + (pathname) => { + return ( + matchPath(pathname ?? '', { + path: MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH, + exact: true, + }) !== null + ); + } +); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_settings_selectors.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_settings_selectors.ts index 84049c98eaa11..40d77f5869b67 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_settings_selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/policy_settings_selectors.ts @@ -23,8 +23,8 @@ import { MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH, } from '../../../../../common/constants'; import { ManagementRoutePolicyDetailsParams } from '../../../../../types'; -import { getPolicyDataForUpdate } from '../../../../../../../common/endpoint/service/policy/get_policy_data_for_update'; -import { isOnPolicyTrustedAppsPage } from './trusted_apps_selectors'; +import { getPolicyDataForUpdate } from '../../../../../../../common/endpoint/service/policy'; +import { isOnPolicyTrustedAppsView, isOnPolicyFormView } from './policy_common_selectors'; /** Returns the policy details */ export const policyDetails = (state: Immutable) => state.policyItem; @@ -81,19 +81,9 @@ export const needsToRefresh = (state: Immutable): boolean => return !state.policyItem && !state.apiError; }; -/** Returns a boolean of whether the user is on the policy form page or not */ -export const isOnPolicyFormPage = (state: Immutable) => { - return ( - matchPath(state.location?.pathname ?? '', { - path: MANAGEMENT_ROUTING_POLICY_DETAILS_FORM_PATH, - exact: true, - }) !== null - ); -}; - /** Returns a boolean of whether the user is on some of the policy details page or not */ export const isOnPolicyDetailsPage = (state: Immutable) => - isOnPolicyFormPage(state) || isOnPolicyTrustedAppsPage(state); + isOnPolicyFormView(state) || isOnPolicyTrustedAppsView(state); /** Returns the license info fetched from the license service */ export const license = (state: Immutable) => { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/trusted_apps_selectors.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/trusted_apps_selectors.test.ts index 6d32988464957..6839edb965332 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/trusted_apps_selectors.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/trusted_apps_selectors.test.ts @@ -6,9 +6,8 @@ */ import { PolicyDetailsState } from '../../../types'; -import { initialPolicyDetailsState } from '../reducer/initial_policy_details_state'; +import { initialPolicyDetailsState } from '../reducer'; import { - getCurrentArtifactsLocation, getAssignableArtifactsList, getAssignableArtifactsListIsLoading, getUpdateArtifactsIsLoading, @@ -17,8 +16,8 @@ import { getAssignableArtifactsListExist, getAssignableArtifactsListExistIsLoading, getUpdateArtifacts, - isOnPolicyTrustedAppsPage, } from './trusted_apps_selectors'; +import { getCurrentArtifactsLocation, isOnPolicyTrustedAppsView } from './policy_common_selectors'; import { ImmutableObject } from '../../../../../../../common/endpoint/types'; import { @@ -39,7 +38,7 @@ describe('policy trusted apps selectors', () => { describe('isOnPolicyTrustedAppsPage()', () => { it('when location is on policy trusted apps page', () => { - const isOnPage = isOnPolicyTrustedAppsPage({ + const isOnPage = isOnPolicyTrustedAppsView({ ...initialState, location: { pathname: MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH, @@ -50,7 +49,7 @@ describe('policy trusted apps selectors', () => { expect(isOnPage).toBeFalsy(); }); it('when location is not on policy trusted apps page', () => { - const isOnPage = isOnPolicyTrustedAppsPage({ + const isOnPage = isOnPolicyTrustedAppsView({ ...initialState, location: { pathname: '', search: '', hash: '' }, }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/trusted_apps_selectors.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/trusted_apps_selectors.ts index 65d24ac58cab4..b168ec18107c2 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/trusted_apps_selectors.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/selectors/trusted_apps_selectors.ts @@ -5,35 +5,48 @@ * 2.0. */ -import { matchPath } from 'react-router-dom'; -import { PolicyDetailsArtifactsPageLocation, PolicyDetailsState } from '../../../types'; +import { createSelector } from 'reselect'; +import { Pagination } from '@elastic/eui'; +import { + PolicyArtifactsState, + PolicyAssignedTrustedApps, + PolicyDetailsArtifactsPageListLocationParams, + PolicyDetailsSelector, + PolicyDetailsState, +} from '../../../types'; import { Immutable, ImmutableArray, PostTrustedAppCreateResponse, - GetTrustedListAppsResponse, + GetTrustedAppsListResponse, + PolicyData, } from '../../../../../../../common/endpoint/types'; -import { MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH } from '../../../../../common/constants'; +import { MANAGEMENT_PAGE_SIZE_OPTIONS } from '../../../../../common/constants'; import { getLastLoadedResourceState, isFailedResourceState, isLoadedResourceState, isLoadingResourceState, + LoadedResourceState, } from '../../../../../state'; +import { getCurrentArtifactsLocation } from './policy_common_selectors'; -/** - * Returns current artifacts location - */ -export const getCurrentArtifactsLocation = ( - state: Immutable -): Immutable => state.artifacts.location; +export const doesPolicyHaveTrustedApps = ( + state: PolicyDetailsState +): { loading: boolean; hasTrustedApps: boolean } => { + // TODO: implement empty state (task #1645) + return { + loading: false, + hasTrustedApps: true, + }; +}; /** * Returns current assignable artifacts list */ export const getAssignableArtifactsList = ( state: Immutable -): Immutable | undefined => +): Immutable | undefined => getLastLoadedResourceState(state.artifacts.assignableList)?.data; /** @@ -92,12 +105,79 @@ export const getUpdateArtifacts = ( : undefined; }; -/** Returns a boolean of whether the user is on the policy details page or not */ -export const isOnPolicyTrustedAppsPage = (state: Immutable) => { - return ( - matchPath(state.location?.pathname ?? '', { - path: MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH, - exact: true, - }) !== null - ); +export const getCurrentPolicyAssignedTrustedAppsState: PolicyDetailsSelector< + PolicyArtifactsState['assignedList'] +> = (state) => { + return state.artifacts.assignedList; }; + +export const getLatestLoadedPolicyAssignedTrustedAppsState: PolicyDetailsSelector< + undefined | LoadedResourceState +> = createSelector(getCurrentPolicyAssignedTrustedAppsState, (currentAssignedTrustedAppsState) => { + return getLastLoadedResourceState(currentAssignedTrustedAppsState); +}); + +export const getCurrentUrlLocationPaginationParams: PolicyDetailsSelector = + // eslint-disable-next-line @typescript-eslint/naming-convention + createSelector(getCurrentArtifactsLocation, ({ filter, page_index, page_size }) => { + return { filter, page_index, page_size }; + }); + +export const doesPolicyTrustedAppsListNeedUpdate: PolicyDetailsSelector = createSelector( + getCurrentPolicyAssignedTrustedAppsState, + getCurrentUrlLocationPaginationParams, + (assignedListState, locationData) => { + return ( + !isLoadedResourceState(assignedListState) || + (isLoadedResourceState(assignedListState) && + ( + Object.keys(locationData) as Array + ).some((key) => assignedListState.data.location[key] !== locationData[key])) + ); + } +); + +export const isPolicyTrustedAppListLoading: PolicyDetailsSelector = createSelector( + getCurrentPolicyAssignedTrustedAppsState, + (assignedState) => isLoadingResourceState(assignedState) +); + +export const getPolicyTrustedAppList: PolicyDetailsSelector = + createSelector(getLatestLoadedPolicyAssignedTrustedAppsState, (assignedState) => { + return assignedState?.data.artifacts.data ?? []; + }); + +export const getPolicyTrustedAppsListPagination: PolicyDetailsSelector = createSelector( + getLatestLoadedPolicyAssignedTrustedAppsState, + (currentAssignedTrustedAppsState) => { + const trustedAppsApiResponse = currentAssignedTrustedAppsState?.data.artifacts; + + return { + // Trusted apps api is `1` based for page - need to subtract here for `Pagination` component + pageIndex: trustedAppsApiResponse?.page ? trustedAppsApiResponse.page - 1 : 0, + pageSize: trustedAppsApiResponse?.per_page ?? MANAGEMENT_PAGE_SIZE_OPTIONS[0], + totalItemCount: trustedAppsApiResponse?.total || 0, + pageSizeOptions: [...MANAGEMENT_PAGE_SIZE_OPTIONS], + }; + } +); + +export const getTrustedAppsPolicyListState: PolicyDetailsSelector< + PolicyDetailsState['artifacts']['policies'] +> = (state) => state.artifacts.policies; + +export const getTrustedAppsListOfAllPolicies: PolicyDetailsSelector = createSelector( + getTrustedAppsPolicyListState, + (policyListState) => { + return getLastLoadedResourceState(policyListState)?.data.items ?? []; + } +); + +export const getTrustedAppsAllPoliciesById: PolicyDetailsSelector< + Record> +> = createSelector(getTrustedAppsListOfAllPolicies, (allPolicies) => { + return allPolicies.reduce>>((mapById, policy) => { + mapById[policy.id] = policy; + return mapById; + }, {}) as Immutable>>; +}); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/test_utils/index.ts b/x-pack/plugins/security_solution/public/management/pages/policy/test_utils/index.ts index 383b7e277babd..d92c41f5a1cc6 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/test_utils/index.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/test_utils/index.ts @@ -6,13 +6,13 @@ */ import { - GetTrustedListAppsResponse, + GetTrustedAppsListResponse, PostTrustedAppCreateResponse, } from '../../../../../common/endpoint/types'; import { createSampleTrustedApps, createSampleTrustedApp } from '../../trusted_apps/test_utils'; -export const getMockListResponse: () => GetTrustedListAppsResponse = () => ({ +export const getMockListResponse: () => GetTrustedAppsListResponse = () => ({ data: createSampleTrustedApps({}), per_page: 100, page: 1, diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/types.ts b/x-pack/plugins/security_solution/public/management/pages/policy/types.ts index 8e4e31a3c70e9..87f3243211c89 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/types.ts @@ -14,58 +14,41 @@ import { PolicyData, UIPolicyConfig, PostTrustedAppCreateResponse, - GetTrustedListAppsResponse, MaybeImmutable, + GetTrustedAppsListResponse, } from '../../../../common/endpoint/types'; import { ServerApiError } from '../../../common/types'; import { GetAgentStatusResponse, GetOnePackagePolicyResponse, GetPackagePoliciesResponse, - GetPackagesResponse, UpdatePackagePolicyResponse, } from '../../../../../fleet/common'; import { AsyncResourceState } from '../../state'; import { ImmutableMiddlewareAPI } from '../../../common/store'; import { AppAction } from '../../../common/store/actions'; +import { TrustedAppsService } from '../trusted_apps/service'; + +export type PolicyDetailsStore = ImmutableMiddlewareAPI; /** * Function that runs Policy Details middleware */ export type MiddlewareRunner = ( - coreStart: CoreStart, - store: ImmutableMiddlewareAPI, + context: MiddlewareRunnerContext, + store: PolicyDetailsStore, action: MaybeImmutable ) => Promise; -/** - * Policy list store state - */ -export interface PolicyListState { - /** Array of policy items */ - policyItems: PolicyData[]; - /** Information about the latest endpoint package */ - endpointPackageInfo?: GetPackagesResponse['response'][0]; - /** API error if loading data failed */ - apiError?: ServerApiError; - /** total number of policies */ - total: number; - /** Number of policies per page */ - pageSize: number; - /** page number (zero based) */ - pageIndex: number; - /** data is being retrieved from server */ - isLoading: boolean; - /** current location information */ - location?: Immutable; - /** policy is being deleted */ - isDeleting: boolean; - /** Deletion status */ - deleteStatus?: boolean; - /** A summary of stats for the agents associated with a given Fleet Agent Policy */ - agentStatusSummary?: GetAgentStatusResponse['results']; +export interface MiddlewareRunnerContext { + coreStart: CoreStart; + trustedAppsService: TrustedAppsService; } +export type PolicyDetailsSelector = ( + state: Immutable +) => Immutable; + /** * Policy details store state */ @@ -90,6 +73,11 @@ export interface PolicyDetailsState { license?: ILicense; } +export interface PolicyAssignedTrustedApps { + location: PolicyDetailsArtifactsPageListLocationParams; + artifacts: GetTrustedAppsListResponse; +} + /** * Policy artifacts store state */ @@ -97,11 +85,15 @@ export interface PolicyArtifactsState { /** artifacts location params */ location: PolicyDetailsArtifactsPageLocation; /** A list of artifacts can be linked to the policy */ - assignableList: AsyncResourceState; - /** Represents if avaialble trusted apps entries exist, regardless of whether the list is showing results */ + assignableList: AsyncResourceState; + /** Represents if available trusted apps entries exist, regardless of whether the list is showing results */ assignableListEntriesExist: AsyncResourceState; /** A list of trusted apps going to be updated */ trustedAppsToUpdate: AsyncResourceState; + /** List of artifacts currently assigned to the policy (body specific and global) */ + assignedList: AsyncResourceState; + /** A list of all available polices */ + policies: AsyncResourceState; } export enum OS { @@ -110,13 +102,17 @@ export enum OS { linux = 'linux', } -export interface PolicyDetailsArtifactsPageLocation { +export interface PolicyDetailsArtifactsPageListLocationParams { page_index: number; page_size: number; - show?: 'list'; filter: string; } +export interface PolicyDetailsArtifactsPageLocation + extends PolicyDetailsArtifactsPageListLocationParams { + show?: 'list'; +} + /** * Returns the keys of an object whose values meet a criteria. * Ex) interface largeNestedObject = { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/assignable/policy_artifacts_assignable_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/assignable/policy_artifacts_assignable_list.tsx index 7046b289063f6..32f6b43a7ac98 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/assignable/policy_artifacts_assignable_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/artifacts/assignable/policy_artifacts_assignable_list.tsx @@ -8,7 +8,7 @@ import React, { useMemo } from 'react'; import { - GetTrustedListAppsResponse, + GetTrustedAppsListResponse, Immutable, TrustedApp, } from '../../../../../../../common/endpoint/types'; @@ -16,7 +16,7 @@ import { Loader } from '../../../../../../common/components/loader'; import { ArtifactEntryCardMinified } from '../../../../../components/artifact_entry_card'; export interface PolicyArtifactsAssignableListProps { - artifacts: Immutable; // Or other artifacts type like Event Filters or Endpoint Exceptions + artifacts: Immutable; // Or other artifacts type like Event Filters or Endpoint Exceptions selectedArtifactIds: string[]; selectedArtifactsUpdated: (id: string, selected: boolean) => void; isListLoading: boolean; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx index 80ee88e826852..da37590dcb9aa 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx @@ -12,8 +12,8 @@ import { EuiTabbedContent, EuiSpacer, EuiTabbedContentTab } from '@elastic/eui'; import { usePolicyDetailsSelector } from '../policy_hooks'; import { - isOnPolicyFormPage, - isOnPolicyTrustedAppsPage, + isOnPolicyFormView, + isOnPolicyTrustedAppsView, policyIdFromParams, } from '../../store/policy_details/selectors'; @@ -23,8 +23,8 @@ import { getPolicyDetailPath, getPolicyTrustedAppsPath } from '../../../../commo export const PolicyTabs = React.memo(() => { const history = useHistory(); - const isInSettingsTab = usePolicyDetailsSelector(isOnPolicyFormPage); - const isInTrustedAppsTab = usePolicyDetailsSelector(isOnPolicyTrustedAppsPage); + const isInSettingsTab = usePolicyDetailsSelector(isOnPolicyFormView); + const isInTrustedAppsTab = usePolicyDetailsSelector(isOnPolicyTrustedAppsView); const policyId = usePolicyDetailsSelector(policyIdFromParams); const tabs = useMemo( diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/index.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/index.ts new file mode 100644 index 0000000000000..1360b7ba60e37 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/index.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { PolicyTrustedAppsLayout } from './layout'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/layout/policy_trusted_apps_layout.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/layout/policy_trusted_apps_layout.tsx index f29b6a9feae3b..d2a0c0867c717 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/layout/policy_trusted_apps_layout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/layout/policy_trusted_apps_layout.tsx @@ -17,6 +17,7 @@ import { import { getCurrentArtifactsLocation } from '../../../store/policy_details/selectors'; import { usePolicyDetailsNavigateCallback, usePolicyDetailsSelector } from '../../policy_hooks'; import { PolicyTrustedAppsFlyout } from '../flyout'; +import { PolicyTrustedAppsList } from '../list/policy_trusted_apps_list'; export const PolicyTrustedAppsLayout = React.memo(() => { const location = usePolicyDetailsSelector(getCurrentArtifactsLocation); @@ -67,8 +68,7 @@ export const PolicyTrustedAppsLayout = React.memo(() => { color="transparent" borderRadius="none" > - {/* TODO: To be implemented */} - {'Policy trusted apps layout content'} + {showListFlyout ? : null}
    diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.tsx new file mode 100644 index 0000000000000..4463a395043a4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.tsx @@ -0,0 +1,192 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; +import { EuiLoadingSpinner, EuiSpacer, EuiText, Pagination } from '@elastic/eui'; +import { useHistory } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; +import { + ArtifactCardGrid, + ArtifactCardGridCardComponentProps, + ArtifactCardGridProps, +} from '../../../../../components/artifact_card_grid'; +import { usePolicyDetailsSelector } from '../../policy_hooks'; +import { + doesPolicyHaveTrustedApps, + getCurrentArtifactsLocation, + getPolicyTrustedAppList, + getPolicyTrustedAppsListPagination, + getTrustedAppsAllPoliciesById, + isPolicyTrustedAppListLoading, + policyIdFromParams, +} from '../../../store/policy_details/selectors'; +import { + getPolicyDetailPath, + getPolicyDetailsArtifactsListPath, + getTrustedAppsListPath, +} from '../../../../../common/routing'; +import { Immutable, TrustedApp } from '../../../../../../../common/endpoint/types'; +import { useAppUrl } from '../../../../../../common/lib/kibana'; +import { APP_ID } from '../../../../../../../common/constants'; +import { ContextMenuItemNavByRouterProps } from '../../../../../components/context_menu_with_router_support/context_menu_item_nav_by_router'; +import { ArtifactEntryCollapsibleCardProps } from '../../../../../components/artifact_entry_card'; + +export const PolicyTrustedAppsList = memo(() => { + const history = useHistory(); + const { getAppUrl } = useAppUrl(); + const policyId = usePolicyDetailsSelector(policyIdFromParams); + const hasTrustedApps = usePolicyDetailsSelector(doesPolicyHaveTrustedApps); + const isLoading = usePolicyDetailsSelector(isPolicyTrustedAppListLoading); + const trustedAppItems = usePolicyDetailsSelector(getPolicyTrustedAppList); + const pagination = usePolicyDetailsSelector(getPolicyTrustedAppsListPagination); + const urlParams = usePolicyDetailsSelector(getCurrentArtifactsLocation); + const allPoliciesById = usePolicyDetailsSelector(getTrustedAppsAllPoliciesById); + + const [isCardExpanded, setCardExpanded] = useState>({}); + + // TODO:PT show load errors if any + + const handlePageChange = useCallback( + ({ pageIndex, pageSize }) => { + history.push( + getPolicyDetailsArtifactsListPath(policyId, { + ...urlParams, + // If user changed page size, then reset page index back to the first page + page_index: pageSize !== pagination.pageSize ? 0 : pageIndex, + page_size: pageSize, + }) + ); + }, + [history, pagination.pageSize, policyId, urlParams] + ); + + const handleExpandCollapse = useCallback( + ({ expanded, collapsed }) => { + const newCardExpandedSettings: Record = {}; + + for (const trustedApp of expanded) { + newCardExpandedSettings[trustedApp.id] = true; + } + + for (const trustedApp of collapsed) { + newCardExpandedSettings[trustedApp.id] = false; + } + + setCardExpanded(newCardExpandedSettings); + }, + [] + ); + + const totalItemsCountLabel = useMemo(() => { + return i18n.translate('xpack.securitySolution.endpoint.policy.trustedApps.list.totalCount', { + defaultMessage: + 'Showing {totalItemsCount, plural, one {# trusted application} other {# trusted applications}}', + values: { totalItemsCount: pagination.totalItemCount }, + }); + }, [pagination.totalItemCount]); + + const cardProps = useMemo, ArtifactCardGridCardComponentProps>>(() => { + const newCardProps = new Map(); + + for (const trustedApp of trustedAppItems) { + const viewUrlPath = getTrustedAppsListPath({ id: trustedApp.id, show: 'edit' }); + const assignedPoliciesMenuItems: ArtifactEntryCollapsibleCardProps['policies'] = + trustedApp.effectScope.type === 'global' + ? undefined + : trustedApp.effectScope.policies.reduce< + Required['policies'] + >((byIdPolicies, trustedAppAssignedPolicyId) => { + if (!allPoliciesById[trustedAppAssignedPolicyId]) { + byIdPolicies[trustedAppAssignedPolicyId] = { children: trustedAppAssignedPolicyId }; + return byIdPolicies; + } + + const policyDetailsPath = getPolicyDetailPath(trustedAppAssignedPolicyId); + + const thisPolicyMenuProps: ContextMenuItemNavByRouterProps = { + navigateAppId: APP_ID, + navigateOptions: { + path: policyDetailsPath, + }, + href: getAppUrl({ path: policyDetailsPath }), + children: allPoliciesById[trustedAppAssignedPolicyId].name, + }; + + byIdPolicies[trustedAppAssignedPolicyId] = thisPolicyMenuProps; + + return byIdPolicies; + }, {}); + + const thisTrustedAppCardProps: ArtifactCardGridCardComponentProps = { + expanded: Boolean(isCardExpanded[trustedApp.id]), + actions: [ + { + icon: 'controlsHorizontal', + children: i18n.translate( + 'xpack.securitySolution.endpoint.policy.trustedApps.list.viewAction', + { defaultMessage: 'View full details' } + ), + href: getAppUrl({ appId: APP_ID, path: viewUrlPath }), + navigateAppId: APP_ID, + navigateOptions: { path: viewUrlPath }, + }, + ], + policies: assignedPoliciesMenuItems, + }; + + newCardProps.set(trustedApp, thisTrustedAppCardProps); + } + + return newCardProps; + }, [allPoliciesById, getAppUrl, isCardExpanded, trustedAppItems]); + + const provideCardProps = useCallback['cardComponentProps']>( + (item) => { + return cardProps.get(item as Immutable)!; + }, + [cardProps] + ); + + // Anytime a new set of data (trusted apps) is retrieved, reset the card expand state + useEffect(() => { + setCardExpanded({}); + }, [trustedAppItems]); + + if (hasTrustedApps.loading) { + return ( +
    + +
    + ); + } + + if (!hasTrustedApps.hasTrustedApps) { + // TODO: implement empty state (task #1645) + return
    {'No trusted application'}
    ; + } + + return ( + <> + + {totalItemsCountLabel} + + + + + + + ); +}); +PolicyTrustedAppsList.displayName = 'PolicyTrustedAppsList'; diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/index.ts b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/index.ts index c643094e61126..09aa80ffae495 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/index.ts +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/index.ts @@ -18,7 +18,7 @@ import { import { DeleteTrustedAppsRequestParams, - GetTrustedListAppsResponse, + GetTrustedAppsListResponse, GetTrustedAppsListRequest, PostTrustedAppCreateRequest, PostTrustedAppCreateResponse, @@ -36,7 +36,7 @@ import { sendGetEndpointSpecificPackagePolicies } from '../../policy/store/servi export interface TrustedAppsService { getTrustedApp(params: GetOneTrustedAppRequestParams): Promise; - getTrustedAppsList(request: GetTrustedAppsListRequest): Promise; + getTrustedAppsList(request: GetTrustedAppsListRequest): Promise; deleteTrustedApp(request: DeleteTrustedAppsRequestParams): Promise; createTrustedApp(request: PostTrustedAppCreateRequest): Promise; updateTrustedApp( @@ -58,7 +58,7 @@ export class TrustedAppsHttpService implements TrustedAppsService { } async getTrustedAppsList(request: GetTrustedAppsListRequest) { - return this.http.get(TRUSTED_APPS_LIST_API, { + return this.http.get(TRUSTED_APPS_LIST_API, { query: request, }); } diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/__snapshots__/index.test.tsx.snap index 236a93d63bcee..e2b5ad43e40f2 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/trusted_apps_grid/__snapshots__/index.test.tsx.snap @@ -407,7 +407,7 @@ exports[`TrustedAppsGrid renders correctly when loaded data 1`] = ` class="body-content undefined" >
    { page: number = 1, // eslint-disable-next-line @typescript-eslint/naming-convention per_page: number = 20 - ): GetTrustedListAppsResponse => { + ): GetTrustedAppsListResponse => { return { data: [getFakeTrustedApp()], total: 50, // << Should be a value large enough to fulfill two pages @@ -683,7 +683,7 @@ describe('When on the Trusted Apps Page', () => { }); describe('and there are no trusted apps', () => { - const releaseExistsResponse: jest.MockedFunction<() => Promise> = + const releaseExistsResponse: jest.MockedFunction<() => Promise> = jest.fn(async () => { return { data: [], @@ -692,7 +692,7 @@ describe('When on the Trusted Apps Page', () => { per_page: 1, }; }); - const releaseListResponse: jest.MockedFunction<() => Promise> = + const releaseListResponse: jest.MockedFunction<() => Promise> = jest.fn(async () => { return { data: [], diff --git a/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts b/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts index 3fb05c8bf1048..0fcb05827358e 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/index.ts @@ -10,11 +10,17 @@ import { ToolingLog } from '@kbn/dev-utils'; import { KbnClient } from '@kbn/test'; import bluebird from 'bluebird'; import { basename } from 'path'; +import { AxiosResponse } from 'axios'; import { TRUSTED_APPS_CREATE_API, TRUSTED_APPS_LIST_API } from '../../../common/endpoint/constants'; import { TrustedApp } from '../../../common/endpoint/types'; import { TrustedAppGenerator } from '../../../common/endpoint/data_generators/trusted_app_generator'; import { indexFleetEndpointPolicy } from '../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; import { setupFleetForEndpoint } from '../../../common/endpoint/data_loaders/setup_fleet_for_endpoint'; +import { GetPolicyListResponse } from '../../../public/management/pages/policy/types'; +import { + PACKAGE_POLICY_API_ROUTES, + PACKAGE_POLICY_SAVED_OBJECT_TYPE, +} from '../../../../fleet/common'; const defaultLogger = new ToolingLog({ level: 'info', writeTo: process.stdout }); const separator = '----------------------------------------'; @@ -83,21 +89,25 @@ export const run: (options?: RunOptions) => Promise = async ({ }), ]); - // Setup a list of read endpoint policies and return a method to randomly select one + // Setup a list of real endpoint policies and return a method to randomly select one const randomPolicyId: () => string = await (async () => { const randomN = (max: number): number => Math.floor(Math.random() * max); - const policyIds: string[] = []; - - for (let i = 0, t = 5; i < t; i++) { - policyIds.push( - ( - await indexFleetEndpointPolicy( - kbnClient, - `Policy for Trusted App assignment ${i + 1}`, - installedEndpointPackage.version - ) - ).integrationPolicies[0].id - ); + const policyIds: string[] = + (await fetchEndpointPolicies(kbnClient)).data.items.map((policy) => policy.id) || []; + + // If the number of existing policies is less than 5, then create some more policies + if (policyIds.length < 5) { + for (let i = 0, t = 5 - policyIds.length; i < t; i++) { + policyIds.push( + ( + await indexFleetEndpointPolicy( + kbnClient, + `Policy for Trusted App assignment ${i + 1}`, + installedEndpointPackage.version + ) + ).integrationPolicies[0].id + ); + } } return () => policyIds[randomN(policyIds.length)]; @@ -153,3 +163,16 @@ const createRunLogger = () => { }, }); }; + +const fetchEndpointPolicies = ( + kbnClient: KbnClient +): Promise> => { + return kbnClient.request({ + method: 'GET', + path: PACKAGE_POLICY_API_ROUTES.LIST_PATTERN, + query: { + perPage: 100, + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, + }, + }); +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/service.ts b/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/service.ts index 7cbdbceaf24cc..9cefc55eddec4 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/service.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/service.ts @@ -16,7 +16,7 @@ import { GetOneTrustedAppResponse, GetTrustedAppsListRequest, GetTrustedAppsSummaryResponse, - GetTrustedListAppsResponse, + GetTrustedAppsListResponse, PostTrustedAppCreateRequest, PostTrustedAppCreateResponse, PutTrustedAppUpdateRequest, @@ -124,7 +124,7 @@ export const getTrustedApp = async ( export const getTrustedAppsList = async ( exceptionsListClient: ExceptionListClient, { page, per_page: perPage, kuery }: GetTrustedAppsListRequest -): Promise => { +): Promise => { // Ensure list is created if it does not exist await exceptionsListClient.createTrustedAppsList(); From c1f2b1983de66c796dd0ac69d76eab9048616a1a Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 4 Oct 2021 12:49:27 +0100 Subject: [PATCH 29/98] skip flaky suite (#106650) --- x-pack/test/functional/apps/infra/home_page.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/test/functional/apps/infra/home_page.ts index 78fc57e50bf31..c0bcee5f78966 100644 --- a/x-pack/test/functional/apps/infra/home_page.ts +++ b/x-pack/test/functional/apps/infra/home_page.ts @@ -86,7 +86,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); - describe('Saved Views', () => { + // FLAKY: https://github.com/elastic/kibana/issues/106650 + describe.skip('Saved Views', () => { before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs')); after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs')); it('should have save and load controls', async () => { From a99bdcacab9fabb99d50c226876774ea5bf73303 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 4 Oct 2021 13:02:23 +0100 Subject: [PATCH 30/98] skip failing es promotion suites (#113744) --- .../input_control_vis/input_control_range.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/dashboard_elements/input_control_vis/input_control_range.ts b/test/functional/apps/dashboard_elements/input_control_vis/input_control_range.ts index 566e6f033d2fd..29c914d76a8c5 100644 --- a/test/functional/apps/dashboard_elements/input_control_vis/input_control_range.ts +++ b/test/functional/apps/dashboard_elements/input_control_vis/input_control_range.ts @@ -18,7 +18,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const { visualize, visEditor } = getPageObjects(['visualize', 'visEditor']); - describe('input control range', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/113744 + describe.skip('input control range', () => { before(async () => { await PageObjects.visualize.initTests(); await security.testUser.setRoles(['kibana_admin', 'kibana_sample_admin']); From fefc34e28f72264997cbd5b190908eeaa9887097 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 4 Oct 2021 13:08:02 +0100 Subject: [PATCH 31/98] skip failing es promotion suites (#113745) --- test/functional/apps/management/_scripted_fields.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/management/_scripted_fields.js b/test/functional/apps/management/_scripted_fields.js index 4aa06f4cd9ad7..2e965c275d6dd 100644 --- a/test/functional/apps/management/_scripted_fields.js +++ b/test/functional/apps/management/_scripted_fields.js @@ -367,7 +367,8 @@ export default function ({ getService, getPageObjects }) { }); }); - describe('creating and using Painless date scripted fields', function describeIndexTests() { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/113745 + describe.skip('creating and using Painless date scripted fields', function describeIndexTests() { const scriptedPainlessFieldName2 = 'painDate'; it('should create scripted field', async function () { From edf16e60126427f5101e75b72f046fee7c491065 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Mon, 4 Oct 2021 15:33:21 +0200 Subject: [PATCH 32/98] Remove `jsonwebtoken` and `base64url` dependencies. (#113723) --- package.json | 3 -- renovate.json5 | 7 ++-- .../fixtures/oidc/oidc_tools.ts | 41 ++++++++++++------- yarn.lock | 11 +---- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index ac30b5de6f486..f436a13a057e9 100644 --- a/package.json +++ b/package.json @@ -272,7 +272,6 @@ "json-stable-stringify": "^1.0.1", "json-stringify-pretty-compact": "1.2.0", "json-stringify-safe": "5.0.1", - "jsonwebtoken": "^8.5.1", "jsts": "^1.6.2", "kea": "^2.4.2", "load-json-file": "^6.2.0", @@ -554,7 +553,6 @@ "@types/jsdom": "^16.2.3", "@types/json-stable-stringify": "^1.0.32", "@types/json5": "^0.0.30", - "@types/jsonwebtoken": "^8.5.5", "@types/license-checker": "15.0.0", "@types/listr": "^0.14.0", "@types/loader-utils": "^1.1.3", @@ -662,7 +660,6 @@ "babel-plugin-styled-components": "^1.13.2", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "backport": "^5.6.6", - "base64url": "^3.0.1", "callsites": "^3.1.0", "chai": "3.5.0", "chance": "1.0.18", diff --git a/renovate.json5 b/renovate.json5 index 12a30876291da..dea7d311bae16 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -86,10 +86,9 @@ { groupName: 'platform security modules', packageNames: [ - 'broadcast-channel', - 'jsonwebtoken', '@types/jsonwebtoken', - 'node-forge', '@types/node-forge', - 'require-in-the-middle', + 'broadcast-channel', + 'node-forge', '@types/node-forge', + 'require-in-the-middle', 'tough-cookie', '@types/tough-cookie', 'xml-crypto', '@types/xml-crypto' ], diff --git a/x-pack/test/security_api_integration/fixtures/oidc/oidc_tools.ts b/x-pack/test/security_api_integration/fixtures/oidc/oidc_tools.ts index 8d078994eb0e9..3db2e2ebdce0f 100644 --- a/x-pack/test/security_api_integration/fixtures/oidc/oidc_tools.ts +++ b/x-pack/test/security_api_integration/fixtures/oidc/oidc_tools.ts @@ -5,10 +5,8 @@ * 2.0. */ -import base64url from 'base64url'; -import { createHash } from 'crypto'; +import { createHash, createSign } from 'crypto'; import fs from 'fs'; -import jwt from 'jsonwebtoken'; import url from 'url'; export function getStateAndNonce(urlWithStateAndNonce: string) { @@ -16,16 +14,20 @@ export function getStateAndNonce(urlWithStateAndNonce: string) { return { state: parsedQuery.state as string, nonce: parsedQuery.nonce as string }; } +function fromBase64(base64: string) { + return base64.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); +} + export function createTokens(userId: string, nonce: string) { - const signingKey = fs.readFileSync(require.resolve('./jwks_private.pem')); - const iat = Math.floor(Date.now() / 1000); + const idTokenHeader = fromBase64( + Buffer.from(JSON.stringify({ alg: 'RS256' })).toString('base64') + ); + const iat = Math.floor(Date.now() / 1000); const accessToken = `valid-access-token${userId}`; const accessTokenHashBuffer = createHash('sha256').update(accessToken).digest(); - - return { - accessToken, - idToken: jwt.sign( + const idTokenBody = fromBase64( + Buffer.from( JSON.stringify({ iss: 'https://test-op.elastic.co', sub: `user${userId}`, @@ -34,10 +36,19 @@ export function createTokens(userId: string, nonce: string) { exp: iat + 3600, iat, // See more details on `at_hash` at https://openid.net/specs/openid-connect-core-1_0.html#ImplicitIDToken - at_hash: base64url(accessTokenHashBuffer.slice(0, accessTokenHashBuffer.length / 2)), - }), - signingKey, - { algorithm: 'RS256' } - ), - }; + at_hash: fromBase64( + accessTokenHashBuffer.slice(0, accessTokenHashBuffer.length / 2).toString('base64') + ), + }) + ).toString('base64') + ); + + const idToken = `${idTokenHeader}.${idTokenBody}`; + + const signingKey = fs.readFileSync(require.resolve('./jwks_private.pem')); + const idTokenSignature = fromBase64( + createSign('RSA-SHA256').update(idToken).sign(signingKey, 'base64') + ); + + return { accessToken, idToken: `${idToken}.${idTokenSignature}` }; } diff --git a/yarn.lock b/yarn.lock index 14cf34cae847b..83c0691646817 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6394,13 +6394,6 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.30.tgz#44cb52f32a809734ca562e685c6473b5754a7818" integrity sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA== -"@types/jsonwebtoken@^8.5.5": - version "8.5.5" - resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.5.tgz#da5f2f4baee88f052ef3e4db4c1a0afb46cff22c" - integrity sha512-OGqtHQ7N5/Ap/TUwO6IgHDuLiAoTmHhGpNvgkCm/F4N6pKzx/RBSfr2OXZSwC6vkfnsEdb6+7DNZVtiXiwdwFw== - dependencies: - "@types/node" "*" - "@types/keyv@*": version "3.1.1" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" @@ -9235,7 +9228,7 @@ base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.2.0, base64-js@^1.3.0, base64-j resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== -base64url@^3.0.0, base64url@^3.0.1: +base64url@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== @@ -19171,7 +19164,7 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= -jsonwebtoken@^8.3.0, jsonwebtoken@^8.5.1: +jsonwebtoken@^8.3.0: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== From 163133827b894468cb9dce4ed0a4aad493aff1f2 Mon Sep 17 00:00:00 2001 From: Kevin Lacabane Date: Mon, 4 Oct 2021 15:57:47 +0200 Subject: [PATCH 33/98] [Stack Monitoring] React migration kibana overview (#113604) * Create react Kibana template * React Kibana overview * Add breadcrumb to kibana overview * fix linting errors Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../monitoring/public/application/index.tsx | 11 +- .../pages/kibana/kibana_template.tsx | 30 +++++ .../application/pages/kibana/overview.tsx | 119 ++++++++++++++++++ 3 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/monitoring/public/application/pages/kibana/kibana_template.tsx create mode 100644 x-pack/plugins/monitoring/public/application/pages/kibana/overview.tsx diff --git a/x-pack/plugins/monitoring/public/application/index.tsx b/x-pack/plugins/monitoring/public/application/index.tsx index dea8d18bb65b1..acdf3b0986a64 100644 --- a/x-pack/plugins/monitoring/public/application/index.tsx +++ b/x-pack/plugins/monitoring/public/application/index.tsx @@ -23,7 +23,8 @@ import { ElasticsearchOverviewPage } from './pages/elasticsearch/overview'; import { BeatsOverviewPage } from './pages/beats/overview'; import { BeatsInstancesPage } from './pages/beats/instances'; import { BeatsInstancePage } from './pages/beats/instance'; -import { CODE_PATH_ELASTICSEARCH, CODE_PATH_BEATS } from '../../common/constants'; +import { KibanaOverviewPage } from './pages/kibana/overview'; +import { CODE_PATH_ELASTICSEARCH, CODE_PATH_BEATS, CODE_PATH_KIBANA } from '../../common/constants'; import { ElasticsearchNodesPage } from './pages/elasticsearch/nodes_page'; import { ElasticsearchIndicesPage } from './pages/elasticsearch/indices_page'; import { ElasticsearchNodePage } from './pages/elasticsearch/node_page'; @@ -133,6 +134,14 @@ const MonitoringApp: React.FC<{ fetchAllClusters={false} /> + {/* Kibana Views */} + + = ({ ...props }) => { + const tabs: TabMenuItem[] = [ + { + id: 'overview', + label: i18n.translate('xpack.monitoring.kibanaNavigation.overviewLinkText', { + defaultMessage: 'Overview', + }), + route: '/kibana', + }, + { + id: 'instances', + label: i18n.translate('xpack.monitoring.kibanaNavigation.instancesLinkText', { + defaultMessage: 'Instances', + }), + route: '/kibana/instances', + }, + ]; + + return ; +}; diff --git a/x-pack/plugins/monitoring/public/application/pages/kibana/overview.tsx b/x-pack/plugins/monitoring/public/application/pages/kibana/overview.tsx new file mode 100644 index 0000000000000..2356011a3f77b --- /dev/null +++ b/x-pack/plugins/monitoring/public/application/pages/kibana/overview.tsx @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useCallback, useContext, useEffect, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { find } from 'lodash'; +import { + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPanel, + EuiSpacer, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; + +import { KibanaTemplate } from './kibana_template'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { GlobalStateContext } from '../../global_state_context'; +import { ComponentProps } from '../../route_init'; +// @ts-ignore +import { MonitoringTimeseriesContainer } from '../../../components/chart'; +// @ts-ignore +import { ClusterStatus } from '../../../components/kibana/cluster_status'; +import { BreadcrumbContainer } from '../../hooks/use_breadcrumbs'; +import { useCharts } from '../../hooks/use_charts'; + +const KibanaOverview = ({ data }: { data: any }) => { + const { zoomInfo, onBrush } = useCharts(); + + if (!data) return null; + + return ( + + + + + + + + + + + + + + + + + + + ); +}; + +export const KibanaOverviewPage: React.FC = ({ clusters }) => { + const globalState = useContext(GlobalStateContext); + const { services } = useKibana<{ data: any }>(); + const { generate: generateBreadcrumbs } = useContext(BreadcrumbContainer.Context); + const [data, setData] = useState(); + const clusterUuid = globalState.cluster_uuid; + const cluster = find(clusters, { + cluster_uuid: clusterUuid, + }) as any; + const ccs = globalState.ccs; + const title = i18n.translate('xpack.monitoring.kibana.overview.title', { + defaultMessage: 'Kibana', + }); + const pageTitle = i18n.translate('xpack.monitoring.kibana.overview.pageTitle', { + defaultMessage: 'Kibana overview', + }); + + useEffect(() => { + if (cluster) { + generateBreadcrumbs(cluster.cluster_name, { + inKibana: true, + }); + } + }, [cluster, generateBreadcrumbs]); + + const getPageData = useCallback(async () => { + const bounds = services.data?.query.timefilter.timefilter.getBounds(); + const url = `../api/monitoring/v1/clusters/${clusterUuid}/kibana`; + + const response = await services.http?.fetch(url, { + method: 'POST', + body: JSON.stringify({ + ccs, + timeRange: { + min: bounds.min.toISOString(), + max: bounds.max.toISOString(), + }, + }), + }); + + setData(response); + }, [ccs, clusterUuid, services.data?.query.timefilter.timefilter, services.http]); + + return ( + + + + ); +}; From c868cd5c812a82f72fa21b3a4cd261160c910d39 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 4 Oct 2021 16:00:08 +0200 Subject: [PATCH 34/98] [Discover] Extract fetch observable initialization to separate function (#108831) * Don't trigger autorefresh when there's no time picker - because there's no UI for that * Refactor and add test * Add doc and test * Refactor * Remove index pattern without timefield filtering Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apps/main/services/use_saved_search.ts | 43 ++++----- .../apps/main/utils/get_fetch_observable.ts | 61 ++++++++++++ .../main/utils/get_fetch_observeable.test.ts | 95 +++++++++++++++++++ 3 files changed, 172 insertions(+), 27 deletions(-) create mode 100644 src/plugins/discover/public/application/apps/main/utils/get_fetch_observable.ts create mode 100644 src/plugins/discover/public/application/apps/main/utils/get_fetch_observeable.test.ts diff --git a/src/plugins/discover/public/application/apps/main/services/use_saved_search.ts b/src/plugins/discover/public/application/apps/main/services/use_saved_search.ts index 164dff8627790..26f95afba5a93 100644 --- a/src/plugins/discover/public/application/apps/main/services/use_saved_search.ts +++ b/src/plugins/discover/public/application/apps/main/services/use_saved_search.ts @@ -6,15 +6,14 @@ * Side Public License, v 1. */ import { useCallback, useEffect, useMemo, useRef } from 'react'; -import { BehaviorSubject, merge, Subject } from 'rxjs'; -import { debounceTime, filter, tap } from 'rxjs/operators'; +import { BehaviorSubject, Subject } from 'rxjs'; import { DiscoverServices } from '../../../../build_services'; import { DiscoverSearchSessionManager } from './discover_search_session'; import { SearchSource } from '../../../../../../data/common'; import { GetStateReturn } from './discover_state'; import { ElasticSearchHit } from '../../../doc_views/doc_views_types'; import { RequestAdapter } from '../../../../../../inspector/public'; -import { AutoRefreshDoneFn } from '../../../../../../data/public'; +import type { AutoRefreshDoneFn } from '../../../../../../data/public'; import { validateTimeRange } from '../utils/validate_time_range'; import { Chart } from '../components/chart/point_series'; import { useSingleton } from '../utils/use_singleton'; @@ -23,6 +22,7 @@ import { FetchStatus } from '../../../types'; import { fetchAll } from '../utils/fetch_all'; import { useBehaviorSubject } from '../utils/use_behavior_subject'; import { sendResetMsg } from './use_saved_search_messages'; +import { getFetch$ } from '../utils/get_fetch_observable'; export interface SavedSearchData { main$: DataMain$; @@ -134,6 +134,7 @@ export const useSavedSearch = ({ */ const refs = useRef<{ abortController?: AbortController; + autoRefreshDone?: AutoRefreshDoneFn; }>({}); /** @@ -145,29 +146,17 @@ export const useSavedSearch = ({ * handler emitted by `timefilter.getAutoRefreshFetch$()` * to notify when data completed loading and to start a new autorefresh loop */ - let autoRefreshDoneCb: AutoRefreshDoneFn | undefined; - const fetch$ = merge( + const setAutoRefreshDone = (fn: AutoRefreshDoneFn | undefined) => { + refs.current.autoRefreshDone = fn; + }; + const fetch$ = getFetch$({ + setAutoRefreshDone, + data, + main$, refetch$, - filterManager.getFetches$(), - timefilter.getFetch$(), - timefilter.getAutoRefreshFetch$().pipe( - tap((done) => { - autoRefreshDoneCb = done; - }), - filter(() => { - /** - * filter to prevent auto-refresh triggered fetch when - * loading is still ongoing - */ - const currentFetchStatus = main$.getValue().fetchStatus; - return ( - currentFetchStatus !== FetchStatus.LOADING && currentFetchStatus !== FetchStatus.PARTIAL - ); - }) - ), - data.query.queryString.getUpdates$(), - searchSessionManager.newSearchSessionIdFromURL$.pipe(filter((sessionId) => !!sessionId)) - ).pipe(debounceTime(100)); + searchSessionManager, + searchSource, + }); const subscription = fetch$.subscribe((val) => { if (!validateTimeRange(timefilter.getTime(), services.toastNotifications)) { @@ -190,8 +179,8 @@ export const useSavedSearch = ({ }).subscribe({ complete: () => { // if this function was set and is executed, another refresh fetch can be triggered - autoRefreshDoneCb?.(); - autoRefreshDoneCb = undefined; + refs.current.autoRefreshDone?.(); + refs.current.autoRefreshDone = undefined; }, }); } catch (error) { diff --git a/src/plugins/discover/public/application/apps/main/utils/get_fetch_observable.ts b/src/plugins/discover/public/application/apps/main/utils/get_fetch_observable.ts new file mode 100644 index 0000000000000..aac6196e64f6f --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/utils/get_fetch_observable.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { merge } from 'rxjs'; +import { debounceTime, filter, tap } from 'rxjs/operators'; + +import { FetchStatus } from '../../../types'; +import type { + AutoRefreshDoneFn, + DataPublicPluginStart, + SearchSource, +} from '../../../../../../data/public'; +import { DataMain$, DataRefetch$ } from '../services/use_saved_search'; +import { DiscoverSearchSessionManager } from '../services/discover_search_session'; + +/** + * This function returns an observable that's used to trigger data fetching + */ +export function getFetch$({ + setAutoRefreshDone, + data, + main$, + refetch$, + searchSessionManager, +}: { + setAutoRefreshDone: (val: AutoRefreshDoneFn | undefined) => void; + data: DataPublicPluginStart; + main$: DataMain$; + refetch$: DataRefetch$; + searchSessionManager: DiscoverSearchSessionManager; + searchSource: SearchSource; +}) { + const { timefilter } = data.query.timefilter; + const { filterManager } = data.query; + return merge( + refetch$, + filterManager.getFetches$(), + timefilter.getFetch$(), + timefilter.getAutoRefreshFetch$().pipe( + tap((done) => { + setAutoRefreshDone(done); + }), + filter(() => { + const currentFetchStatus = main$.getValue().fetchStatus; + return ( + /** + * filter to prevent auto-refresh triggered fetch when + * loading is still ongoing + */ + currentFetchStatus !== FetchStatus.LOADING && currentFetchStatus !== FetchStatus.PARTIAL + ); + }) + ), + data.query.queryString.getUpdates$(), + searchSessionManager.newSearchSessionIdFromURL$.pipe(filter((sessionId) => !!sessionId)) + ).pipe(debounceTime(100)); +} diff --git a/src/plugins/discover/public/application/apps/main/utils/get_fetch_observeable.test.ts b/src/plugins/discover/public/application/apps/main/utils/get_fetch_observeable.test.ts new file mode 100644 index 0000000000000..5f728b115b2e9 --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/utils/get_fetch_observeable.test.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { getFetch$ } from './get_fetch_observable'; +import { FetchStatus } from '../../../types'; +import { BehaviorSubject, Subject } from 'rxjs'; +import { DataPublicPluginStart } from '../../../../../../data/public'; +import { createSearchSessionMock } from '../../../../__mocks__/search_session'; +import { DataRefetch$ } from '../services/use_saved_search'; +import { savedSearchMock, savedSearchMockWithTimeField } from '../../../../__mocks__/saved_search'; + +function createDataMock( + queryString$: Subject, + filterManager$: Subject, + timefilterFetch$: Subject, + autoRefreshFetch$: Subject +) { + return { + query: { + queryString: { + getUpdates$: () => { + return queryString$; + }, + }, + filterManager: { + getFetches$: () => { + return filterManager$; + }, + }, + timefilter: { + timefilter: { + getFetch$: () => { + return timefilterFetch$; + }, + getAutoRefreshFetch$: () => { + return autoRefreshFetch$; + }, + }, + }, + }, + } as unknown as DataPublicPluginStart; +} + +describe('getFetchObservable', () => { + test('refetch$.next should trigger fetch$.next', async (done) => { + const searchSessionManagerMock = createSearchSessionMock(); + + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }); + const refetch$: DataRefetch$ = new Subject(); + const fetch$ = getFetch$({ + setAutoRefreshDone: jest.fn(), + main$, + refetch$, + data: createDataMock(new Subject(), new Subject(), new Subject(), new Subject()), + searchSessionManager: searchSessionManagerMock.searchSessionManager, + searchSource: savedSearchMock.searchSource, + }); + + fetch$.subscribe(() => { + done(); + }); + refetch$.next(); + }); + test('getAutoRefreshFetch$ should trigger fetch$.next', async () => { + jest.useFakeTimers(); + const searchSessionManagerMock = createSearchSessionMock(); + const autoRefreshFetch$ = new Subject(); + + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }); + const refetch$: DataRefetch$ = new Subject(); + const dataMock = createDataMock(new Subject(), new Subject(), new Subject(), autoRefreshFetch$); + const setAutoRefreshDone = jest.fn(); + const fetch$ = getFetch$({ + setAutoRefreshDone, + main$, + refetch$, + data: dataMock, + searchSessionManager: searchSessionManagerMock.searchSessionManager, + searchSource: savedSearchMockWithTimeField.searchSource, + }); + + const fetchfnMock = jest.fn(); + fetch$.subscribe(() => { + fetchfnMock(); + }); + autoRefreshFetch$.next(jest.fn()); + jest.runAllTimers(); + expect(fetchfnMock).toHaveBeenCalledTimes(1); + expect(setAutoRefreshDone).toHaveBeenCalled(); + }); +}); From 1ff02e1da684a5bbd3d1179db9567b5dd2fe4a97 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Mon, 4 Oct 2021 10:05:01 -0400 Subject: [PATCH 35/98] [Observability] [Exploratory View] Add exploratory view multi series (#113464) * Revert "[Observability][Exploratory View] revert exploratory view multi-series (#107647)" This reverts commit 1649661ffdc79d00f9d23451790335e5d25da25f. * Revert "[Observability][Exploratory View] revert exploratory view multi-series (#107647)" This reverts commit 1649661ffdc79d00f9d23451790335e5d25da25f. * [Observability] [Exploratory View] Create multi series feature branch (#108079) * Revert "[Observability][Exploratory View] revert exploratory view multi-series (#107647)" This reverts commit 1649661ffdc79d00f9d23451790335e5d25da25f. * Revert "[Observability][Exploratory View] revert exploratory view multi-series (#107647)" This reverts commit 1649661ffdc79d00f9d23451790335e5d25da25f. * update types * update tests * [Observability] exploratory view design issues (#111028) * remove custom y axis labels for better clarity * move add series button to the bottom * disable auto apply * fix missing test * When series count changes, collapse other series. (#110894) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * Feature/observability exploratory view multi series panels (#111555) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * [Exploratory View] Fix date range picker on secondary series (#111700) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * [Exploratory View] Collapse series only on add, not delete (#111790) * [Exploratory view] Remove preview panel (#111884) * [Exploratory view] implement popovers for data type and metric type (#112370) * implement popovers for data type and metric type * adjust types * add IncompleteBadge * make report metric dismissable * show date-picker even if metric is undefined * adjust styles of expanded series row * add truncation to series name * move incomplete badge and add edit pencil * add tooltip to data type badge * adjust content * lint * delete extra file * move filters row * adjust name editing behavior * adjust filter styles Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * move cases button to top * fix types * more types :( Co-authored-by: Justin Kambic Co-authored-by: shahzad31 Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Shahzad --- packages/kbn-test/src/jest/utils/get_url.ts | 9 +- test/functional/page_objects/common_page.ts | 5 +- .../app/RumDashboard/ActionMenu/index.tsx | 22 +- .../PageLoadDistribution/index.tsx | 19 +- .../app/RumDashboard/PageViewsTrend/index.tsx | 19 +- .../analyze_data_button.test.tsx | 8 +- .../analyze_data_button.tsx | 37 +- .../apm/server/lib/rum_client/has_rum_data.ts | 5 +- .../add_data_buttons/mobile_add_data.tsx | 32 ++ .../add_data_buttons/synthetics_add_data.tsx | 32 ++ .../shared/add_data_buttons/ux_add_data.tsx | 32 ++ .../action_menu/action_menu.test.tsx | 61 ++++ .../components/action_menu/action_menu.tsx | 98 ++++++ .../components/action_menu/index.tsx | 26 ++ .../date_range_picker.tsx | 63 ++-- .../components/empty_view.tsx | 17 +- .../components/filter_label.test.tsx | 14 +- .../components/filter_label.tsx | 11 +- .../components/series_color_picker.tsx | 65 ++++ .../series_date_picker/index.tsx | 35 +- .../series_date_picker.test.tsx | 59 ++-- .../configurations/constants/constants.ts | 13 + .../configurations/constants/url_constants.ts | 4 +- .../configurations/default_configs.ts | 17 +- .../configurations/lens_attributes.test.ts | 23 +- .../configurations/lens_attributes.ts | 45 +-- .../mobile/device_distribution_config.ts | 8 +- .../mobile/distribution_config.ts | 4 +- .../mobile/kpi_over_time_config.ts | 10 +- .../rum/core_web_vitals_config.test.ts | 9 +- .../rum/core_web_vitals_config.ts | 4 +- .../rum/data_distribution_config.ts | 9 +- .../rum/kpi_over_time_config.ts | 10 +- .../synthetics/data_distribution_config.ts | 9 +- .../synthetics/kpi_over_time_config.ts | 4 +- .../test_data/sample_attribute.ts | 89 +++-- .../test_data/sample_attribute_cwv.ts | 4 +- .../test_data/sample_attribute_kpi.ts | 75 ++-- .../exploratory_view/configurations/utils.ts | 27 +- .../exploratory_view.test.tsx | 34 +- .../exploratory_view/exploratory_view.tsx | 174 +++++++--- .../header/add_to_case_action.test.tsx | 7 +- .../header/add_to_case_action.tsx | 3 +- .../exploratory_view/header/header.test.tsx | 47 +-- .../shared/exploratory_view/header/header.tsx | 87 ++--- .../last_updated.tsx | 21 +- .../exploratory_view/hooks/use_add_to_case.ts | 2 +- .../hooks/use_app_index_pattern.tsx | 2 +- .../hooks/use_discover_link.tsx | 92 +++++ .../hooks/use_lens_attributes.ts | 57 ++- .../hooks/use_series_filters.ts | 43 ++- .../hooks/use_series_storage.test.tsx | 91 ++--- .../hooks/use_series_storage.tsx | 123 ++++--- .../shared/exploratory_view/index.tsx | 4 +- .../exploratory_view/lens_embeddable.tsx | 77 +++- .../shared/exploratory_view/rtl_helpers.tsx | 61 ++-- .../columns/data_types_col.test.tsx | 62 ---- .../series_builder/columns/data_types_col.tsx | 74 ---- .../columns/date_picker_col.tsx | 39 --- .../columns/report_breakdowns.test.tsx | 74 ---- .../columns/report_breakdowns.tsx | 26 -- .../columns/report_definition_col.tsx | 101 ------ .../columns/report_filters.test.tsx | 28 -- .../series_builder/columns/report_filters.tsx | 29 -- .../columns/report_types_col.test.tsx | 79 ----- .../columns/report_types_col.tsx | 108 ------ .../series_builder/report_metric_options.tsx | 46 --- .../series_builder/series_builder.tsx | 303 ---------------- .../series_editor/chart_edit_options.tsx | 30 -- .../series_editor/columns/breakdowns.test.tsx | 22 +- .../series_editor/columns/breakdowns.tsx | 49 +-- .../series_editor/columns/chart_options.tsx | 35 -- .../columns/chart_type_select.tsx | 73 ++++ .../columns/chart_types.test.tsx | 6 +- .../columns/chart_types.tsx | 52 ++- .../columns/data_type_select.test.tsx | 45 +++ .../columns/data_type_select.tsx | 144 ++++++++ .../series_editor/columns/date_picker_col.tsx | 78 ++++- .../columns/filter_expanded.test.tsx | 48 +-- .../series_editor/columns/filter_expanded.tsx | 139 ++++---- .../columns/filter_value_btn.test.tsx | 145 ++++---- .../columns/filter_value_btn.tsx | 16 +- .../columns/incomplete_badge.tsx | 63 ++++ .../columns/operation_type_select.test.tsx | 36 +- .../columns/operation_type_select.tsx | 13 +- .../series_editor/columns/remove_series.tsx | 41 ++- .../columns/report_definition_col.test.tsx | 46 +-- .../columns/report_definition_col.tsx | 59 ++++ .../columns/report_definition_field.tsx | 50 ++- .../columns/report_type_select.tsx | 63 ++++ .../{ => columns}/selected_filters.test.tsx | 22 +- .../columns/selected_filters.tsx | 101 ++++++ .../series_editor/columns/series_actions.tsx | 139 ++++---- .../series_editor/columns/series_filter.tsx | 145 ++------ .../series_editor/columns/series_info.tsx | 37 ++ .../columns/series_name.test.tsx | 47 +++ .../series_editor/columns/series_name.tsx | 105 ++++++ .../series_editor/expanded_series_row.tsx | 95 +++++ .../series_editor/report_metric_options.tsx | 139 ++++++++ .../series_editor/selected_filters.tsx | 101 ------ .../exploratory_view/series_editor/series.tsx | 93 +++++ .../series_editor/series_editor.tsx | 328 +++++++++++------- .../shared/exploratory_view/types.ts | 17 +- .../views/add_series_button.test.tsx | 106 ++++++ .../views/add_series_button.tsx | 80 +++++ .../exploratory_view/views/series_views.tsx | 26 ++ .../exploratory_view/views/view_actions.tsx | 30 ++ .../field_value_combobox.tsx | 61 ++-- .../field_value_selection.tsx | 4 +- .../field_value_suggestions/index.test.tsx | 2 + .../shared/field_value_suggestions/index.tsx | 8 +- .../shared/field_value_suggestions/types.ts | 3 +- .../filter_value_label/filter_value_label.tsx | 18 +- .../public/components/shared/index.tsx | 3 +- .../public/hooks/use_quick_time_ranges.tsx | 2 +- x-pack/plugins/observability/public/plugin.ts | 2 + .../observability/public/routes/index.tsx | 16 +- .../translations/translations/ja-JP.json | 20 -- .../translations/translations/zh-CN.json | 20 -- .../common/charts/ping_histogram.tsx | 25 +- .../common/header/action_menu_content.tsx | 29 +- .../monitor_duration_container.tsx | 21 +- .../apps/observability/exploratory_view.ts | 82 +++++ .../apps/observability/index.ts | 3 +- 124 files changed, 3602 insertions(+), 2508 deletions(-) create mode 100644 x-pack/plugins/observability/public/components/shared/add_data_buttons/mobile_add_data.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/add_data_buttons/synthetics_add_data.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/add_data_buttons/ux_add_data.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.test.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/index.tsx rename x-pack/plugins/observability/public/components/shared/exploratory_view/{series_date_picker => components}/date_range_picker.tsx (58%) create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_color_picker.tsx rename x-pack/plugins/observability/public/components/shared/exploratory_view/{ => components}/series_date_picker/index.tsx (54%) rename x-pack/plugins/observability/public/components/shared/exploratory_view/{ => components}/series_date_picker/series_date_picker.test.tsx (51%) rename x-pack/plugins/observability/public/components/shared/exploratory_view/{series_builder => header}/last_updated.tsx (55%) create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/data_types_col.test.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/data_types_col.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/date_picker_col.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_breakdowns.test.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_breakdowns.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_col.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_filters.test.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_filters.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_types_col.test.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_types_col.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/report_metric_options.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/series_builder.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/chart_edit_options.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_options.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_type_select.tsx rename x-pack/plugins/observability/public/components/shared/exploratory_view/{series_builder => series_editor}/columns/chart_types.test.tsx (85%) rename x-pack/plugins/observability/public/components/shared/exploratory_view/{series_builder => series_editor}/columns/chart_types.tsx (77%) create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.test.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx rename x-pack/plugins/observability/public/components/shared/exploratory_view/{series_builder => series_editor}/columns/operation_type_select.test.tsx (69%) rename x-pack/plugins/observability/public/components/shared/exploratory_view/{series_builder => series_editor}/columns/operation_type_select.tsx (91%) rename x-pack/plugins/observability/public/components/shared/exploratory_view/{series_builder => series_editor}/columns/report_definition_col.test.tsx (65%) create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.tsx rename x-pack/plugins/observability/public/components/shared/exploratory_view/{series_builder => series_editor}/columns/report_definition_field.tsx (69%) create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_type_select.tsx rename x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/{ => columns}/selected_filters.test.tsx (59%) create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_info.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.test.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx delete mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/selected_filters.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.test.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/views/series_views.tsx create mode 100644 x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.tsx create mode 100644 x-pack/test/observability_functional/apps/observability/exploratory_view.ts diff --git a/packages/kbn-test/src/jest/utils/get_url.ts b/packages/kbn-test/src/jest/utils/get_url.ts index 734e26c5199d7..e08695b334e1b 100644 --- a/packages/kbn-test/src/jest/utils/get_url.ts +++ b/packages/kbn-test/src/jest/utils/get_url.ts @@ -22,11 +22,6 @@ interface UrlParam { username?: string; } -interface App { - pathname?: string; - hash?: string; -} - /** * Converts a config and a pathname to a url * @param {object} config A url config @@ -46,11 +41,11 @@ interface App { * @return {string} */ -function getUrl(config: UrlParam, app: App) { +function getUrl(config: UrlParam, app: UrlParam) { return url.format(_.assign({}, config, app)); } -getUrl.noAuth = function getUrlNoAuth(config: UrlParam, app: App) { +getUrl.noAuth = function getUrlNoAuth(config: UrlParam, app: UrlParam) { config = _.pickBy(config, function (val, param) { return param !== 'auth'; }); diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts index 853a926f4f6e8..8fe2e4139e6ca 100644 --- a/test/functional/page_objects/common_page.ts +++ b/test/functional/page_objects/common_page.ts @@ -217,8 +217,9 @@ export class CommonPageObject extends FtrService { { basePath = '', shouldLoginIfPrompted = true, - disableWelcomePrompt = true, hash = '', + search = '', + disableWelcomePrompt = true, insertTimestamp = true, } = {} ) { @@ -229,11 +230,13 @@ export class CommonPageObject extends FtrService { appUrl = getUrl.noAuth(this.config.get('servers.kibana'), { pathname: `${basePath}${appConfig.pathname}`, hash: hash || appConfig.hash, + search, }); } else { appUrl = getUrl.noAuth(this.config.get('servers.kibana'), { pathname: `${basePath}/app/${appName}`, hash, + search, }); } diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ActionMenu/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ActionMenu/index.tsx index 170e3a2fdad1e..593de7c3a6f70 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ActionMenu/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ActionMenu/index.tsx @@ -11,12 +11,12 @@ import { i18n } from '@kbn/i18n'; import { createExploratoryViewUrl, HeaderMenuPortal, - SeriesUrl, } from '../../../../../../observability/public'; import { useUrlParams } from '../../../../context/url_params_context/use_url_params'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { AppMountParameters } from '../../../../../../../../src/core/public'; import { InspectorHeaderLink } from '../../../shared/apm_header_action_menu/inspector_header_link'; +import { SERVICE_NAME } from '../../../../../common/elasticsearch_fieldnames'; const ANALYZE_DATA = i18n.translate('xpack.apm.analyzeDataButtonLabel', { defaultMessage: 'Analyze data', @@ -39,15 +39,22 @@ export function UXActionMenu({ services: { http }, } = useKibana(); const { urlParams } = useUrlParams(); - const { rangeTo, rangeFrom } = urlParams; + const { rangeTo, rangeFrom, serviceName } = urlParams; const uxExploratoryViewLink = createExploratoryViewUrl( { - 'ux-series': { - dataType: 'ux', - isNew: true, - time: { from: rangeFrom, to: rangeTo }, - } as unknown as SeriesUrl, + reportType: 'kpi-over-time', + allSeries: [ + { + dataType: 'ux', + name: `${serviceName}-page-views`, + time: { from: rangeFrom!, to: rangeTo! }, + reportDefinitions: { + [SERVICE_NAME]: serviceName ? [serviceName] : [], + }, + selectedMetricField: 'Records', + }, + ], }, http?.basePath.get() ); @@ -61,6 +68,7 @@ export function UXActionMenu({ {ANALYZE_MESSAGE}

    }> { render(); expect((screen.getByRole('link') as HTMLAnchorElement).href).toEqual( - 'http://localhost/app/observability/exploratory-view#?sr=(apm-series:(dt:ux,isNew:!t,op:average,rdf:(service.environment:!(testEnvironment),service.name:!(testServiceName)),rt:kpi-over-time,time:(from:now-15m,to:now)))' + 'http://localhost/app/observability/exploratory-view/#?reportType=kpi-over-time&sr=!((dt:ux,mt:transaction.duration.us,n:testServiceName-response-latency,op:average,rdf:(service.environment:!(testEnvironment),service.name:!(testServiceName)),time:(from:now-15m,to:now)))' ); }); }); @@ -48,7 +48,7 @@ describe('AnalyzeDataButton', () => { render(); expect((screen.getByRole('link') as HTMLAnchorElement).href).toEqual( - 'http://localhost/app/observability/exploratory-view#?sr=(apm-series:(dt:mobile,isNew:!t,op:average,rdf:(service.environment:!(testEnvironment),service.name:!(testServiceName)),rt:kpi-over-time,time:(from:now-15m,to:now)))' + 'http://localhost/app/observability/exploratory-view/#?reportType=kpi-over-time&sr=!((dt:mobile,mt:transaction.duration.us,n:testServiceName-response-latency,op:average,rdf:(service.environment:!(testEnvironment),service.name:!(testServiceName)),time:(from:now-15m,to:now)))' ); }); }); @@ -58,7 +58,7 @@ describe('AnalyzeDataButton', () => { render(); expect((screen.getByRole('link') as HTMLAnchorElement).href).toEqual( - 'http://localhost/app/observability/exploratory-view#?sr=(apm-series:(dt:mobile,isNew:!t,op:average,rdf:(service.name:!(testServiceName)),rt:kpi-over-time,time:(from:now-15m,to:now)))' + 'http://localhost/app/observability/exploratory-view/#?reportType=kpi-over-time&sr=!((dt:mobile,mt:transaction.duration.us,n:testServiceName-response-latency,op:average,rdf:(service.environment:!(ENVIRONMENT_NOT_DEFINED),service.name:!(testServiceName)),time:(from:now-15m,to:now)))' ); }); }); @@ -68,7 +68,7 @@ describe('AnalyzeDataButton', () => { render(); expect((screen.getByRole('link') as HTMLAnchorElement).href).toEqual( - 'http://localhost/app/observability/exploratory-view#?sr=(apm-series:(dt:mobile,isNew:!t,op:average,rdf:(service.environment:!(ALL_VALUES),service.name:!(testServiceName)),rt:kpi-over-time,time:(from:now-15m,to:now)))' + 'http://localhost/app/observability/exploratory-view/#?reportType=kpi-over-time&sr=!((dt:mobile,mt:transaction.duration.us,n:testServiceName-response-latency,op:average,rdf:(service.environment:!(ALL_VALUES),service.name:!(testServiceName)),time:(from:now-15m,to:now)))' ); }); }); diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/analyze_data_button.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/analyze_data_button.tsx index 068d7bb1c242f..a4fc964a444c9 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/analyze_data_button.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/analyze_data_button.tsx @@ -9,10 +9,7 @@ import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; -import { - createExploratoryViewUrl, - SeriesUrl, -} from '../../../../../../observability/public'; +import { createExploratoryViewUrl } from '../../../../../../observability/public'; import { ALL_VALUES_SELECTED } from '../../../../../../observability/public'; import { isIosAgentName, @@ -21,6 +18,7 @@ import { import { SERVICE_ENVIRONMENT, SERVICE_NAME, + TRANSACTION_DURATION, } from '../../../../../common/elasticsearch_fieldnames'; import { ENVIRONMENT_ALL, @@ -29,13 +27,11 @@ import { import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; import { useApmParams } from '../../../../hooks/use_apm_params'; -function getEnvironmentDefinition(environment?: string) { +function getEnvironmentDefinition(environment: string) { switch (environment) { case ENVIRONMENT_ALL.value: return { [SERVICE_ENVIRONMENT]: [ALL_VALUES_SELECTED] }; case ENVIRONMENT_NOT_DEFINED.value: - case undefined: - return {}; default: return { [SERVICE_ENVIRONMENT]: [environment] }; } @@ -54,21 +50,26 @@ export function AnalyzeDataButton() { if ( (isRumAgentName(agentName) || isIosAgentName(agentName)) && - canShowDashboard + rangeFrom && + canShowDashboard && + rangeTo ) { const href = createExploratoryViewUrl( { - 'apm-series': { - dataType: isRumAgentName(agentName) ? 'ux' : 'mobile', - time: { from: rangeFrom, to: rangeTo }, - reportType: 'kpi-over-time', - reportDefinitions: { - [SERVICE_NAME]: [serviceName], - ...getEnvironmentDefinition(environment), + reportType: 'kpi-over-time', + allSeries: [ + { + name: `${serviceName}-response-latency`, + selectedMetricField: TRANSACTION_DURATION, + dataType: isRumAgentName(agentName) ? 'ux' : 'mobile', + time: { from: rangeFrom, to: rangeTo }, + reportDefinitions: { + [SERVICE_NAME]: [serviceName], + ...(environment ? getEnvironmentDefinition(environment) : {}), + }, + operationType: 'average', }, - operationType: 'average', - isNew: true, - } as SeriesUrl, + ], }, basepath ); diff --git a/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts b/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts index ebb5c7655806a..9409e94fa9ba9 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts @@ -5,6 +5,7 @@ * 2.0. */ +import moment from 'moment'; import { SetupUX } from '../../routes/rum_client'; import { SERVICE_NAME, @@ -16,8 +17,8 @@ import { TRANSACTION_PAGE_LOAD } from '../../../common/transaction_types'; export async function hasRumData({ setup, - start, - end, + start = moment().subtract(24, 'h').valueOf(), + end = moment().valueOf(), }: { setup: SetupUX; start?: number; diff --git a/x-pack/plugins/observability/public/components/shared/add_data_buttons/mobile_add_data.tsx b/x-pack/plugins/observability/public/components/shared/add_data_buttons/mobile_add_data.tsx new file mode 100644 index 0000000000000..0e17c6277618b --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/add_data_buttons/mobile_add_data.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiHeaderLink } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { useKibana } from '../../../utils/kibana_react'; + +export function MobileAddData() { + const kibana = useKibana(); + + return ( + + {ADD_DATA_LABEL} + + ); +} + +const ADD_DATA_LABEL = i18n.translate('xpack.observability.mobile.addDataButtonLabel', { + defaultMessage: 'Add Mobile data', +}); diff --git a/x-pack/plugins/observability/public/components/shared/add_data_buttons/synthetics_add_data.tsx b/x-pack/plugins/observability/public/components/shared/add_data_buttons/synthetics_add_data.tsx new file mode 100644 index 0000000000000..af91624769e6b --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/add_data_buttons/synthetics_add_data.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiHeaderLink } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { useKibana } from '../../../utils/kibana_react'; + +export function SyntheticsAddData() { + const kibana = useKibana(); + + return ( + + {ADD_DATA_LABEL} + + ); +} + +const ADD_DATA_LABEL = i18n.translate('xpack.observability..synthetics.addDataButtonLabel', { + defaultMessage: 'Add synthetics data', +}); diff --git a/x-pack/plugins/observability/public/components/shared/add_data_buttons/ux_add_data.tsx b/x-pack/plugins/observability/public/components/shared/add_data_buttons/ux_add_data.tsx new file mode 100644 index 0000000000000..c6aa0742466f1 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/add_data_buttons/ux_add_data.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiHeaderLink } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { useKibana } from '../../../utils/kibana_react'; + +export function UXAddData() { + const kibana = useKibana(); + + return ( + + {ADD_DATA_LABEL} + + ); +} + +const ADD_DATA_LABEL = i18n.translate('xpack.observability.ux.addDataButtonLabel', { + defaultMessage: 'Add UX data', +}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.test.tsx new file mode 100644 index 0000000000000..2b59628c3e8d3 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.test.tsx @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render } from '../../rtl_helpers'; +import { fireEvent, screen } from '@testing-library/dom'; +import React from 'react'; +import { sampleAttribute } from '../../configurations/test_data/sample_attribute'; +import * as pluginHook from '../../../../../hooks/use_plugin_context'; +import { TypedLensByValueInput } from '../../../../../../../lens/public'; +import { ExpViewActionMenuContent } from './action_menu'; + +jest.spyOn(pluginHook, 'usePluginContext').mockReturnValue({ + appMountParameters: { + setHeaderActionMenu: jest.fn(), + }, +} as any); + +describe('Action Menu', function () { + it('should be able to click open in lens', async function () { + const { findByText, core } = render( + + ); + + expect(await screen.findByText('Open in Lens')).toBeInTheDocument(); + + fireEvent.click(await findByText('Open in Lens')); + + expect(core.lens?.navigateToPrefilledEditor).toHaveBeenCalledTimes(1); + expect(core.lens?.navigateToPrefilledEditor).toHaveBeenCalledWith( + { + id: '', + attributes: sampleAttribute, + timeRange: { to: 'now', from: 'now-10m' }, + }, + { + openInNewTab: true, + } + ); + }); + + it('should be able to click save', async function () { + const { findByText } = render( + + ); + + expect(await screen.findByText('Save')).toBeInTheDocument(); + + fireEvent.click(await findByText('Save')); + + expect(await screen.findByText('Lens Save Modal Component')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.tsx new file mode 100644 index 0000000000000..08b4a3b948c57 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.tsx @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { LensEmbeddableInput, TypedLensByValueInput } from '../../../../../../../lens/public'; +import { ObservabilityAppServices } from '../../../../../application/types'; +import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public'; +import { AddToCaseAction } from '../../header/add_to_case_action'; + +export function ExpViewActionMenuContent({ + timeRange, + lensAttributes, +}: { + timeRange?: { from: string; to: string }; + lensAttributes: TypedLensByValueInput['attributes'] | null; +}) { + const kServices = useKibana().services; + + const { lens } = kServices; + + const [isSaveOpen, setIsSaveOpen] = useState(false); + + const LensSaveModalComponent = lens.SaveModalComponent; + + return ( + <> + + + + + + { + if (lensAttributes) { + lens.navigateToPrefilledEditor( + { + id: '', + timeRange, + attributes: lensAttributes, + }, + { + openInNewTab: true, + } + ); + } + }} + > + {i18n.translate('xpack.observability.expView.heading.openInLens', { + defaultMessage: 'Open in Lens', + })} + + + + { + if (lensAttributes) { + setIsSaveOpen(true); + } + }} + size="s" + > + {i18n.translate('xpack.observability.expView.heading.saveLensVisualization', { + defaultMessage: 'Save', + })} + + + + + {isSaveOpen && lensAttributes && ( + setIsSaveOpen(false)} + // if we want to do anything after the viz is saved + // right now there is no action, so an empty function + onSave={() => {}} + /> + )} + + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/index.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/index.tsx new file mode 100644 index 0000000000000..23500b63e900a --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/index.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { ExpViewActionMenuContent } from './action_menu'; +import HeaderMenuPortal from '../../../header_menu_portal'; +import { usePluginContext } from '../../../../../hooks/use_plugin_context'; +import { TypedLensByValueInput } from '../../../../../../../lens/public'; + +interface Props { + timeRange?: { from: string; to: string }; + lensAttributes: TypedLensByValueInput['attributes'] | null; +} +export function ExpViewActionMenu(props: Props) { + const { appMountParameters } = usePluginContext(); + + return ( + + + + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_date_picker/date_range_picker.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/date_range_picker.tsx similarity index 58% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_date_picker/date_range_picker.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/components/date_range_picker.tsx index c30863585b3b0..aabde404aa7b4 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_date_picker/date_range_picker.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/date_range_picker.tsx @@ -6,48 +6,48 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiDatePicker, EuiDatePickerRange } from '@elastic/eui'; -import DateMath from '@elastic/datemath'; import { Moment } from 'moment'; +import DateMath from '@elastic/datemath'; +import { i18n } from '@kbn/i18n'; import { useSeriesStorage } from '../hooks/use_series_storage'; import { useUiSetting } from '../../../../../../../../src/plugins/kibana_react/public'; +import { SeriesUrl } from '../types'; +import { ReportTypes } from '../configurations/constants'; export const parseAbsoluteDate = (date: string, options = {}) => { return DateMath.parse(date, options)!; }; -export function DateRangePicker({ seriesId }: { seriesId: string }) { - const { firstSeriesId, getSeries, setSeries } = useSeriesStorage(); +export function DateRangePicker({ seriesId, series }: { seriesId: number; series: SeriesUrl }) { + const { firstSeries, setSeries, reportType } = useSeriesStorage(); const dateFormat = useUiSetting('dateFormat'); - const { - time: { from, to }, - reportType, - } = getSeries(firstSeriesId); + const seriesFrom = series.time?.from; + const seriesTo = series.time?.to; - const series = getSeries(seriesId); + const { from: mainFrom, to: mainTo } = firstSeries!.time; - const { - time: { from: seriesFrom, to: seriesTo }, - } = series; + const startDate = parseAbsoluteDate(seriesFrom ?? mainFrom)!; + const endDate = parseAbsoluteDate(seriesTo ?? mainTo, { roundUp: true })!; - const startDate = parseAbsoluteDate(seriesFrom ?? from)!; - const endDate = parseAbsoluteDate(seriesTo ?? to, { roundUp: true })!; + const getTotalDuration = () => { + const mainStartDate = parseAbsoluteDate(mainFrom)!; + const mainEndDate = parseAbsoluteDate(mainTo, { roundUp: true })!; + return mainEndDate.diff(mainStartDate, 'millisecond'); + }; - const onStartChange = (newDate: Moment) => { - if (reportType === 'kpi-over-time') { - const mainStartDate = parseAbsoluteDate(from)!; - const mainEndDate = parseAbsoluteDate(to, { roundUp: true })!; - const totalDuration = mainEndDate.diff(mainStartDate, 'millisecond'); - const newFrom = newDate.toISOString(); - const newTo = newDate.add(totalDuration, 'millisecond').toISOString(); + const onStartChange = (newStartDate: Moment) => { + if (reportType === ReportTypes.KPI) { + const totalDuration = getTotalDuration(); + const newFrom = newStartDate.toISOString(); + const newTo = newStartDate.add(totalDuration, 'millisecond').toISOString(); setSeries(seriesId, { ...series, time: { from: newFrom, to: newTo }, }); } else { - const newFrom = newDate.toISOString(); + const newFrom = newStartDate.toISOString(); setSeries(seriesId, { ...series, @@ -55,20 +55,19 @@ export function DateRangePicker({ seriesId }: { seriesId: string }) { }); } }; - const onEndChange = (newDate: Moment) => { - if (reportType === 'kpi-over-time') { - const mainStartDate = parseAbsoluteDate(from)!; - const mainEndDate = parseAbsoluteDate(to, { roundUp: true })!; - const totalDuration = mainEndDate.diff(mainStartDate, 'millisecond'); - const newTo = newDate.toISOString(); - const newFrom = newDate.subtract(totalDuration, 'millisecond').toISOString(); + + const onEndChange = (newEndDate: Moment) => { + if (reportType === ReportTypes.KPI) { + const totalDuration = getTotalDuration(); + const newTo = newEndDate.toISOString(); + const newFrom = newEndDate.subtract(totalDuration, 'millisecond').toISOString(); setSeries(seriesId, { ...series, time: { from: newFrom, to: newTo }, }); } else { - const newTo = newDate.toISOString(); + const newTo = newEndDate.toISOString(); setSeries(seriesId, { ...series, @@ -90,7 +89,7 @@ export function DateRangePicker({ seriesId }: { seriesId: string }) { aria-label={i18n.translate('xpack.observability.expView.dateRanger.startDate', { defaultMessage: 'Start date', })} - dateFormat={dateFormat} + dateFormat={dateFormat.replace('ss.SSS', 'ss')} showTimeSelect /> } @@ -104,7 +103,7 @@ export function DateRangePicker({ seriesId }: { seriesId: string }) { aria-label={i18n.translate('xpack.observability.expView.dateRanger.endDate', { defaultMessage: 'End date', })} - dateFormat={dateFormat} + dateFormat={dateFormat.replace('ss.SSS', 'ss')} showTimeSelect /> } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/empty_view.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/empty_view.tsx index 3566835b1701c..d17e451ef702c 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/empty_view.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/empty_view.tsx @@ -10,19 +10,19 @@ import { isEmpty } from 'lodash'; import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiSpacer, EuiText } from '@elastic/eui'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; -import { LOADING_VIEW } from '../series_builder/series_builder'; -import { SeriesUrl } from '../types'; +import { LOADING_VIEW } from '../series_editor/series_editor'; +import { ReportViewType, SeriesUrl } from '../types'; export function EmptyView({ loading, - height, series, + reportType, }: { loading: boolean; - height: string; - series: SeriesUrl; + series?: SeriesUrl; + reportType: ReportViewType; }) { - const { dataType, reportType, reportDefinitions } = series ?? {}; + const { dataType, reportDefinitions } = series ?? {}; let emptyMessage = EMPTY_LABEL; @@ -45,7 +45,7 @@ export function EmptyView({ } return ( - + {loading && ( ` +const Wrapper = styled.div` text-align: center; - height: ${(props) => props.height}; position: relative; `; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.test.tsx index fe2953edd36d6..03fd23631f755 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { mockAppIndexPattern, mockIndexPattern, render } from '../rtl_helpers'; +import { mockAppIndexPattern, mockIndexPattern, mockUxSeries, render } from '../rtl_helpers'; import { FilterLabel } from './filter_label'; import * as useSeriesHook from '../hooks/use_series_filters'; import { buildFilterLabel } from '../../filter_value_label/filter_value_label'; @@ -27,9 +27,10 @@ describe('FilterLabel', function () { value={'elastic-co'} label={'Web Application'} negate={false} - seriesId={'kpi-over-time'} + seriesId={0} removeFilter={jest.fn()} indexPattern={mockIndexPattern} + series={mockUxSeries} /> ); @@ -51,9 +52,10 @@ describe('FilterLabel', function () { value={'elastic-co'} label={'Web Application'} negate={false} - seriesId={'kpi-over-time'} + seriesId={0} removeFilter={removeFilter} indexPattern={mockIndexPattern} + series={mockUxSeries} /> ); @@ -74,9 +76,10 @@ describe('FilterLabel', function () { value={'elastic-co'} label={'Web Application'} negate={false} - seriesId={'kpi-over-time'} + seriesId={0} removeFilter={removeFilter} indexPattern={mockIndexPattern} + series={mockUxSeries} /> ); @@ -100,9 +103,10 @@ describe('FilterLabel', function () { value={'elastic-co'} label={'Web Application'} negate={true} - seriesId={'kpi-over-time'} + seriesId={0} removeFilter={jest.fn()} indexPattern={mockIndexPattern} + series={mockUxSeries} /> ); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.tsx index a08e777c5ea71..c6254a85de9ac 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.tsx @@ -9,21 +9,24 @@ import React from 'react'; import { IndexPattern } from '../../../../../../../../src/plugins/data/public'; import { useSeriesFilters } from '../hooks/use_series_filters'; import { FilterValueLabel } from '../../filter_value_label/filter_value_label'; +import { SeriesUrl } from '../types'; interface Props { field: string; label: string; - value: string; - seriesId: string; + value: string | string[]; + seriesId: number; + series: SeriesUrl; negate: boolean; definitionFilter?: boolean; indexPattern: IndexPattern; - removeFilter: (field: string, value: string, notVal: boolean) => void; + removeFilter: (field: string, value: string | string[], notVal: boolean) => void; } export function FilterLabel({ label, seriesId, + series, field, value, negate, @@ -31,7 +34,7 @@ export function FilterLabel({ removeFilter, definitionFilter, }: Props) { - const { invertFilter } = useSeriesFilters({ seriesId }); + const { invertFilter } = useSeriesFilters({ seriesId, series }); return indexPattern ? ( { + setSeries(seriesId, { ...series, color: colorN }); + }; + + const color = + series.color ?? (theme.eui as unknown as Record)[`euiColorVis${seriesId}`]; + + const button = ( + + setIsOpen((prevState) => !prevState)} flush="both"> + + + + ); + + return ( + setIsOpen(false)}> + + + + + ); +} + +const PICK_A_COLOR_LABEL = i18n.translate( + 'xpack.observability.overview.exploratoryView.pickColor', + { + defaultMessage: 'Pick a color', + } +); + +const EDIT_SERIES_COLOR_LABEL = i18n.translate( + 'xpack.observability.overview.exploratoryView.editSeriesColor', + { + defaultMessage: 'Edit color for series', + } +); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_date_picker/index.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/index.tsx similarity index 54% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_date_picker/index.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/index.tsx index e21da424b58c8..e02f11dfc4954 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_date_picker/index.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/index.tsx @@ -6,11 +6,13 @@ */ import { EuiSuperDatePicker } from '@elastic/eui'; -import React, { useEffect } from 'react'; -import { useHasData } from '../../../../hooks/use_has_data'; -import { useSeriesStorage } from '../hooks/use_series_storage'; -import { useQuickTimeRanges } from '../../../../hooks/use_quick_time_ranges'; -import { DEFAULT_TIME } from '../configurations/constants'; +import React from 'react'; + +import { useHasData } from '../../../../../hooks/use_has_data'; +import { useSeriesStorage } from '../../hooks/use_series_storage'; +import { useQuickTimeRanges } from '../../../../../hooks/use_quick_time_ranges'; +import { SeriesUrl } from '../../types'; +import { ReportTypes } from '../../configurations/constants'; export interface TimePickerTime { from: string; @@ -22,28 +24,27 @@ export interface TimePickerQuickRange extends TimePickerTime { } interface Props { - seriesId: string; + seriesId: number; + series: SeriesUrl; } -export function SeriesDatePicker({ seriesId }: Props) { +export function SeriesDatePicker({ series, seriesId }: Props) { const { onRefreshTimeRange } = useHasData(); const commonlyUsedRanges = useQuickTimeRanges(); - const { getSeries, setSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); + const { setSeries, reportType, allSeries } = useSeriesStorage(); function onTimeChange({ start, end }: { start: string; end: string }) { onRefreshTimeRange(); - setSeries(seriesId, { ...series, time: { from: start, to: end } }); - } - - useEffect(() => { - if (!series || !series.time) { - setSeries(seriesId, { ...series, time: DEFAULT_TIME }); + if (reportType === ReportTypes.KPI) { + allSeries.forEach((currSeries, seriesIndex) => { + setSeries(seriesIndex, { ...currSeries, time: { from: start, to: end } }); + }); + } else { + setSeries(seriesId, { ...series, time: { from: start, to: end } }); } - }, [series, seriesId, setSeries]); + } return ( , { initSeries }); + const { getByText } = render(, { + initSeries, + }); getByText('Last 30 minutes'); }); - it('should set defaults', async function () { - const initSeries = { - data: { - 'uptime-pings-histogram': { - reportType: 'kpi-over-time' as const, - dataType: 'synthetics' as const, - breakdown: 'monitor.status', - }, - }, - }; - const { setSeries: setSeries1 } = render( - , - { initSeries: initSeries as any } - ); - expect(setSeries1).toHaveBeenCalledTimes(1); - expect(setSeries1).toHaveBeenCalledWith('uptime-pings-histogram', { - breakdown: 'monitor.status', - dataType: 'synthetics' as const, - reportType: 'kpi-over-time' as const, - time: DEFAULT_TIME, - }); - }); - it('should set series data', async function () { const initSeries = { - data: { - 'uptime-pings-histogram': { + data: [ + { + name: 'uptime-pings-histogram', dataType: 'synthetics' as const, - reportType: 'kpi-over-time' as const, breakdown: 'monitor.status', time: { from: 'now-30m', to: 'now' }, }, - }, + ], }; const { onRefreshTimeRange } = mockUseHasData(); - const { getByTestId, setSeries } = render(, { - initSeries, - }); + const { getByTestId, setSeries } = render( + , + { + initSeries, + } + ); await waitFor(function () { fireEvent.click(getByTestId('superDatePickerToggleQuickMenuButton')); @@ -76,10 +57,10 @@ describe('SeriesDatePicker', function () { expect(onRefreshTimeRange).toHaveBeenCalledTimes(1); - expect(setSeries).toHaveBeenCalledWith('series-id', { + expect(setSeries).toHaveBeenCalledWith(0, { + name: 'uptime-pings-histogram', breakdown: 'monitor.status', dataType: 'synthetics', - reportType: 'kpi-over-time', time: { from: 'now/d', to: 'now/d' }, }); expect(setSeries).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/constants.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/constants.ts index ba1f2214223e3..bf5feb7d5863c 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/constants.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/constants.ts @@ -94,6 +94,19 @@ export const DataViewLabels: Record = { 'device-data-distribution': DEVICE_DISTRIBUTION_LABEL, }; +export enum ReportTypes { + KPI = 'kpi-over-time', + DISTRIBUTION = 'data-distribution', + CORE_WEB_VITAL = 'core-web-vitals', + DEVICE_DISTRIBUTION = 'device-data-distribution', +} + +export enum DataTypes { + SYNTHETICS = 'synthetics', + UX = 'ux', + MOBILE = 'mobile', +} + export const USE_BREAK_DOWN_COLUMN = 'USE_BREAK_DOWN_COLUMN'; export const FILTER_RECORDS = 'FILTER_RECORDS'; export const TERMS_COLUMN = 'TERMS_COLUMN'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/url_constants.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/url_constants.ts index 6f990015fbc62..55ac75b47c056 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/url_constants.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/url_constants.ts @@ -8,10 +8,12 @@ export enum URL_KEYS { DATA_TYPE = 'dt', OPERATION_TYPE = 'op', - REPORT_TYPE = 'rt', SERIES_TYPE = 'st', BREAK_DOWN = 'bd', FILTERS = 'ft', REPORT_DEFINITIONS = 'rdf', SELECTED_METRIC = 'mt', + HIDDEN = 'h', + NAME = 'n', + COLOR = 'c', } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts index 574a9f6a2bc10..3f6551986527c 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts @@ -15,6 +15,7 @@ import { getCoreWebVitalsConfig } from './rum/core_web_vitals_config'; import { getMobileKPIConfig } from './mobile/kpi_over_time_config'; import { getMobileKPIDistributionConfig } from './mobile/distribution_config'; import { getMobileDeviceDistributionConfig } from './mobile/device_distribution_config'; +import { DataTypes, ReportTypes } from './constants'; interface Props { reportType: ReportViewType; @@ -24,24 +25,24 @@ interface Props { export const getDefaultConfigs = ({ reportType, dataType, indexPattern }: Props) => { switch (dataType) { - case 'ux': - if (reportType === 'data-distribution') { + case DataTypes.UX: + if (reportType === ReportTypes.DISTRIBUTION) { return getRumDistributionConfig({ indexPattern }); } - if (reportType === 'core-web-vitals') { + if (reportType === ReportTypes.CORE_WEB_VITAL) { return getCoreWebVitalsConfig({ indexPattern }); } return getKPITrendsLensConfig({ indexPattern }); - case 'synthetics': - if (reportType === 'data-distribution') { + case DataTypes.SYNTHETICS: + if (reportType === ReportTypes.DISTRIBUTION) { return getSyntheticsDistributionConfig({ indexPattern }); } return getSyntheticsKPIConfig({ indexPattern }); - case 'mobile': - if (reportType === 'data-distribution') { + case DataTypes.MOBILE: + if (reportType === ReportTypes.DISTRIBUTION) { return getMobileKPIDistributionConfig({ indexPattern }); } - if (reportType === 'device-data-distribution') { + if (reportType === ReportTypes.DEVICE_DISTRIBUTION) { return getMobileDeviceDistributionConfig({ indexPattern }); } return getMobileKPIConfig({ indexPattern }); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts index 706c58609b7cb..9e7c5254b511f 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts @@ -16,7 +16,7 @@ import { } from './constants/elasticsearch_fieldnames'; import { buildExistsFilter, buildPhrasesFilter } from './utils'; import { sampleAttributeKpi } from './test_data/sample_attribute_kpi'; -import { REPORT_METRIC_FIELD } from './constants'; +import { RECORDS_FIELD, REPORT_METRIC_FIELD, ReportTypes } from './constants'; describe('Lens Attribute', () => { mockAppIndexPattern(); @@ -38,6 +38,9 @@ describe('Lens Attribute', () => { indexPattern: mockIndexPattern, reportDefinitions: {}, time: { from: 'now-15m', to: 'now' }, + color: 'green', + name: 'test-series', + selectedMetricField: TRANSACTION_DURATION, }; beforeEach(() => { @@ -50,7 +53,7 @@ describe('Lens Attribute', () => { it('should return expected json for kpi report type', function () { const seriesConfigKpi = getDefaultConfigs({ - reportType: 'kpi-over-time', + reportType: ReportTypes.KPI, dataType: 'ux', indexPattern: mockIndexPattern, }); @@ -63,6 +66,9 @@ describe('Lens Attribute', () => { indexPattern: mockIndexPattern, reportDefinitions: { 'service.name': ['elastic-co'] }, time: { from: 'now-15m', to: 'now' }, + color: 'green', + name: 'test-series', + selectedMetricField: RECORDS_FIELD, }, ]); @@ -135,6 +141,9 @@ describe('Lens Attribute', () => { indexPattern: mockIndexPattern, reportDefinitions: { 'performance.metric': [LCP_FIELD] }, time: { from: 'now-15m', to: 'now' }, + color: 'green', + name: 'test-series', + selectedMetricField: TRANSACTION_DURATION, }; lnsAttr = new LensAttributes([layerConfig1]); @@ -383,7 +392,7 @@ describe('Lens Attribute', () => { palette: undefined, seriesType: 'line', xAccessor: 'x-axis-column-layer0', - yConfig: [{ forAccessor: 'y-axis-column-layer0' }], + yConfig: [{ color: 'green', forAccessor: 'y-axis-column-layer0' }], }, ], legend: { isVisible: true, position: 'right' }, @@ -403,6 +412,9 @@ describe('Lens Attribute', () => { reportDefinitions: { 'performance.metric': [LCP_FIELD] }, breakdown: USER_AGENT_NAME, time: { from: 'now-15m', to: 'now' }, + color: 'green', + name: 'test-series', + selectedMetricField: TRANSACTION_DURATION, }; lnsAttr = new LensAttributes([layerConfig1]); @@ -423,7 +435,7 @@ describe('Lens Attribute', () => { seriesType: 'line', splitAccessor: 'breakdown-column-layer0', xAccessor: 'x-axis-column-layer0', - yConfig: [{ forAccessor: 'y-axis-column-layer0' }], + yConfig: [{ color: 'green', forAccessor: 'y-axis-column-layer0' }], }, ]); @@ -589,6 +601,9 @@ describe('Lens Attribute', () => { indexPattern: mockIndexPattern, reportDefinitions: { 'performance.metric': [LCP_FIELD] }, time: { from: 'now-15m', to: 'now' }, + color: 'green', + name: 'test-series', + selectedMetricField: TRANSACTION_DURATION, }; const filters = lnsAttr.getLayerFilters(layerConfig1, 2); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts index 2778edc94838e..ec2e6b5066c87 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts @@ -37,10 +37,11 @@ import { REPORT_METRIC_FIELD, RECORDS_FIELD, RECORDS_PERCENTAGE_FIELD, + ReportTypes, } from './constants'; import { ColumnFilter, SeriesConfig, UrlFilter, URLReportDefinition } from '../types'; import { PersistableFilter } from '../../../../../../lens/common'; -import { parseAbsoluteDate } from '../series_date_picker/date_range_picker'; +import { parseAbsoluteDate } from '../components/date_range_picker'; import { getDistributionInPercentageColumn } from './lens_columns/overall_column'; function getLayerReferenceName(layerId: string) { @@ -74,14 +75,6 @@ export const parseCustomFieldName = (seriesConfig: SeriesConfig, selectedMetricF timeScale = currField?.timeScale; columnLabel = currField?.label; } - } else if (metricOptions?.[0].field || metricOptions?.[0].id) { - const firstMetricOption = metricOptions?.[0]; - - selectedMetricField = firstMetricOption.field || firstMetricOption.id; - columnType = firstMetricOption.columnType; - columnFilters = firstMetricOption.columnFilters; - timeScale = firstMetricOption.timeScale; - columnLabel = firstMetricOption.label; } return { fieldName: selectedMetricField!, columnType, columnFilters, timeScale, columnLabel }; @@ -96,7 +89,9 @@ export interface LayerConfig { reportDefinitions: URLReportDefinition; time: { to: string; from: string }; indexPattern: IndexPattern; - selectedMetricField?: string; + selectedMetricField: string; + color: string; + name: string; } export class LensAttributes { @@ -467,14 +462,15 @@ export class LensAttributes { getLayerFilters(layerConfig: LayerConfig, totalLayers: number) { const { filters, - time: { from, to }, + time, seriesConfig: { baseFilters: layerFilters, reportType }, } = layerConfig; let baseFilters = ''; - if (reportType !== 'kpi-over-time' && totalLayers > 1) { + + if (reportType !== ReportTypes.KPI && totalLayers > 1 && time) { // for kpi over time, we don't need to add time range filters // since those are essentially plotted along the x-axis - baseFilters += `@timestamp >= ${from} and @timestamp <= ${to}`; + baseFilters += `@timestamp >= ${time.from} and @timestamp <= ${time.to}`; } layerFilters?.forEach((filter: PersistableFilter | ExistsFilter) => { @@ -530,7 +526,11 @@ export class LensAttributes { } getTimeShift(mainLayerConfig: LayerConfig, layerConfig: LayerConfig, index: number) { - if (index === 0 || mainLayerConfig.seriesConfig.reportType !== 'kpi-over-time') { + if ( + index === 0 || + mainLayerConfig.seriesConfig.reportType !== ReportTypes.KPI || + !layerConfig.time + ) { return null; } @@ -542,11 +542,14 @@ export class LensAttributes { time: { from }, } = layerConfig; - const inDays = parseAbsoluteDate(mainFrom).diff(parseAbsoluteDate(from), 'days'); + const inDays = Math.abs(parseAbsoluteDate(mainFrom).diff(parseAbsoluteDate(from), 'days')); if (inDays > 1) { return inDays + 'd'; } - const inHours = parseAbsoluteDate(mainFrom).diff(parseAbsoluteDate(from), 'hours'); + const inHours = Math.abs(parseAbsoluteDate(mainFrom).diff(parseAbsoluteDate(from), 'hours')); + if (inHours === 0) { + return null; + } return inHours + 'h'; } @@ -564,6 +567,8 @@ export class LensAttributes { const { sourceField } = seriesConfig.xAxisColumn; + const label = timeShift ? `${mainYAxis.label}(${timeShift})` : mainYAxis.label; + layers[layerId] = { columnOrder: [ `x-axis-column-${layerId}`, @@ -577,7 +582,7 @@ export class LensAttributes { [`x-axis-column-${layerId}`]: this.getXAxis(layerConfig, layerId), [`y-axis-column-${layerId}`]: { ...mainYAxis, - label: timeShift ? `${mainYAxis.label}(${timeShift})` : mainYAxis.label, + label, filter: { query: columnFilter, language: 'kuery' }, ...(timeShift ? { timeShift } : {}), }, @@ -621,7 +626,7 @@ export class LensAttributes { seriesType: layerConfig.seriesType || layerConfig.seriesConfig.defaultSeriesType, palette: layerConfig.seriesConfig.palette, yConfig: layerConfig.seriesConfig.yConfig || [ - { forAccessor: `y-axis-column-layer${index}` }, + { forAccessor: `y-axis-column-layer${index}`, color: layerConfig.color }, ], xAccessor: `x-axis-column-layer${index}`, ...(layerConfig.breakdown && @@ -635,7 +640,7 @@ export class LensAttributes { }; } - getJSON(): TypedLensByValueInput['attributes'] { + getJSON(refresh?: number): TypedLensByValueInput['attributes'] { const uniqueIndexPatternsIds = Array.from( new Set([...this.layerConfigs.map(({ indexPattern }) => indexPattern.id)]) ); @@ -644,7 +649,7 @@ export class LensAttributes { return { title: 'Prefilled from exploratory view app', - description: '', + description: String(refresh), visualizationType: 'lnsXY', references: [ ...uniqueIndexPatternsIds.map((patternId) => ({ diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/device_distribution_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/device_distribution_config.ts index d1612a08f5551..4e178bba7e02a 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/device_distribution_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/device_distribution_config.ts @@ -6,7 +6,7 @@ */ import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, REPORT_METRIC_FIELD, USE_BREAK_DOWN_COLUMN } from '../constants'; +import { FieldLabels, REPORT_METRIC_FIELD, ReportTypes, USE_BREAK_DOWN_COLUMN } from '../constants'; import { buildPhraseFilter } from '../utils'; import { SERVICE_NAME } from '../constants/elasticsearch_fieldnames'; import { MOBILE_APP, NUMBER_OF_DEVICES } from '../constants/labels'; @@ -14,7 +14,7 @@ import { MobileFields } from './mobile_fields'; export function getMobileDeviceDistributionConfig({ indexPattern }: ConfigProps): SeriesConfig { return { - reportType: 'device-data-distribution', + reportType: ReportTypes.DEVICE_DISTRIBUTION, defaultSeriesType: 'bar', seriesTypes: ['bar', 'bar_horizontal'], xAxisColumn: { @@ -38,13 +38,13 @@ export function getMobileDeviceDistributionConfig({ indexPattern }: ConfigProps) ...MobileFields, [SERVICE_NAME]: MOBILE_APP, }, + definitionFields: [SERVICE_NAME], metricOptions: [ { - id: 'labels.device_id', field: 'labels.device_id', + id: 'labels.device_id', label: NUMBER_OF_DEVICES, }, ], - definitionFields: [SERVICE_NAME], }; } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/distribution_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/distribution_config.ts index 9b1c4c8da3e9b..1da27be4fcc95 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/distribution_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/distribution_config.ts @@ -6,7 +6,7 @@ */ import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, RECORDS_FIELD, REPORT_METRIC_FIELD } from '../constants'; +import { FieldLabels, RECORDS_FIELD, REPORT_METRIC_FIELD, ReportTypes } from '../constants'; import { buildPhrasesFilter } from '../utils'; import { METRIC_SYSTEM_CPU_USAGE, @@ -21,7 +21,7 @@ import { MobileFields } from './mobile_fields'; export function getMobileKPIDistributionConfig({ indexPattern }: ConfigProps): SeriesConfig { return { - reportType: 'data-distribution', + reportType: ReportTypes.DISTRIBUTION, defaultSeriesType: 'bar', seriesTypes: ['line', 'bar'], xAxisColumn: { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/kpi_over_time_config.ts index 945a631078a33..3ee5b3125fcda 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/kpi_over_time_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/kpi_over_time_config.ts @@ -6,7 +6,13 @@ */ import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, OPERATION_COLUMN, RECORDS_FIELD, REPORT_METRIC_FIELD } from '../constants'; +import { + FieldLabels, + OPERATION_COLUMN, + RECORDS_FIELD, + REPORT_METRIC_FIELD, + ReportTypes, +} from '../constants'; import { buildPhrasesFilter } from '../utils'; import { METRIC_SYSTEM_CPU_USAGE, @@ -26,7 +32,7 @@ import { MobileFields } from './mobile_fields'; export function getMobileKPIConfig({ indexPattern }: ConfigProps): SeriesConfig { return { - reportType: 'kpi-over-time', + reportType: ReportTypes.KPI, defaultSeriesType: 'line', seriesTypes: ['line', 'bar', 'area'], xAxisColumn: { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.test.ts index 07bb13f957e45..35e094996f6f2 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.test.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.test.ts @@ -9,7 +9,7 @@ import { mockAppIndexPattern, mockIndexPattern } from '../../rtl_helpers'; import { getDefaultConfigs } from '../default_configs'; import { LayerConfig, LensAttributes } from '../lens_attributes'; import { sampleAttributeCoreWebVital } from '../test_data/sample_attribute_cwv'; -import { SERVICE_NAME, USER_AGENT_OS } from '../constants/elasticsearch_fieldnames'; +import { LCP_FIELD, SERVICE_NAME, USER_AGENT_OS } from '../constants/elasticsearch_fieldnames'; describe('Core web vital config test', function () { mockAppIndexPattern(); @@ -24,10 +24,13 @@ describe('Core web vital config test', function () { const layerConfig: LayerConfig = { seriesConfig, + color: 'green', + name: 'test-series', + breakdown: USER_AGENT_OS, indexPattern: mockIndexPattern, - reportDefinitions: { [SERVICE_NAME]: ['elastic-co'] }, time: { from: 'now-15m', to: 'now' }, - breakdown: USER_AGENT_OS, + reportDefinitions: { [SERVICE_NAME]: ['elastic-co'] }, + selectedMetricField: LCP_FIELD, }; beforeEach(() => { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.ts index 62455df248085..e8d620388a89e 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.ts @@ -11,6 +11,7 @@ import { FieldLabels, FILTER_RECORDS, REPORT_METRIC_FIELD, + ReportTypes, USE_BREAK_DOWN_COLUMN, } from '../constants'; import { buildPhraseFilter } from '../utils'; @@ -38,7 +39,7 @@ export function getCoreWebVitalsConfig({ indexPattern }: ConfigProps): SeriesCon return { defaultSeriesType: 'bar_horizontal_percentage_stacked', - reportType: 'core-web-vitals', + reportType: ReportTypes.CORE_WEB_VITAL, seriesTypes: ['bar_horizontal_percentage_stacked'], xAxisColumn: { sourceField: USE_BREAK_DOWN_COLUMN, @@ -153,5 +154,6 @@ export function getCoreWebVitalsConfig({ indexPattern }: ConfigProps): SeriesCon { color: statusPallete[1], forAccessor: 'y-axis-column-1' }, { color: statusPallete[2], forAccessor: 'y-axis-column-2' }, ], + query: { query: 'transaction.type: "page-load"', language: 'kuery' }, }; } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/data_distribution_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/data_distribution_config.ts index f34c8db6c197d..de6f2c67b2aeb 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/data_distribution_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/data_distribution_config.ts @@ -6,7 +6,12 @@ */ import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, REPORT_METRIC_FIELD, RECORDS_PERCENTAGE_FIELD } from '../constants'; +import { + FieldLabels, + REPORT_METRIC_FIELD, + RECORDS_PERCENTAGE_FIELD, + ReportTypes, +} from '../constants'; import { buildPhraseFilter } from '../utils'; import { CLIENT_GEO_COUNTRY_NAME, @@ -41,7 +46,7 @@ import { export function getRumDistributionConfig({ indexPattern }: ConfigProps): SeriesConfig { return { - reportType: 'data-distribution', + reportType: ReportTypes.DISTRIBUTION, defaultSeriesType: 'line', seriesTypes: [], xAxisColumn: { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_over_time_config.ts index 5899b16d12b4f..9112778eadaa7 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_over_time_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_over_time_config.ts @@ -6,7 +6,13 @@ */ import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, OPERATION_COLUMN, RECORDS_FIELD, REPORT_METRIC_FIELD } from '../constants'; +import { + FieldLabels, + OPERATION_COLUMN, + RECORDS_FIELD, + REPORT_METRIC_FIELD, + ReportTypes, +} from '../constants'; import { buildPhraseFilter } from '../utils'; import { CLIENT_GEO_COUNTRY_NAME, @@ -43,7 +49,7 @@ export function getKPITrendsLensConfig({ indexPattern }: ConfigProps): SeriesCon return { defaultSeriesType: 'bar_stacked', seriesTypes: [], - reportType: 'kpi-over-time', + reportType: ReportTypes.KPI, xAxisColumn: { sourceField: '@timestamp', }, diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/data_distribution_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/data_distribution_config.ts index 730e742f9d8c5..da90f45d15201 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/data_distribution_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/data_distribution_config.ts @@ -6,7 +6,12 @@ */ import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, REPORT_METRIC_FIELD, RECORDS_PERCENTAGE_FIELD } from '../constants'; +import { + FieldLabels, + REPORT_METRIC_FIELD, + RECORDS_PERCENTAGE_FIELD, + ReportTypes, +} from '../constants'; import { CLS_LABEL, DCL_LABEL, @@ -30,7 +35,7 @@ export function getSyntheticsDistributionConfig({ indexPattern, }: ConfigProps): SeriesConfig { return { - reportType: 'data-distribution', + reportType: ReportTypes.DISTRIBUTION, defaultSeriesType: series?.seriesType || 'line', seriesTypes: [], xAxisColumn: { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/kpi_over_time_config.ts index 4ee22181d4334..65b43a83a8fb5 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/kpi_over_time_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/kpi_over_time_config.ts @@ -6,7 +6,7 @@ */ import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, OPERATION_COLUMN, REPORT_METRIC_FIELD } from '../constants'; +import { FieldLabels, OPERATION_COLUMN, REPORT_METRIC_FIELD, ReportTypes } from '../constants'; import { CLS_LABEL, DCL_LABEL, @@ -30,7 +30,7 @@ const SUMMARY_DOWN = 'summary.down'; export function getSyntheticsKPIConfig({ indexPattern }: ConfigProps): SeriesConfig { return { - reportType: 'kpi-over-time', + reportType: ReportTypes.KPI, defaultSeriesType: 'bar_stacked', seriesTypes: [], xAxisColumn: { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts index 596e7af4378ec..7e0ea1e575481 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts @@ -5,12 +5,18 @@ * 2.0. */ export const sampleAttribute = { - title: 'Prefilled from exploratory view app', - description: '', - visualizationType: 'lnsXY', + description: 'undefined', references: [ - { id: 'apm-*', name: 'indexpattern-datasource-current-indexpattern', type: 'index-pattern' }, - { id: 'apm-*', name: 'indexpattern-datasource-layer-layer0', type: 'index-pattern' }, + { + id: 'apm-*', + name: 'indexpattern-datasource-current-indexpattern', + type: 'index-pattern', + }, + { + id: 'apm-*', + name: 'indexpattern-datasource-layer-layer0', + type: 'index-pattern', + }, ], state: { datasourceStates: { @@ -28,17 +34,23 @@ export const sampleAttribute = { ], columns: { 'x-axis-column-layer0': { - sourceField: 'transaction.duration.us', - label: 'Page load time', dataType: 'number', - operationType: 'range', isBucketed: true, - scale: 'interval', + label: 'Page load time', + operationType: 'range', params: { - type: 'histogram', - ranges: [{ from: 0, to: 1000, label: '' }], maxBars: 'auto', + ranges: [ + { + from: 0, + label: '', + to: 1000, + }, + ], + type: 'histogram', }, + scale: 'interval', + sourceField: 'transaction.duration.us', }, 'y-axis-column-layer0': { dataType: 'number', @@ -81,16 +93,16 @@ export const sampleAttribute = { 'y-axis-column-layer0X1': { customLabel: true, dataType: 'number', - isBucketed: false, - label: 'Part of count() / overall_sum(count())', - operationType: 'count', - scale: 'ratio', - sourceField: 'Records', filter: { language: 'kuery', query: 'transaction.type: page-load and processor.event: transaction and transaction.type : *', }, + isBucketed: false, + label: 'Part of count() / overall_sum(count())', + operationType: 'count', + scale: 'ratio', + sourceField: 'Records', }, 'y-axis-column-layer0X2': { customLabel: true, @@ -140,27 +152,52 @@ export const sampleAttribute = { }, }, }, + filters: [], + query: { + language: 'kuery', + query: 'transaction.duration.us < 60000000', + }, visualization: { - legend: { isVisible: true, position: 'right' }, - valueLabels: 'hide', - fittingFunction: 'Linear', + axisTitlesVisibilitySettings: { + x: true, + yLeft: true, + yRight: true, + }, curveType: 'CURVE_MONOTONE_X', - axisTitlesVisibilitySettings: { x: true, yLeft: true, yRight: true }, - tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true }, - gridlinesVisibilitySettings: { x: true, yLeft: true, yRight: true }, - preferredSeriesType: 'line', + fittingFunction: 'Linear', + gridlinesVisibilitySettings: { + x: true, + yLeft: true, + yRight: true, + }, layers: [ { accessors: ['y-axis-column-layer0'], layerId: 'layer0', layerType: 'data', seriesType: 'line', - yConfig: [{ forAccessor: 'y-axis-column-layer0' }], xAccessor: 'x-axis-column-layer0', + yConfig: [ + { + color: 'green', + forAccessor: 'y-axis-column-layer0', + }, + ], }, ], + legend: { + isVisible: true, + position: 'right', + }, + preferredSeriesType: 'line', + tickLabelsVisibilitySettings: { + x: true, + yLeft: true, + yRight: true, + }, + valueLabels: 'hide', }, - query: { query: 'transaction.duration.us < 60000000', language: 'kuery' }, - filters: [], }, + title: 'Prefilled from exploratory view app', + visualizationType: 'lnsXY', }; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts index 56ceba8fc52de..dff3d6b3ad5ef 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts @@ -5,7 +5,7 @@ * 2.0. */ export const sampleAttributeCoreWebVital = { - description: '', + description: 'undefined', references: [ { id: 'apm-*', @@ -94,7 +94,7 @@ export const sampleAttributeCoreWebVital = { filters: [], query: { language: 'kuery', - query: '', + query: 'transaction.type: "page-load"', }, visualization: { axisTitlesVisibilitySettings: { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts index 72933573c410b..6ed9b4face6e3 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts @@ -5,12 +5,18 @@ * 2.0. */ export const sampleAttributeKpi = { - title: 'Prefilled from exploratory view app', - description: '', - visualizationType: 'lnsXY', + description: 'undefined', references: [ - { id: 'apm-*', name: 'indexpattern-datasource-current-indexpattern', type: 'index-pattern' }, - { id: 'apm-*', name: 'indexpattern-datasource-layer-layer0', type: 'index-pattern' }, + { + id: 'apm-*', + name: 'indexpattern-datasource-current-indexpattern', + type: 'index-pattern', + }, + { + id: 'apm-*', + name: 'indexpattern-datasource-layer-layer0', + type: 'index-pattern', + }, ], state: { datasourceStates: { @@ -20,25 +26,27 @@ export const sampleAttributeKpi = { columnOrder: ['x-axis-column-layer0', 'y-axis-column-layer0'], columns: { 'x-axis-column-layer0': { - sourceField: '@timestamp', dataType: 'date', isBucketed: true, label: '@timestamp', operationType: 'date_histogram', - params: { interval: 'auto' }, + params: { + interval: 'auto', + }, scale: 'interval', + sourceField: '@timestamp', }, 'y-axis-column-layer0': { dataType: 'number', + filter: { + language: 'kuery', + query: 'transaction.type: page-load and processor.event: transaction', + }, isBucketed: false, label: 'Page views', operationType: 'count', scale: 'ratio', sourceField: 'Records', - filter: { - query: 'transaction.type: page-load and processor.event: transaction', - language: 'kuery', - }, }, }, incompleteColumns: {}, @@ -46,27 +54,52 @@ export const sampleAttributeKpi = { }, }, }, + filters: [], + query: { + language: 'kuery', + query: '', + }, visualization: { - legend: { isVisible: true, position: 'right' }, - valueLabels: 'hide', - fittingFunction: 'Linear', + axisTitlesVisibilitySettings: { + x: true, + yLeft: true, + yRight: true, + }, curveType: 'CURVE_MONOTONE_X', - axisTitlesVisibilitySettings: { x: true, yLeft: true, yRight: true }, - tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true }, - gridlinesVisibilitySettings: { x: true, yLeft: true, yRight: true }, - preferredSeriesType: 'line', + fittingFunction: 'Linear', + gridlinesVisibilitySettings: { + x: true, + yLeft: true, + yRight: true, + }, layers: [ { accessors: ['y-axis-column-layer0'], layerId: 'layer0', layerType: 'data', seriesType: 'line', - yConfig: [{ forAccessor: 'y-axis-column-layer0' }], xAccessor: 'x-axis-column-layer0', + yConfig: [ + { + color: 'green', + forAccessor: 'y-axis-column-layer0', + }, + ], }, ], + legend: { + isVisible: true, + position: 'right', + }, + preferredSeriesType: 'line', + tickLabelsVisibilitySettings: { + x: true, + yLeft: true, + yRight: true, + }, + valueLabels: 'hide', }, - query: { query: '', language: 'kuery' }, - filters: [], }, + title: 'Prefilled from exploratory view app', + visualizationType: 'lnsXY', }; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts index c7d2d21581e7a..56e6cb5210356 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts @@ -5,7 +5,7 @@ * 2.0. */ import rison, { RisonValue } from 'rison-node'; -import type { SeriesUrl, UrlFilter } from '../types'; +import type { ReportViewType, SeriesUrl, UrlFilter } from '../types'; import type { AllSeries, AllShortSeries } from '../hooks/use_series_storage'; import { IndexPattern } from '../../../../../../../../src/plugins/data/common'; import { esFilters, ExistsFilter } from '../../../../../../../../src/plugins/data/public'; @@ -16,40 +16,43 @@ export function convertToShortUrl(series: SeriesUrl) { const { operationType, seriesType, - reportType, breakdown, filters, reportDefinitions, dataType, selectedMetricField, + hidden, + name, + color, ...restSeries } = series; return { [URL_KEYS.OPERATION_TYPE]: operationType, - [URL_KEYS.REPORT_TYPE]: reportType, [URL_KEYS.SERIES_TYPE]: seriesType, [URL_KEYS.BREAK_DOWN]: breakdown, [URL_KEYS.FILTERS]: filters, [URL_KEYS.REPORT_DEFINITIONS]: reportDefinitions, [URL_KEYS.DATA_TYPE]: dataType, [URL_KEYS.SELECTED_METRIC]: selectedMetricField, + [URL_KEYS.HIDDEN]: hidden, + [URL_KEYS.NAME]: name, + [URL_KEYS.COLOR]: color, ...restSeries, }; } -export function createExploratoryViewUrl(allSeries: AllSeries, baseHref = '') { - const allSeriesIds = Object.keys(allSeries); - - const allShortSeries: AllShortSeries = {}; - - allSeriesIds.forEach((seriesKey) => { - allShortSeries[seriesKey] = convertToShortUrl(allSeries[seriesKey]); - }); +export function createExploratoryViewUrl( + { reportType, allSeries }: { reportType: ReportViewType; allSeries: AllSeries }, + baseHref = '' +) { + const allShortSeries: AllShortSeries = allSeries.map((series) => convertToShortUrl(series)); return ( baseHref + - `/app/observability/exploratory-view#?sr=${rison.encode(allShortSeries as RisonValue)}` + `/app/observability/exploratory-view/#?reportType=${reportType}&sr=${rison.encode( + allShortSeries as unknown as RisonValue + )}` ); } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.test.tsx index a3b5130e9830b..8f061fcbfbf26 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.test.tsx @@ -6,12 +6,18 @@ */ import React from 'react'; -import { screen, waitFor } from '@testing-library/dom'; +import { screen } from '@testing-library/dom'; import { render, mockAppIndexPattern } from './rtl_helpers'; import { ExploratoryView } from './exploratory_view'; import * as obsvInd from './utils/observability_index_patterns'; +import * as pluginHook from '../../../hooks/use_plugin_context'; import { createStubIndexPattern } from '../../../../../../../src/plugins/data/common/stubs'; +jest.spyOn(pluginHook, 'usePluginContext').mockReturnValue({ + appMountParameters: { + setHeaderActionMenu: jest.fn(), + }, +} as any); describe('ExploratoryView', () => { mockAppIndexPattern(); @@ -40,36 +46,22 @@ describe('ExploratoryView', () => { }); it('renders exploratory view', async () => { - render(); + render(, { initSeries: { data: [] } }); - expect(await screen.findByText(/open in lens/i)).toBeInTheDocument(); + expect(await screen.findByText(/No series found. Please add a series./i)).toBeInTheDocument(); + expect(await screen.findByText(/Hide chart/i)).toBeInTheDocument(); + expect(await screen.findByText(/Refresh/i)).toBeInTheDocument(); expect( await screen.findByRole('heading', { name: /Performance Distribution/i }) ).toBeInTheDocument(); }); it('renders lens component when there is series', async () => { - const initSeries = { - data: { - 'ux-series': { - isNew: true, - dataType: 'ux' as const, - reportType: 'data-distribution' as const, - breakdown: 'user_agent .name', - reportDefinitions: { 'service.name': ['elastic-co'] }, - time: { from: 'now-15m', to: 'now' }, - }, - }, - }; - - render(, { initSeries }); + render(); - expect(await screen.findByText(/open in lens/i)).toBeInTheDocument(); expect((await screen.findAllByText('Performance distribution'))[0]).toBeInTheDocument(); expect(await screen.findByText(/Lens Embeddable Component/i)).toBeInTheDocument(); - await waitFor(() => { - screen.getByRole('table', { name: /this table contains 1 rows\./i }); - }); + expect(screen.getByTestId('exploratoryViewSeriesPanel0')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.tsx index af04108c56790..faf064868dec5 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.tsx @@ -4,11 +4,12 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import { i18n } from '@kbn/i18n'; import React, { useEffect, useRef, useState } from 'react'; -import { EuiPanel, EuiTitle } from '@elastic/eui'; +import { EuiButtonEmpty, EuiPanel, EuiResizableContainer, EuiTitle } from '@elastic/eui'; import styled from 'styled-components'; -import { isEmpty } from 'lodash'; +import { PanelDirection } from '@elastic/eui/src/components/resizable_container/types'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { ObservabilityPublicPluginsStart } from '../../../plugin'; import { ExploratoryViewHeader } from './header/header'; @@ -16,40 +17,15 @@ import { useSeriesStorage } from './hooks/use_series_storage'; import { useLensAttributes } from './hooks/use_lens_attributes'; import { TypedLensByValueInput } from '../../../../../lens/public'; import { useAppIndexPatternContext } from './hooks/use_app_index_pattern'; -import { SeriesBuilder } from './series_builder/series_builder'; -import { SeriesUrl } from './types'; +import { SeriesViews } from './views/series_views'; import { LensEmbeddable } from './lens_embeddable'; import { EmptyView } from './components/empty_view'; -export const combineTimeRanges = ( - allSeries: Record, - firstSeries?: SeriesUrl -) => { - let to: string = ''; - let from: string = ''; - if (firstSeries?.reportType === 'kpi-over-time') { - return firstSeries.time; - } - Object.values(allSeries ?? {}).forEach((series) => { - if (series.dataType && series.reportType && !isEmpty(series.reportDefinitions)) { - const seriesTo = new Date(series.time.to); - const seriesFrom = new Date(series.time.from); - if (!to || seriesTo > new Date(to)) { - to = series.time.to; - } - if (!from || seriesFrom < new Date(from)) { - from = series.time.from; - } - } - }); - return { to, from }; -}; +export type PanelId = 'seriesPanel' | 'chartPanel'; export function ExploratoryView({ saveAttributes, - multiSeries, }: { - multiSeries?: boolean; saveAttributes?: (attr: TypedLensByValueInput['attributes'] | null) => void; }) { const { @@ -69,20 +45,19 @@ export function ExploratoryView({ const { loadIndexPattern, loading } = useAppIndexPatternContext(); - const { firstSeries, firstSeriesId, allSeries } = useSeriesStorage(); + const { firstSeries, allSeries, lastRefresh, reportType } = useSeriesStorage(); const lensAttributesT = useLensAttributes(); const setHeightOffset = () => { if (seriesBuilderRef?.current && wrapperRef.current) { const headerOffset = wrapperRef.current.getBoundingClientRect().top; - const seriesOffset = seriesBuilderRef.current.getBoundingClientRect().height; - setHeight(`calc(100vh - ${seriesOffset + headerOffset + 40}px)`); + setHeight(`calc(100vh - ${headerOffset + 40}px)`); } }; useEffect(() => { - Object.values(allSeries).forEach((seriesT) => { + allSeries.forEach((seriesT) => { loadIndexPattern({ dataType: seriesT.dataType, }); @@ -96,38 +71,102 @@ export function ExploratoryView({ } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [JSON.stringify(lensAttributesT ?? {})]); + }, [JSON.stringify(lensAttributesT ?? {}), lastRefresh]); useEffect(() => { setHeightOffset(); }); + const collapseFn = useRef<(id: PanelId, direction: PanelDirection) => void>(); + + const [hiddenPanel, setHiddenPanel] = useState(''); + + const onCollapse = (panelId: string) => { + setHiddenPanel((prevState) => (panelId === prevState ? '' : panelId)); + }; + + const onChange = (panelId: PanelId) => { + onCollapse(panelId); + if (collapseFn.current) { + collapseFn.current(panelId, panelId === 'seriesPanel' ? 'right' : 'left'); + } + }; + return ( {lens ? ( <> - + - {lensAttributes ? ( - - ) : ( - + + {(EuiResizablePanel, EuiResizableButton, { togglePanel }) => { + collapseFn.current = (id, direction) => togglePanel?.(id, { direction }); + + return ( + <> + + {lensAttributes ? ( + + ) : ( + + )} + + + + {hiddenPanel === 'chartPanel' ? ( + onChange('chartPanel')} iconType="arrowDown"> + {SHOW_CHART_LABEL} + + ) : ( + onChange('chartPanel')} + iconType="arrowUp" + color="text" + > + {HIDE_CHART_LABEL} + + )} + + + + ); + }} + + {hiddenPanel === 'seriesPanel' && ( + onChange('seriesPanel')} iconType="arrowUp"> + {PREVIEW_LABEL} + )} - ) : ( -

    - {i18n.translate('xpack.observability.overview.exploratoryView.lensDisabled', { - defaultMessage: - 'Lens app is not available, please enable Lens to use exploratory view.', - })} -

    +

    {LENS_NOT_AVAILABLE}

    )}
    @@ -147,4 +186,39 @@ const Wrapper = styled(EuiPanel)` margin: 0 auto; width: 100%; overflow-x: auto; + position: relative; +`; + +const ShowPreview = styled(EuiButtonEmpty)` + position: absolute; + bottom: 34px; +`; +const HideChart = styled(EuiButtonEmpty)` + position: absolute; + top: -35px; + right: 50px; `; +const ShowChart = styled(EuiButtonEmpty)` + position: absolute; + top: -10px; + right: 50px; +`; + +const HIDE_CHART_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.hideChart', { + defaultMessage: 'Hide chart', +}); + +const SHOW_CHART_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.showChart', { + defaultMessage: 'Show chart', +}); + +const PREVIEW_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.preview', { + defaultMessage: 'Preview', +}); + +const LENS_NOT_AVAILABLE = i18n.translate( + 'xpack.observability.overview.exploratoryView.lensDisabled', + { + defaultMessage: 'Lens app is not available, please enable Lens to use exploratory view.', + } +); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.test.tsx index 619ea0d21ae15..b8f16f3e5effb 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.test.tsx @@ -23,14 +23,15 @@ describe('AddToCaseAction', function () { it('should be able to click add to case button', async function () { const initSeries = { - data: { - 'uptime-pings-histogram': { + data: [ + { + name: 'test-series', dataType: 'synthetics' as const, reportType: 'kpi-over-time' as const, breakdown: 'monitor.status', time: { from: 'now-15m', to: 'now' }, }, - }, + ], }; const { findByText, core } = render( diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.tsx index 4fa8deb2700d0..bc813a4980e78 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.tsx @@ -17,7 +17,7 @@ import { Case, SubCase } from '../../../../../../cases/common'; import { observabilityFeatureId } from '../../../../../common'; export interface AddToCaseProps { - timeRange: { from: string; to: string }; + timeRange?: { from: string; to: string }; lensAttributes: TypedLensByValueInput['attributes'] | null; } @@ -54,6 +54,7 @@ export function AddToCaseAction({ lensAttributes, timeRange }: AddToCaseProps) { return ( <> ); - getByText('Open in Lens'); - }); - - it('should be able to click open in lens', function () { - const initSeries = { - data: { - 'uptime-pings-histogram': { - dataType: 'synthetics' as const, - reportType: 'kpi-over-time' as const, - breakdown: 'monitor.status', - time: { from: 'now-15m', to: 'now' }, - }, - }, - }; - - const { getByText, core } = render( - , - { initSeries } - ); - fireEvent.click(getByText('Open in Lens')); - - expect(core?.lens?.navigateToPrefilledEditor).toHaveBeenCalledTimes(1); - expect(core?.lens?.navigateToPrefilledEditor).toHaveBeenCalledWith( - { - attributes: { title: 'Performance distribution' }, - id: '', - timeRange: { - from: 'now-15m', - to: 'now', - }, - }, - { openInNewTab: true } - ); + getByText('Refresh'); }); }); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/header.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/header.tsx index 7adef4779ea94..bec8673f88b4e 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/header.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/header.tsx @@ -5,44 +5,37 @@ * 2.0. */ -import React, { useState } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiBetaBadge, EuiButton, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import { TypedLensByValueInput, LensEmbeddableInput } from '../../../../../../lens/public'; -import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; +import { TypedLensByValueInput } from '../../../../../../lens/public'; import { DataViewLabels } from '../configurations/constants'; -import { ObservabilityAppServices } from '../../../../application/types'; import { useSeriesStorage } from '../hooks/use_series_storage'; -import { combineTimeRanges } from '../exploratory_view'; -import { AddToCaseAction } from './add_to_case_action'; +import { LastUpdated } from './last_updated'; +import { combineTimeRanges } from '../lens_embeddable'; +import { ExpViewActionMenu } from '../components/action_menu'; interface Props { - seriesId: string; + seriesId?: number; + lastUpdated?: number; lensAttributes: TypedLensByValueInput['attributes'] | null; } -export function ExploratoryViewHeader({ seriesId, lensAttributes }: Props) { - const kServices = useKibana().services; +export function ExploratoryViewHeader({ seriesId, lensAttributes, lastUpdated }: Props) { + const { getSeries, allSeries, setLastRefresh, reportType } = useSeriesStorage(); - const { lens } = kServices; + const series = seriesId ? getSeries(seriesId) : undefined; - const { getSeries, allSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); - - const [isSaveOpen, setIsSaveOpen] = useState(false); - - const LensSaveModalComponent = lens.SaveModalComponent; - - const timeRange = combineTimeRanges(allSeries, series); + const timeRange = combineTimeRanges(reportType, allSeries, series); return ( <> +

    - {DataViewLabels[series.reportType] ?? + {DataViewLabels[reportType] ?? i18n.translate('xpack.observability.expView.heading.label', { defaultMessage: 'Analyze data', })}{' '} @@ -58,58 +51,18 @@ export function ExploratoryViewHeader({ seriesId, lensAttributes }: Props) { - + - { - if (lensAttributes) { - lens.navigateToPrefilledEditor( - { - id: '', - timeRange, - attributes: lensAttributes, - }, - { - openInNewTab: true, - } - ); - } - }} - > - {i18n.translate('xpack.observability.expView.heading.openInLens', { - defaultMessage: 'Open in Lens', - })} - - - - { - if (lensAttributes) { - setIsSaveOpen(true); - } - }} - > - {i18n.translate('xpack.observability.expView.heading.saveLensVisualization', { - defaultMessage: 'Save', - })} + setLastRefresh(Date.now())}> + {REFRESH_LABEL} - - {isSaveOpen && lensAttributes && ( - setIsSaveOpen(false)} - onSave={() => {}} - /> - )} ); } + +const REFRESH_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.refresh', { + defaultMessage: 'Refresh', +}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/last_updated.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/last_updated.tsx similarity index 55% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/last_updated.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/header/last_updated.tsx index 874171de123d2..c352ec0423dd8 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/last_updated.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/last_updated.tsx @@ -8,6 +8,7 @@ import React, { useEffect, useState } from 'react'; import { EuiIcon, EuiText } from '@elastic/eui'; import moment from 'moment'; +import { FormattedMessage } from '@kbn/i18n/react'; interface Props { lastUpdated?: number; @@ -18,20 +19,34 @@ export function LastUpdated({ lastUpdated }: Props) { useEffect(() => { const interVal = setInterval(() => { setRefresh(Date.now()); - }, 1000); + }, 5000); return () => { clearInterval(interVal); }; }, []); + useEffect(() => { + setRefresh(Date.now()); + }, [lastUpdated]); + if (!lastUpdated) { return null; } + const isWarning = moment().diff(moment(lastUpdated), 'minute') > 5; + const isDanger = moment().diff(moment(lastUpdated), 'minute') > 10; + return ( - - Last Updated: {moment(lastUpdated).from(refresh)} + + + ); } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.ts index 5ec9e1d4ab4b5..d1e15aa916eed 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.ts @@ -25,7 +25,7 @@ async function addToCase( http: HttpSetup, theCase: Case | SubCase, attributes: TypedLensByValueInput['attributes'], - timeRange: { from: string; to: string } + timeRange?: { from: string; to: string } ) { const apiPath = `/api/cases/${theCase?.id}/comments`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_index_pattern.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_index_pattern.tsx index 88818665bbe2a..83a7ac1ae17dc 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_index_pattern.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_index_pattern.tsx @@ -27,7 +27,7 @@ interface ProviderProps { } type HasAppDataState = Record; -type IndexPatternState = Record; +export type IndexPatternState = Record; type LoadingState = Record; export function IndexPatternContextProvider({ children }: ProviderProps) { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx new file mode 100644 index 0000000000000..4f19a8131f669 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useCallback, useEffect, useState } from 'react'; +import { useKibana } from '../../../../utils/kibana_react'; +import { SeriesConfig, SeriesUrl } from '../types'; +import { useAppIndexPatternContext } from './use_app_index_pattern'; +import { buildExistsFilter, buildPhraseFilter, buildPhrasesFilter } from '../configurations/utils'; +import { getFiltersFromDefs } from './use_lens_attributes'; +import { RECORDS_FIELD, RECORDS_PERCENTAGE_FIELD } from '../configurations/constants'; + +interface UseDiscoverLink { + seriesConfig?: SeriesConfig; + series: SeriesUrl; +} + +export const useDiscoverLink = ({ series, seriesConfig }: UseDiscoverLink) => { + const kServices = useKibana().services; + const { + application: { navigateToUrl }, + } = kServices; + + const { indexPatterns } = useAppIndexPatternContext(); + + const urlGenerator = kServices.discover?.urlGenerator; + const [discoverUrl, setDiscoverUrl] = useState(''); + + useEffect(() => { + const indexPattern = indexPatterns?.[series.dataType]; + + const definitions = series.reportDefinitions ?? {}; + const filters = [...(seriesConfig?.baseFilters ?? [])]; + + const definitionFilters = getFiltersFromDefs(definitions); + + definitionFilters.forEach(({ field, values = [] }) => { + if (values.length > 1) { + filters.push(buildPhrasesFilter(field, values, indexPattern)[0]); + } else { + filters.push(buildPhraseFilter(field, values[0], indexPattern)[0]); + } + }); + + const selectedMetricField = series.selectedMetricField; + + if ( + selectedMetricField && + selectedMetricField !== RECORDS_FIELD && + selectedMetricField !== RECORDS_PERCENTAGE_FIELD + ) { + filters.push(buildExistsFilter(selectedMetricField, indexPattern)[0]); + } + + const getDiscoverUrl = async () => { + if (!urlGenerator?.createUrl) return; + + const newUrl = await urlGenerator.createUrl({ + filters, + indexPatternId: indexPattern?.id, + }); + setDiscoverUrl(newUrl); + }; + getDiscoverUrl(); + }, [ + indexPatterns, + series.dataType, + series.reportDefinitions, + series.selectedMetricField, + seriesConfig?.baseFilters, + urlGenerator, + ]); + + const onClick = useCallback( + (event: React.MouseEvent) => { + if (discoverUrl) { + event.preventDefault(); + + return navigateToUrl(discoverUrl); + } + }, + [discoverUrl, navigateToUrl] + ); + + return { + href: discoverUrl, + onClick, + }; +}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.ts index 8bb265b4f6d89..ef974d54e6cdc 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.ts @@ -9,12 +9,18 @@ import { useMemo } from 'react'; import { isEmpty } from 'lodash'; import { TypedLensByValueInput } from '../../../../../../lens/public'; import { LayerConfig, LensAttributes } from '../configurations/lens_attributes'; -import { useSeriesStorage } from './use_series_storage'; +import { + AllSeries, + allSeriesKey, + convertAllShortSeries, + useSeriesStorage, +} from './use_series_storage'; import { getDefaultConfigs } from '../configurations/default_configs'; import { SeriesUrl, UrlFilter } from '../types'; import { useAppIndexPatternContext } from './use_app_index_pattern'; import { ALL_VALUES_SELECTED } from '../../field_value_suggestions/field_value_combobox'; +import { useTheme } from '../../../../hooks/use_theme'; export const getFiltersFromDefs = (reportDefinitions: SeriesUrl['reportDefinitions']) => { return Object.entries(reportDefinitions ?? {}) @@ -28,41 +34,54 @@ export const getFiltersFromDefs = (reportDefinitions: SeriesUrl['reportDefinitio }; export const useLensAttributes = (): TypedLensByValueInput['attributes'] | null => { - const { allSeriesIds, allSeries } = useSeriesStorage(); + const { storage, allSeries, lastRefresh, reportType } = useSeriesStorage(); const { indexPatterns } = useAppIndexPatternContext(); + const theme = useTheme(); + return useMemo(() => { - if (isEmpty(indexPatterns) || isEmpty(allSeriesIds)) { + if (isEmpty(indexPatterns) || isEmpty(allSeries) || !reportType) { return null; } + const allSeriesT: AllSeries = convertAllShortSeries(storage.get(allSeriesKey) ?? []); + const layerConfigs: LayerConfig[] = []; - allSeriesIds.forEach((seriesIdT) => { - const seriesT = allSeries[seriesIdT]; - const indexPattern = indexPatterns?.[seriesT?.dataType]; - if (indexPattern && seriesT.reportType && !isEmpty(seriesT.reportDefinitions)) { + allSeriesT.forEach((series, seriesIndex) => { + const indexPattern = indexPatterns?.[series?.dataType]; + + if ( + indexPattern && + !isEmpty(series.reportDefinitions) && + !series.hidden && + series.selectedMetricField + ) { const seriesConfig = getDefaultConfigs({ - reportType: seriesT.reportType, - dataType: seriesT.dataType, + reportType, indexPattern, + dataType: series.dataType, }); - const filters: UrlFilter[] = (seriesT.filters ?? []).concat( - getFiltersFromDefs(seriesT.reportDefinitions) + const filters: UrlFilter[] = (series.filters ?? []).concat( + getFiltersFromDefs(series.reportDefinitions) ); + const color = `euiColorVis${seriesIndex}`; + layerConfigs.push({ filters, indexPattern, seriesConfig, - time: seriesT.time, - breakdown: seriesT.breakdown, - seriesType: seriesT.seriesType, - operationType: seriesT.operationType, - reportDefinitions: seriesT.reportDefinitions ?? {}, - selectedMetricField: seriesT.selectedMetricField, + time: series.time, + name: series.name, + breakdown: series.breakdown, + seriesType: series.seriesType, + operationType: series.operationType, + reportDefinitions: series.reportDefinitions ?? {}, + selectedMetricField: series.selectedMetricField, + color: series.color ?? (theme.eui as unknown as Record)[color], }); } }); @@ -73,6 +92,6 @@ export const useLensAttributes = (): TypedLensByValueInput['attributes'] | null const lensAttributes = new LensAttributes(layerConfigs); - return lensAttributes.getJSON(); - }, [indexPatterns, allSeriesIds, allSeries]); + return lensAttributes.getJSON(lastRefresh); + }, [indexPatterns, allSeries, reportType, storage, theme, lastRefresh]); }; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_filters.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_filters.ts index 2d2618bc46152..f2a6130cdc59d 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_filters.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_filters.ts @@ -6,18 +6,16 @@ */ import { useSeriesStorage } from './use_series_storage'; -import { UrlFilter } from '../types'; +import { SeriesUrl, UrlFilter } from '../types'; export interface UpdateFilter { field: string; - value: string; + value: string | string[]; negate?: boolean; } -export const useSeriesFilters = ({ seriesId }: { seriesId: string }) => { - const { getSeries, setSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); +export const useSeriesFilters = ({ seriesId, series }: { seriesId: number; series: SeriesUrl }) => { + const { setSeries } = useSeriesStorage(); const filters = series.filters ?? []; @@ -26,10 +24,14 @@ export const useSeriesFilters = ({ seriesId }: { seriesId: string }) => { .map((filter) => { if (filter.field === field) { if (negate) { - const notValuesN = filter.notValues?.filter((val) => val !== value); + const notValuesN = filter.notValues?.filter((val) => + value instanceof Array ? !value.includes(val) : val !== value + ); return { ...filter, notValues: notValuesN }; } else { - const valuesN = filter.values?.filter((val) => val !== value); + const valuesN = filter.values?.filter((val) => + value instanceof Array ? !value.includes(val) : val !== value + ); return { ...filter, values: valuesN }; } } @@ -43,9 +45,9 @@ export const useSeriesFilters = ({ seriesId }: { seriesId: string }) => { const addFilter = ({ field, value, negate }: UpdateFilter) => { const currFilter: UrlFilter = { field }; if (negate) { - currFilter.notValues = [value]; + currFilter.notValues = value instanceof Array ? value : [value]; } else { - currFilter.values = [value]; + currFilter.values = value instanceof Array ? value : [value]; } if (filters.length === 0) { setSeries(seriesId, { ...series, filters: [currFilter] }); @@ -65,13 +67,26 @@ export const useSeriesFilters = ({ seriesId }: { seriesId: string }) => { const currNotValues = currFilter.notValues ?? []; const currValues = currFilter.values ?? []; - const notValues = currNotValues.filter((val) => val !== value); - const values = currValues.filter((val) => val !== value); + const notValues = currNotValues.filter((val) => + value instanceof Array ? !value.includes(val) : val !== value + ); + + const values = currValues.filter((val) => + value instanceof Array ? !value.includes(val) : val !== value + ); if (negate) { - notValues.push(value); + if (value instanceof Array) { + notValues.push(...value); + } else { + notValues.push(value); + } } else { - values.push(value); + if (value instanceof Array) { + values.push(...value); + } else { + values.push(value); + } } currFilter.notValues = notValues.length > 0 ? notValues : undefined; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx index c32acc47abd1b..ce6d7bd94d8e4 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx @@ -6,37 +6,39 @@ */ import React, { useEffect } from 'react'; - -import { UrlStorageContextProvider, useSeriesStorage } from './use_series_storage'; +import { Route, Router } from 'react-router-dom'; import { render } from '@testing-library/react'; +import { UrlStorageContextProvider, useSeriesStorage } from './use_series_storage'; +import { getHistoryFromUrl } from '../rtl_helpers'; -const mockSingleSeries = { - 'performance-distribution': { - reportType: 'data-distribution', +const mockSingleSeries = [ + { + name: 'performance-distribution', dataType: 'ux', breakdown: 'user_agent.name', time: { from: 'now-15m', to: 'now' }, }, -}; +]; -const mockMultipleSeries = { - 'performance-distribution': { - reportType: 'data-distribution', +const mockMultipleSeries = [ + { + name: 'performance-distribution', dataType: 'ux', breakdown: 'user_agent.name', time: { from: 'now-15m', to: 'now' }, }, - 'kpi-over-time': { - reportType: 'kpi-over-time', + { + name: 'kpi-over-time', dataType: 'synthetics', breakdown: 'user_agent.name', time: { from: 'now-15m', to: 'now' }, }, -}; +]; -describe('userSeries', function () { +describe('userSeriesStorage', function () { function setupTestComponent(seriesData: any) { const setData = jest.fn(); + function TestComponent() { const data = useSeriesStorage(); @@ -48,11 +50,20 @@ describe('userSeries', function () { } render( - - - + + + (key === 'sr' ? seriesData : null)), + set: jest.fn(), + }} + > + + + + ); return setData; @@ -63,22 +74,20 @@ describe('userSeries', function () { expect(setData).toHaveBeenCalledTimes(2); expect(setData).toHaveBeenLastCalledWith( expect.objectContaining({ - allSeries: { - 'performance-distribution': { - breakdown: 'user_agent.name', + allSeries: [ + { + name: 'performance-distribution', dataType: 'ux', - reportType: 'data-distribution', + breakdown: 'user_agent.name', time: { from: 'now-15m', to: 'now' }, }, - }, - allSeriesIds: ['performance-distribution'], + ], firstSeries: { - breakdown: 'user_agent.name', + name: 'performance-distribution', dataType: 'ux', - reportType: 'data-distribution', + breakdown: 'user_agent.name', time: { from: 'now-15m', to: 'now' }, }, - firstSeriesId: 'performance-distribution', }) ); }); @@ -89,42 +98,38 @@ describe('userSeries', function () { expect(setData).toHaveBeenCalledTimes(2); expect(setData).toHaveBeenLastCalledWith( expect.objectContaining({ - allSeries: { - 'performance-distribution': { - breakdown: 'user_agent.name', + allSeries: [ + { + name: 'performance-distribution', dataType: 'ux', - reportType: 'data-distribution', + breakdown: 'user_agent.name', time: { from: 'now-15m', to: 'now' }, }, - 'kpi-over-time': { - reportType: 'kpi-over-time', + { + name: 'kpi-over-time', dataType: 'synthetics', breakdown: 'user_agent.name', time: { from: 'now-15m', to: 'now' }, }, - }, - allSeriesIds: ['performance-distribution', 'kpi-over-time'], + ], firstSeries: { - breakdown: 'user_agent.name', + name: 'performance-distribution', dataType: 'ux', - reportType: 'data-distribution', + breakdown: 'user_agent.name', time: { from: 'now-15m', to: 'now' }, }, - firstSeriesId: 'performance-distribution', }) ); }); it('should return expected result when there are no series', function () { - const setData = setupTestComponent({}); + const setData = setupTestComponent([]); - expect(setData).toHaveBeenCalledTimes(2); + expect(setData).toHaveBeenCalledTimes(1); expect(setData).toHaveBeenLastCalledWith( expect.objectContaining({ - allSeries: {}, - allSeriesIds: [], + allSeries: [], firstSeries: undefined, - firstSeriesId: undefined, }) ); }); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.tsx index a47a124d14b4d..d9a5adc822140 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.tsx @@ -22,13 +22,17 @@ import { OperationType, SeriesType } from '../../../../../../lens/public'; import { URL_KEYS } from '../configurations/constants/url_constants'; export interface SeriesContextValue { - firstSeries: SeriesUrl; - firstSeriesId: string; - allSeriesIds: string[]; + firstSeries?: SeriesUrl; + lastRefresh: number; + setLastRefresh: (val: number) => void; + applyChanges: () => void; allSeries: AllSeries; - setSeries: (seriesIdN: string, newValue: SeriesUrl) => void; - getSeries: (seriesId: string) => SeriesUrl; - removeSeries: (seriesId: string) => void; + setSeries: (seriesIndex: number, newValue: SeriesUrl) => void; + getSeries: (seriesIndex: number) => SeriesUrl | undefined; + removeSeries: (seriesIndex: number) => void; + setReportType: (reportType: string) => void; + storage: IKbnUrlStateStorage | ISessionStorageStateStorage; + reportType: ReportViewType; } export const UrlStorageContext = createContext({} as SeriesContextValue); @@ -36,72 +40,87 @@ interface ProviderProps { storage: IKbnUrlStateStorage | ISessionStorageStateStorage; } -function convertAllShortSeries(allShortSeries: AllShortSeries) { - const allSeriesIds = Object.keys(allShortSeries); - const allSeriesN: AllSeries = {}; - allSeriesIds.forEach((seriesKey) => { - allSeriesN[seriesKey] = convertFromShortUrl(allShortSeries[seriesKey]); - }); - - return allSeriesN; +export function convertAllShortSeries(allShortSeries: AllShortSeries) { + return (allShortSeries ?? []).map((shortSeries) => convertFromShortUrl(shortSeries)); } +export const allSeriesKey = 'sr'; +const reportTypeKey = 'reportType'; + export function UrlStorageContextProvider({ children, storage, }: ProviderProps & { children: JSX.Element }) { - const allSeriesKey = 'sr'; - - const [allShortSeries, setAllShortSeries] = useState( - () => storage.get(allSeriesKey) ?? {} - ); const [allSeries, setAllSeries] = useState(() => - convertAllShortSeries(storage.get(allSeriesKey) ?? {}) + convertAllShortSeries(storage.get(allSeriesKey) ?? []) ); - const [firstSeriesId, setFirstSeriesId] = useState(''); + + const [lastRefresh, setLastRefresh] = useState(() => Date.now()); + + const [reportType, setReportType] = useState( + () => (storage as IKbnUrlStateStorage).get(reportTypeKey) ?? '' + ); + const [firstSeries, setFirstSeries] = useState(); useEffect(() => { - const allSeriesIds = Object.keys(allShortSeries); - const allSeriesN: AllSeries = convertAllShortSeries(allShortSeries ?? {}); + const firstSeriesT = allSeries?.[0]; - setAllSeries(allSeriesN); - setFirstSeriesId(allSeriesIds?.[0]); - setFirstSeries(allSeriesN?.[allSeriesIds?.[0]]); - (storage as IKbnUrlStateStorage).set(allSeriesKey, allShortSeries); - }, [allShortSeries, storage]); + setFirstSeries(firstSeriesT); + }, [allSeries, storage]); - const setSeries = (seriesIdN: string, newValue: SeriesUrl) => { - setAllShortSeries((prevState) => { - prevState[seriesIdN] = convertToShortUrl(newValue); - return { ...prevState }; - }); - }; + const setSeries = useCallback((seriesIndex: number, newValue: SeriesUrl) => { + setAllSeries((prevAllSeries) => { + const newStateRest = prevAllSeries.map((series, index) => { + if (index === seriesIndex) { + return newValue; + } + return series; + }); + + if (prevAllSeries.length === seriesIndex) { + return [...newStateRest, newValue]; + } - const removeSeries = (seriesIdN: string) => { - setAllShortSeries((prevState) => { - delete prevState[seriesIdN]; - return { ...prevState }; + return [...newStateRest]; }); - }; + }, []); - const allSeriesIds = Object.keys(allShortSeries); + useEffect(() => { + (storage as IKbnUrlStateStorage).set(reportTypeKey, reportType); + }, [reportType, storage]); + + const removeSeries = useCallback((seriesIndex: number) => { + setAllSeries((prevAllSeries) => + prevAllSeries.filter((seriesT, index) => index !== seriesIndex) + ); + }, []); const getSeries = useCallback( - (seriesId?: string) => { - return seriesId ? allSeries?.[seriesId] ?? {} : ({} as SeriesUrl); + (seriesIndex: number) => { + return allSeries[seriesIndex]; }, [allSeries] ); + const applyChanges = useCallback(() => { + const allShortSeries = allSeries.map((series) => convertToShortUrl(series)); + + (storage as IKbnUrlStateStorage).set(allSeriesKey, allShortSeries); + setLastRefresh(Date.now()); + }, [allSeries, storage]); + const value = { + applyChanges, storage, getSeries, setSeries, removeSeries, - firstSeriesId, allSeries, - allSeriesIds, + lastRefresh, + setLastRefresh, + setReportType, + reportType: storage.get(reportTypeKey) as ReportViewType, firstSeries: firstSeries!, }; return {children}; @@ -112,10 +131,9 @@ export function useSeriesStorage() { } function convertFromShortUrl(newValue: ShortUrlSeries): SeriesUrl { - const { dt, op, st, rt, bd, ft, time, rdf, mt, ...restSeries } = newValue; + const { dt, op, st, bd, ft, time, rdf, mt, h, n, c, ...restSeries } = newValue; return { operationType: op, - reportType: rt!, seriesType: st, breakdown: bd, filters: ft!, @@ -123,26 +141,31 @@ function convertFromShortUrl(newValue: ShortUrlSeries): SeriesUrl { reportDefinitions: rdf, dataType: dt!, selectedMetricField: mt, + hidden: h, + name: n, + color: c, ...restSeries, }; } interface ShortUrlSeries { [URL_KEYS.OPERATION_TYPE]?: OperationType; - [URL_KEYS.REPORT_TYPE]?: ReportViewType; [URL_KEYS.DATA_TYPE]?: AppDataType; [URL_KEYS.SERIES_TYPE]?: SeriesType; [URL_KEYS.BREAK_DOWN]?: string; [URL_KEYS.FILTERS]?: UrlFilter[]; [URL_KEYS.REPORT_DEFINITIONS]?: URLReportDefinition; [URL_KEYS.SELECTED_METRIC]?: string; + [URL_KEYS.HIDDEN]?: boolean; + [URL_KEYS.NAME]: string; + [URL_KEYS.COLOR]?: string; time?: { to: string; from: string; }; } -export type AllShortSeries = Record; -export type AllSeries = Record; +export type AllShortSeries = ShortUrlSeries[]; +export type AllSeries = SeriesUrl[]; -export const NEW_SERIES_KEY = 'new-series-key'; +export const NEW_SERIES_KEY = 'new-series'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/index.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/index.tsx index e55752ceb62ba..3de29b02853e8 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/index.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/index.tsx @@ -25,11 +25,9 @@ import { TypedLensByValueInput } from '../../../../../lens/public'; export function ExploratoryViewPage({ saveAttributes, - multiSeries = false, useSessionStorage = false, }: { useSessionStorage?: boolean; - multiSeries?: boolean; saveAttributes?: (attr: TypedLensByValueInput['attributes'] | null) => void; }) { useTrackPageview({ app: 'observability-overview', path: 'exploratory-view' }); @@ -61,7 +59,7 @@ export function ExploratoryViewPage({ - + diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/lens_embeddable.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/lens_embeddable.tsx index 4cb586fe94ceb..9e4d9486dc155 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/lens_embeddable.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/lens_embeddable.tsx @@ -7,16 +7,51 @@ import { i18n } from '@kbn/i18n'; import React, { Dispatch, SetStateAction, useCallback } from 'react'; -import { combineTimeRanges } from './exploratory_view'; +import styled from 'styled-components'; +import { isEmpty } from 'lodash'; import { TypedLensByValueInput } from '../../../../../lens/public'; import { useSeriesStorage } from './hooks/use_series_storage'; import { ObservabilityPublicPluginsStart } from '../../../plugin'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { ReportViewType, SeriesUrl } from './types'; +import { ReportTypes } from './configurations/constants'; interface Props { lensAttributes: TypedLensByValueInput['attributes']; setLastUpdated: Dispatch>; } +export const combineTimeRanges = ( + reportType: ReportViewType, + allSeries: SeriesUrl[], + firstSeries?: SeriesUrl +) => { + let to: string = ''; + let from: string = ''; + + if (reportType === ReportTypes.KPI) { + return firstSeries?.time; + } + + allSeries.forEach((series) => { + if ( + series.dataType && + series.selectedMetricField && + !isEmpty(series.reportDefinitions) && + series.time + ) { + const seriesTo = new Date(series.time.to); + const seriesFrom = new Date(series.time.from); + if (!to || seriesTo > new Date(to)) { + to = series.time.to; + } + if (!from || seriesFrom < new Date(from)) { + from = series.time.from; + } + } + }); + + return { to, from }; +}; export function LensEmbeddable(props: Props) { const { lensAttributes, setLastUpdated } = props; @@ -27,9 +62,11 @@ export function LensEmbeddable(props: Props) { const LensComponent = lens?.EmbeddableComponent; - const { firstSeriesId, firstSeries: series, setSeries, allSeries } = useSeriesStorage(); + const { firstSeries, setSeries, allSeries, reportType } = useSeriesStorage(); - const timeRange = combineTimeRanges(allSeries, series); + const firstSeriesId = 0; + + const timeRange = firstSeries ? combineTimeRanges(reportType, allSeries, firstSeries) : null; const onLensLoad = useCallback(() => { setLastUpdated(Date.now()); @@ -37,9 +74,9 @@ export function LensEmbeddable(props: Props) { const onBrushEnd = useCallback( ({ range }: { range: number[] }) => { - if (series?.reportType !== 'data-distribution') { + if (reportType !== 'data-distribution' && firstSeries) { setSeries(firstSeriesId, { - ...series, + ...firstSeries, time: { from: new Date(range[0]).toISOString(), to: new Date(range[1]).toISOString(), @@ -53,16 +90,30 @@ export function LensEmbeddable(props: Props) { ); } }, - [notifications?.toasts, series, firstSeriesId, setSeries] + [reportType, setSeries, firstSeries, notifications?.toasts] ); + if (timeRange === null || !firstSeries) { + return null; + } + return ( - + + + ); } + +const LensWrapper = styled.div` + height: 100%; + + &&& > div { + height: 100%; + } +`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/rtl_helpers.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/rtl_helpers.tsx index a577a8df3e3d9..48a22f91eb7f6 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/rtl_helpers.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/rtl_helpers.tsx @@ -10,7 +10,7 @@ import React, { ReactElement } from 'react'; import { stringify } from 'query-string'; // eslint-disable-next-line import/no-extraneous-dependencies import { render as reactTestLibRender, RenderOptions } from '@testing-library/react'; -import { Router } from 'react-router-dom'; +import { Route, Router } from 'react-router-dom'; import { createMemoryHistory, History } from 'history'; import { CoreStart } from 'kibana/public'; import { I18nProvider } from '@kbn/i18n/react'; @@ -24,7 +24,7 @@ import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/ import { lensPluginMock } from '../../../../../lens/public/mocks'; import * as useAppIndexPatternHook from './hooks/use_app_index_pattern'; import { IndexPatternContextProvider } from './hooks/use_app_index_pattern'; -import { AllSeries, UrlStorageContext } from './hooks/use_series_storage'; +import { AllSeries, SeriesContextValue, UrlStorageContext } from './hooks/use_series_storage'; import * as fetcherHook from '../../../hooks/use_fetcher'; import * as useSeriesFilterHook from './hooks/use_series_filters'; @@ -35,10 +35,12 @@ import indexPatternData from './configurations/test_data/test_index_pattern.json // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { setIndexPatterns } from '../../../../../../../src/plugins/data/public/services'; import { IndexPattern, IndexPatternsContract } from '../../../../../../../src/plugins/data/common'; + +import { AppDataType, SeriesUrl, UrlFilter } from './types'; import { createStubIndexPattern } from '../../../../../../../src/plugins/data/common/stubs'; -import { AppDataType, UrlFilter } from './types'; import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; import { ListItem } from '../../../hooks/use_values_list'; +import { TRANSACTION_DURATION } from './configurations/constants/elasticsearch_fieldnames'; import { casesPluginMock } from '../../../../../cases/public/mocks'; interface KibanaProps { @@ -157,9 +159,11 @@ export function MockRouter({ }: MockRouterProps) { return ( - - {children} - + + + {children} + + ); } @@ -172,7 +176,7 @@ export function render( core: customCore, kibanaProps, renderOptions, - url, + url = '/app/observability/exploratory-view/', initSeries = {}, }: RenderRouterOptions = {} ) { @@ -202,7 +206,7 @@ export function render( }; } -const getHistoryFromUrl = (url: Url) => { +export const getHistoryFromUrl = (url: Url) => { if (typeof url === 'string') { return createMemoryHistory({ initialEntries: [url], @@ -251,6 +255,15 @@ export const mockUseValuesList = (values?: ListItem[]) => { return { spy, onRefreshTimeRange }; }; +export const mockUxSeries = { + name: 'performance-distribution', + dataType: 'ux', + breakdown: 'user_agent.name', + time: { from: 'now-15m', to: 'now' }, + reportDefinitions: { 'service.name': ['elastic-co'] }, + selectedMetricField: TRANSACTION_DURATION, +} as SeriesUrl; + function mockSeriesStorageContext({ data, filters, @@ -260,34 +273,34 @@ function mockSeriesStorageContext({ filters?: UrlFilter[]; breakdown?: string; }) { - const mockDataSeries = data || { - 'performance-distribution': { - reportType: 'data-distribution', - dataType: 'ux', - breakdown: breakdown || 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - ...(filters ? { filters } : {}), - }, + const testSeries = { + ...mockUxSeries, + breakdown: breakdown || 'user_agent.name', + ...(filters ? { filters } : {}), }; - const allSeriesIds = Object.keys(mockDataSeries); - const firstSeriesId = allSeriesIds?.[0]; - const series = mockDataSeries[firstSeriesId]; + const mockDataSeries = data || [testSeries]; const removeSeries = jest.fn(); const setSeries = jest.fn(); - const getSeries = jest.fn().mockReturnValue(series); + const getSeries = jest.fn().mockReturnValue(testSeries); return { - firstSeriesId, - allSeriesIds, removeSeries, setSeries, getSeries, - firstSeries: mockDataSeries[firstSeriesId], + autoApply: true, + reportType: 'data-distribution', + lastRefresh: Date.now(), + setLastRefresh: jest.fn(), + setAutoApply: jest.fn(), + applyChanges: jest.fn(), + firstSeries: mockDataSeries[0], allSeries: mockDataSeries, - }; + setReportType: jest.fn(), + storage: { get: jest.fn().mockReturnValue(mockDataSeries) } as any, + } as SeriesContextValue; } export function mockUseSeriesFilter() { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/data_types_col.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/data_types_col.test.tsx deleted file mode 100644 index b10702ebded57..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/data_types_col.test.tsx +++ /dev/null @@ -1,62 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { fireEvent, screen } from '@testing-library/react'; -import { mockAppIndexPattern, render } from '../../rtl_helpers'; -import { dataTypes, DataTypesCol } from './data_types_col'; - -describe('DataTypesCol', function () { - const seriesId = 'test-series-id'; - - mockAppIndexPattern(); - - it('should render properly', function () { - const { getByText } = render(); - - dataTypes.forEach(({ label }) => { - getByText(label); - }); - }); - - it('should set series on change', function () { - const { setSeries } = render(); - - fireEvent.click(screen.getByText(/user experience \(rum\)/i)); - - expect(setSeries).toHaveBeenCalledTimes(1); - expect(setSeries).toHaveBeenCalledWith(seriesId, { - dataType: 'ux', - isNew: true, - time: { - from: 'now-15m', - to: 'now', - }, - }); - }); - - it('should set series on change on already selected', function () { - const initSeries = { - data: { - [seriesId]: { - dataType: 'synthetics' as const, - reportType: 'kpi-over-time' as const, - breakdown: 'monitor.status', - time: { from: 'now-15m', to: 'now' }, - }, - }, - }; - - render(, { initSeries }); - - const button = screen.getByRole('button', { - name: /Synthetic Monitoring/i, - }); - - expect(button.classList).toContain('euiButton--fill'); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/data_types_col.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/data_types_col.tsx deleted file mode 100644 index f386f62d9ed73..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/data_types_col.tsx +++ /dev/null @@ -1,74 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import styled from 'styled-components'; -import { AppDataType } from '../../types'; -import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; - -export const dataTypes: Array<{ id: AppDataType; label: string }> = [ - { id: 'synthetics', label: 'Synthetic Monitoring' }, - { id: 'ux', label: 'User Experience (RUM)' }, - { id: 'mobile', label: 'Mobile Experience' }, - // { id: 'infra_logs', label: 'Logs' }, - // { id: 'infra_metrics', label: 'Metrics' }, - // { id: 'apm', label: 'APM' }, -]; - -export function DataTypesCol({ seriesId }: { seriesId: string }) { - const { getSeries, setSeries, removeSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); - const { loading } = useAppIndexPatternContext(); - - const onDataTypeChange = (dataType?: AppDataType) => { - if (!dataType) { - removeSeries(seriesId); - } else { - setSeries(seriesId || `${dataType}-series`, { - dataType, - isNew: true, - time: series.time, - } as any); - } - }; - - const selectedDataType = series.dataType; - - return ( - - {dataTypes.map(({ id: dataTypeId, label }) => ( - - - - ))} - - ); -} - -const FlexGroup = styled(EuiFlexGroup)` - width: 100%; -`; - -const Button = styled(EuiButton)` - will-change: transform; -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/date_picker_col.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/date_picker_col.tsx deleted file mode 100644 index 6be78084ae195..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/date_picker_col.tsx +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import styled from 'styled-components'; -import { SeriesDatePicker } from '../../series_date_picker'; -import { DateRangePicker } from '../../series_date_picker/date_range_picker'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; - -interface Props { - seriesId: string; -} -export function DatePickerCol({ seriesId }: Props) { - const { firstSeriesId, getSeries } = useSeriesStorage(); - const { reportType } = getSeries(firstSeriesId); - - return ( - - {firstSeriesId === seriesId || reportType !== 'kpi-over-time' ? ( - - ) : ( - - )} - - ); -} - -const Wrapper = styled.div` - .euiSuperDatePicker__flexWrapper { - width: 100%; - > .euiFlexItem { - margin-right: 0px; - } - } -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_breakdowns.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_breakdowns.test.tsx deleted file mode 100644 index a5e5ad3900ded..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_breakdowns.test.tsx +++ /dev/null @@ -1,74 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { fireEvent, screen } from '@testing-library/react'; -import { getDefaultConfigs } from '../../configurations/default_configs'; -import { mockIndexPattern, render } from '../../rtl_helpers'; -import { ReportBreakdowns } from './report_breakdowns'; -import { USER_AGENT_OS } from '../../configurations/constants/elasticsearch_fieldnames'; - -describe('Series Builder ReportBreakdowns', function () { - const seriesId = 'test-series-id'; - const dataViewSeries = getDefaultConfigs({ - reportType: 'data-distribution', - dataType: 'ux', - indexPattern: mockIndexPattern, - }); - - it('should render properly', function () { - render(); - - screen.getByText('Select an option: , is selected'); - screen.getAllByText('Browser family'); - }); - - it('should set new series breakdown on change', function () { - const { setSeries } = render( - - ); - - const btn = screen.getByRole('button', { - name: /select an option: Browser family , is selected/i, - hidden: true, - }); - - fireEvent.click(btn); - - fireEvent.click(screen.getByText(/operating system/i)); - - expect(setSeries).toHaveBeenCalledTimes(1); - expect(setSeries).toHaveBeenCalledWith(seriesId, { - breakdown: USER_AGENT_OS, - dataType: 'ux', - reportType: 'data-distribution', - time: { from: 'now-15m', to: 'now' }, - }); - }); - it('should set undefined on new series on no select breakdown', function () { - const { setSeries } = render( - - ); - - const btn = screen.getByRole('button', { - name: /select an option: Browser family , is selected/i, - hidden: true, - }); - - fireEvent.click(btn); - - fireEvent.click(screen.getByText(/no breakdown/i)); - - expect(setSeries).toHaveBeenCalledTimes(1); - expect(setSeries).toHaveBeenCalledWith(seriesId, { - breakdown: undefined, - dataType: 'ux', - reportType: 'data-distribution', - time: { from: 'now-15m', to: 'now' }, - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_breakdowns.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_breakdowns.tsx deleted file mode 100644 index fa2d01691ce1d..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_breakdowns.tsx +++ /dev/null @@ -1,26 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { Breakdowns } from '../../series_editor/columns/breakdowns'; -import { SeriesConfig } from '../../types'; - -export function ReportBreakdowns({ - seriesId, - seriesConfig, -}: { - seriesConfig: SeriesConfig; - seriesId: string; -}) { - return ( - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_col.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_col.tsx deleted file mode 100644 index 7962bf2b924f7..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_col.tsx +++ /dev/null @@ -1,101 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; -import styled from 'styled-components'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { ReportMetricOptions } from '../report_metric_options'; -import { SeriesConfig } from '../../types'; -import { SeriesChartTypesSelect } from './chart_types'; -import { OperationTypeSelect } from './operation_type_select'; -import { DatePickerCol } from './date_picker_col'; -import { parseCustomFieldName } from '../../configurations/lens_attributes'; -import { ReportDefinitionField } from './report_definition_field'; - -function getColumnType(seriesConfig: SeriesConfig, selectedMetricField?: string) { - const { columnType } = parseCustomFieldName(seriesConfig, selectedMetricField); - - return columnType; -} - -export function ReportDefinitionCol({ - seriesConfig, - seriesId, -}: { - seriesConfig: SeriesConfig; - seriesId: string; -}) { - const { getSeries, setSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); - - const { reportDefinitions: selectedReportDefinitions = {}, selectedMetricField } = series ?? {}; - - const { definitionFields, defaultSeriesType, hasOperationType, yAxisColumns, metricOptions } = - seriesConfig; - - const onChange = (field: string, value?: string[]) => { - if (!value?.[0]) { - delete selectedReportDefinitions[field]; - setSeries(seriesId, { - ...series, - reportDefinitions: { ...selectedReportDefinitions }, - }); - } else { - setSeries(seriesId, { - ...series, - reportDefinitions: { ...selectedReportDefinitions, [field]: value }, - }); - } - }; - - const columnType = getColumnType(seriesConfig, selectedMetricField); - - return ( - - - - - - {definitionFields.map((field) => ( - - - - ))} - {metricOptions && ( - - - - )} - {(hasOperationType || columnType === 'operation') && ( - - - - )} - - - - - ); -} - -const FlexGroup = styled(EuiFlexGroup)` - width: 100%; -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_filters.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_filters.test.tsx deleted file mode 100644 index 0b183b5f20c03..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_filters.test.tsx +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { screen } from '@testing-library/react'; -import { ReportFilters } from './report_filters'; -import { getDefaultConfigs } from '../../configurations/default_configs'; -import { mockIndexPattern, render } from '../../rtl_helpers'; - -describe('Series Builder ReportFilters', function () { - const seriesId = 'test-series-id'; - - const dataViewSeries = getDefaultConfigs({ - reportType: 'data-distribution', - indexPattern: mockIndexPattern, - dataType: 'ux', - }); - - it('should render properly', function () { - render(); - - screen.getByText('Add filter'); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_filters.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_filters.tsx deleted file mode 100644 index d5938c5387e8f..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_filters.tsx +++ /dev/null @@ -1,29 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { SeriesFilter } from '../../series_editor/columns/series_filter'; -import { SeriesConfig } from '../../types'; - -export function ReportFilters({ - seriesConfig, - seriesId, -}: { - seriesConfig: SeriesConfig; - seriesId: string; -}) { - return ( - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_types_col.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_types_col.test.tsx deleted file mode 100644 index 12ae8560453c9..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_types_col.test.tsx +++ /dev/null @@ -1,79 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { fireEvent, screen } from '@testing-library/react'; -import { mockAppIndexPattern, render } from '../../rtl_helpers'; -import { ReportTypesCol, SELECTED_DATA_TYPE_FOR_REPORT } from './report_types_col'; -import { ReportTypes } from '../series_builder'; -import { DEFAULT_TIME } from '../../configurations/constants'; - -describe('ReportTypesCol', function () { - const seriesId = 'performance-distribution'; - - mockAppIndexPattern(); - - it('should render properly', function () { - render(); - screen.getByText('Performance distribution'); - screen.getByText('KPI over time'); - }); - - it('should display empty message', function () { - render(); - screen.getByText(SELECTED_DATA_TYPE_FOR_REPORT); - }); - - it('should set series on change', function () { - const { setSeries } = render( - - ); - - fireEvent.click(screen.getByText(/KPI over time/i)); - - expect(setSeries).toHaveBeenCalledWith(seriesId, { - dataType: 'ux', - selectedMetricField: undefined, - reportType: 'kpi-over-time', - time: { from: 'now-15m', to: 'now' }, - }); - expect(setSeries).toHaveBeenCalledTimes(1); - }); - - it('should set selected as filled', function () { - const initSeries = { - data: { - [seriesId]: { - dataType: 'synthetics' as const, - reportType: 'kpi-over-time' as const, - breakdown: 'monitor.status', - time: { from: 'now-15m', to: 'now' }, - isNew: true, - }, - }, - }; - - const { setSeries } = render( - , - { initSeries } - ); - - const button = screen.getByRole('button', { - name: /KPI over time/i, - }); - - expect(button.classList).toContain('euiButton--fill'); - fireEvent.click(button); - - // undefined on click selected - expect(setSeries).toHaveBeenCalledWith(seriesId, { - dataType: 'synthetics', - time: DEFAULT_TIME, - isNew: true, - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_types_col.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_types_col.tsx deleted file mode 100644 index c4eebbfaca3eb..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_types_col.tsx +++ /dev/null @@ -1,108 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { map } from 'lodash'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import styled from 'styled-components'; -import { ReportViewType, SeriesUrl } from '../../types'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { DEFAULT_TIME } from '../../configurations/constants'; -import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; -import { ReportTypeItem } from '../series_builder'; - -interface Props { - seriesId: string; - reportTypes: ReportTypeItem[]; -} - -export function ReportTypesCol({ seriesId, reportTypes }: Props) { - const { setSeries, getSeries, firstSeries, firstSeriesId } = useSeriesStorage(); - - const { reportType: selectedReportType, ...restSeries } = getSeries(seriesId); - - const { loading, hasData } = useAppIndexPatternContext(restSeries.dataType); - - if (!restSeries.dataType) { - return ( - - ); - } - - if (!loading && !hasData) { - return ( - - ); - } - - const disabledReportTypes: ReportViewType[] = map( - reportTypes.filter( - ({ reportType }) => firstSeriesId !== seriesId && reportType !== firstSeries.reportType - ), - 'reportType' - ); - - return reportTypes?.length > 0 ? ( - - {reportTypes.map(({ reportType, label }) => ( - - - - ))} - - ) : ( - {SELECTED_DATA_TYPE_FOR_REPORT} - ); -} - -export const SELECTED_DATA_TYPE_FOR_REPORT = i18n.translate( - 'xpack.observability.expView.reportType.noDataType', - { defaultMessage: 'No data type selected.' } -); - -const FlexGroup = styled(EuiFlexGroup)` - width: 100%; -`; - -const Button = styled(EuiButton)` - will-change: transform; -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/report_metric_options.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/report_metric_options.tsx deleted file mode 100644 index a2a3e34c21834..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/report_metric_options.tsx +++ /dev/null @@ -1,46 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiSuperSelect } from '@elastic/eui'; -import { useSeriesStorage } from '../hooks/use_series_storage'; -import { SeriesConfig } from '../types'; - -interface Props { - seriesId: string; - defaultValue?: string; - options: SeriesConfig['metricOptions']; -} - -export function ReportMetricOptions({ seriesId, options: opts }: Props) { - const { getSeries, setSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); - - const onChange = (value: string) => { - setSeries(seriesId, { - ...series, - selectedMetricField: value, - }); - }; - - const options = opts ?? []; - - return ( - ({ - value: fd || id, - inputDisplay: label, - }))} - valueOfSelected={series.selectedMetricField || options?.[0].field || options?.[0].id} - onChange={(value) => onChange(value)} - /> - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/series_builder.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/series_builder.tsx deleted file mode 100644 index 684cf3a210a51..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/series_builder.tsx +++ /dev/null @@ -1,303 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { RefObject, useEffect, useState } from 'react'; -import { isEmpty } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { - EuiBasicTable, - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiSwitch, -} from '@elastic/eui'; -import { rgba } from 'polished'; -import { AppDataType, SeriesConfig, ReportViewType, SeriesUrl } from '../types'; -import { DataTypesCol } from './columns/data_types_col'; -import { ReportTypesCol } from './columns/report_types_col'; -import { ReportDefinitionCol } from './columns/report_definition_col'; -import { ReportFilters } from './columns/report_filters'; -import { ReportBreakdowns } from './columns/report_breakdowns'; -import { NEW_SERIES_KEY, useSeriesStorage } from '../hooks/use_series_storage'; -import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern'; -import { getDefaultConfigs } from '../configurations/default_configs'; -import { SeriesEditor } from '../series_editor/series_editor'; -import { SeriesActions } from '../series_editor/columns/series_actions'; -import { euiStyled } from '../../../../../../../../src/plugins/kibana_react/common'; -import { LastUpdated } from './last_updated'; -import { - CORE_WEB_VITALS_LABEL, - DEVICE_DISTRIBUTION_LABEL, - KPI_OVER_TIME_LABEL, - PERF_DIST_LABEL, -} from '../configurations/constants/labels'; - -export interface ReportTypeItem { - id: string; - reportType: ReportViewType; - label: string; -} - -export const ReportTypes: Record = { - synthetics: [ - { id: 'kpi', reportType: 'kpi-over-time', label: KPI_OVER_TIME_LABEL }, - { id: 'dist', reportType: 'data-distribution', label: PERF_DIST_LABEL }, - ], - ux: [ - { id: 'kpi', reportType: 'kpi-over-time', label: KPI_OVER_TIME_LABEL }, - { id: 'dist', reportType: 'data-distribution', label: PERF_DIST_LABEL }, - { id: 'cwv', reportType: 'core-web-vitals', label: CORE_WEB_VITALS_LABEL }, - ], - mobile: [ - { id: 'kpi', reportType: 'kpi-over-time', label: KPI_OVER_TIME_LABEL }, - { id: 'dist', reportType: 'data-distribution', label: PERF_DIST_LABEL }, - { id: 'mdd', reportType: 'device-data-distribution', label: DEVICE_DISTRIBUTION_LABEL }, - ], - apm: [], - infra_logs: [], - infra_metrics: [], -}; - -interface BuilderItem { - id: string; - series: SeriesUrl; - seriesConfig?: SeriesConfig; -} - -export function SeriesBuilder({ - seriesBuilderRef, - lastUpdated, - multiSeries, -}: { - seriesBuilderRef: RefObject; - lastUpdated?: number; - multiSeries?: boolean; -}) { - const [editorItems, setEditorItems] = useState([]); - const { getSeries, allSeries, allSeriesIds, setSeries, removeSeries } = useSeriesStorage(); - - const { loading, indexPatterns } = useAppIndexPatternContext(); - - useEffect(() => { - const getDataViewSeries = (dataType: AppDataType, reportType: SeriesUrl['reportType']) => { - if (indexPatterns?.[dataType]) { - return getDefaultConfigs({ - dataType, - indexPattern: indexPatterns[dataType], - reportType: reportType!, - }); - } - }; - - const seriesToEdit: BuilderItem[] = - allSeriesIds - .filter((sId) => { - return allSeries?.[sId]?.isNew; - }) - .map((sId) => { - const series = getSeries(sId); - const seriesConfig = getDataViewSeries(series.dataType, series.reportType); - - return { id: sId, series, seriesConfig }; - }) ?? []; - const initSeries: BuilderItem[] = [{ id: 'series-id', series: {} as SeriesUrl }]; - setEditorItems(multiSeries || seriesToEdit.length > 0 ? seriesToEdit : initSeries); - }, [allSeries, allSeriesIds, getSeries, indexPatterns, loading, multiSeries]); - - const columns = [ - { - name: i18n.translate('xpack.observability.expView.seriesBuilder.dataType', { - defaultMessage: 'Data Type', - }), - field: 'id', - width: '15%', - render: (seriesId: string) => , - }, - { - name: i18n.translate('xpack.observability.expView.seriesBuilder.report', { - defaultMessage: 'Report', - }), - width: '15%', - field: 'id', - render: (seriesId: string, { series: { dataType } }: BuilderItem) => ( - - ), - }, - { - name: i18n.translate('xpack.observability.expView.seriesBuilder.definition', { - defaultMessage: 'Definition', - }), - width: '30%', - field: 'id', - render: ( - seriesId: string, - { series: { dataType, reportType }, seriesConfig }: BuilderItem - ) => { - if (dataType && seriesConfig) { - return loading ? ( - LOADING_VIEW - ) : reportType ? ( - - ) : ( - SELECT_REPORT_TYPE - ); - } - - return null; - }, - }, - { - name: i18n.translate('xpack.observability.expView.seriesBuilder.filters', { - defaultMessage: 'Filters', - }), - width: '20%', - field: 'id', - render: (seriesId: string, { series: { reportType }, seriesConfig }: BuilderItem) => - reportType && seriesConfig ? ( - - ) : null, - }, - { - name: i18n.translate('xpack.observability.expView.seriesBuilder.breakdown', { - defaultMessage: 'Breakdowns', - }), - width: '20%', - field: 'id', - render: (seriesId: string, { series: { reportType }, seriesConfig }: BuilderItem) => - reportType && seriesConfig ? ( - - ) : null, - }, - ...(multiSeries - ? [ - { - name: i18n.translate('xpack.observability.expView.seriesBuilder.actions', { - defaultMessage: 'Actions', - }), - align: 'center' as const, - width: '10%', - field: 'id', - render: (seriesId: string, item: BuilderItem) => ( - - ), - }, - ] - : []), - ]; - - const applySeries = () => { - editorItems.forEach(({ series, id: seriesId }) => { - const { reportType, reportDefinitions, isNew, ...restSeries } = series; - - if (reportType && !isEmpty(reportDefinitions)) { - const reportDefId = Object.values(reportDefinitions ?? {})[0]; - const newSeriesId = `${reportDefId}-${reportType}`; - - const newSeriesN: SeriesUrl = { - ...restSeries, - reportType, - reportDefinitions, - }; - - setSeries(newSeriesId, newSeriesN); - removeSeries(seriesId); - } - }); - }; - - const addSeries = () => { - const prevSeries = allSeries?.[allSeriesIds?.[0]]; - setSeries( - `${NEW_SERIES_KEY}-${editorItems.length + 1}`, - prevSeries - ? ({ isNew: true, time: prevSeries.time } as SeriesUrl) - : ({ isNew: true } as SeriesUrl) - ); - }; - - return ( - - {multiSeries && ( - - - - - - {}} - compressed - /> - - - applySeries()} isDisabled={true} size="s"> - {i18n.translate('xpack.observability.expView.seriesBuilder.apply', { - defaultMessage: 'Apply changes', - })} - - - - addSeries()} size="s"> - {i18n.translate('xpack.observability.expView.seriesBuilder.addSeries', { - defaultMessage: 'Add Series', - })} - - - - )} -
    - {multiSeries && } - {editorItems.length > 0 && ( - - )} - -
    -
    - ); -} - -const Wrapper = euiStyled.div` - max-height: 50vh; - overflow-y: scroll; - overflow-x: clip; - &::-webkit-scrollbar { - height: ${({ theme }) => theme.eui.euiScrollBar}; - width: ${({ theme }) => theme.eui.euiScrollBar}; - } - &::-webkit-scrollbar-thumb { - background-clip: content-box; - background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; - border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; - } - &::-webkit-scrollbar-corner, - &::-webkit-scrollbar-track { - background-color: transparent; - } -`; - -export const LOADING_VIEW = i18n.translate( - 'xpack.observability.expView.seriesBuilder.loadingView', - { - defaultMessage: 'Loading view ...', - } -); - -export const SELECT_REPORT_TYPE = i18n.translate( - 'xpack.observability.expView.seriesBuilder.selectReportType', - { - defaultMessage: 'No report type selected', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/chart_edit_options.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/chart_edit_options.tsx deleted file mode 100644 index 207a53e13f1ad..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/chart_edit_options.tsx +++ /dev/null @@ -1,30 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { Breakdowns } from './columns/breakdowns'; -import { SeriesConfig } from '../types'; -import { ChartOptions } from './columns/chart_options'; - -interface Props { - seriesConfig: SeriesConfig; - seriesId: string; - breakdownFields: string[]; -} -export function ChartEditOptions({ seriesConfig, seriesId, breakdownFields }: Props) { - return ( - - - - - - - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/breakdowns.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/breakdowns.test.tsx index 84568e1c5068a..21b766227a562 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/breakdowns.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/breakdowns.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { fireEvent, screen } from '@testing-library/react'; import { Breakdowns } from './breakdowns'; -import { mockIndexPattern, render } from '../../rtl_helpers'; +import { mockIndexPattern, mockUxSeries, render } from '../../rtl_helpers'; import { getDefaultConfigs } from '../../configurations/default_configs'; import { USER_AGENT_OS } from '../../configurations/constants/elasticsearch_fieldnames'; @@ -20,13 +20,7 @@ describe('Breakdowns', function () { }); it('should render properly', async function () { - render( - - ); + render(); screen.getAllByText('Browser family'); }); @@ -36,9 +30,9 @@ describe('Breakdowns', function () { const { setSeries } = render( , { initSeries } ); @@ -49,10 +43,14 @@ describe('Breakdowns', function () { fireEvent.click(screen.getByText('Browser family')); - expect(setSeries).toHaveBeenCalledWith('series-id', { + expect(setSeries).toHaveBeenCalledWith(0, { breakdown: 'user_agent.name', dataType: 'ux', - reportType: 'data-distribution', + name: 'performance-distribution', + reportDefinitions: { + 'service.name': ['elastic-co'], + }, + selectedMetricField: 'transaction.duration.us', time: { from: 'now-15m', to: 'now' }, }); expect(setSeries).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/breakdowns.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/breakdowns.tsx index 2237935d466ad..6003ddbf0290f 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/breakdowns.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/breakdowns.tsx @@ -10,18 +10,16 @@ import { EuiSuperSelect } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useSeriesStorage } from '../../hooks/use_series_storage'; import { USE_BREAK_DOWN_COLUMN } from '../../configurations/constants'; -import { SeriesConfig } from '../../types'; +import { SeriesConfig, SeriesUrl } from '../../types'; interface Props { - seriesId: string; - breakdowns: string[]; - seriesConfig: SeriesConfig; + seriesId: number; + series: SeriesUrl; + seriesConfig?: SeriesConfig; } -export function Breakdowns({ seriesConfig, seriesId, breakdowns = [] }: Props) { - const { setSeries, getSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); +export function Breakdowns({ seriesConfig, seriesId, series }: Props) { + const { setSeries } = useSeriesStorage(); const selectedBreakdown = series.breakdown; const NO_BREAKDOWN = 'no_breakdown'; @@ -40,9 +38,13 @@ export function Breakdowns({ seriesConfig, seriesId, breakdowns = [] }: Props) { } }; + if (!seriesConfig) { + return null; + } + const hasUseBreakdownColumn = seriesConfig.xAxisColumn.sourceField === USE_BREAK_DOWN_COLUMN; - const items = breakdowns.map((breakdown) => ({ + const items = seriesConfig.breakdownFields.map((breakdown) => ({ id: breakdown, label: seriesConfig.labels[breakdown], })); @@ -50,14 +52,12 @@ export function Breakdowns({ seriesConfig, seriesId, breakdowns = [] }: Props) { if (!hasUseBreakdownColumn) { items.push({ id: NO_BREAKDOWN, - label: i18n.translate('xpack.observability.exp.breakDownFilter.noBreakdown', { - defaultMessage: 'No breakdown', - }), + label: NO_BREAK_DOWN_LABEL, }); } const options = items.map(({ id, label }) => ({ - inputDisplay: id === NO_BREAKDOWN ? label : {label}, + inputDisplay: label, value: id, dropdownDisplay: label, })); @@ -66,15 +66,18 @@ export function Breakdowns({ seriesConfig, seriesId, breakdowns = [] }: Props) { selectedBreakdown || (hasUseBreakdownColumn ? options[0].value : NO_BREAKDOWN); return ( -
    - onOptionChange(value)} - data-test-subj={'seriesBreakdown'} - /> -
    + onOptionChange(value)} + data-test-subj={'seriesBreakdown'} + /> ); } + +export const NO_BREAK_DOWN_LABEL = i18n.translate( + 'xpack.observability.exp.breakDownFilter.noBreakdown', + { + defaultMessage: 'No breakdown', + } +); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_options.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_options.tsx deleted file mode 100644 index f2a6377fd9b71..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_options.tsx +++ /dev/null @@ -1,35 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { SeriesConfig } from '../../types'; -import { OperationTypeSelect } from '../../series_builder/columns/operation_type_select'; -import { SeriesChartTypesSelect } from '../../series_builder/columns/chart_types'; - -interface Props { - seriesConfig: SeriesConfig; - seriesId: string; -} - -export function ChartOptions({ seriesConfig, seriesId }: Props) { - return ( - - - - - {seriesConfig.hasOperationType && ( - - - - )} - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_type_select.tsx new file mode 100644 index 0000000000000..6f88de5cc2afc --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_type_select.tsx @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { EuiPopover, EuiToolTip, EuiButtonEmpty, EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public'; +import { ObservabilityPublicPluginsStart } from '../../../../../plugin'; +import { SeriesUrl, useFetcher } from '../../../../../index'; +import { SeriesConfig } from '../../types'; +import { SeriesChartTypesSelect } from './chart_types'; + +interface Props { + seriesId: number; + series: SeriesUrl; + seriesConfig: SeriesConfig; +} + +export function SeriesChartTypes({ seriesId, series, seriesConfig }: Props) { + const seriesType = series?.seriesType ?? seriesConfig.defaultSeriesType; + + const { + services: { lens }, + } = useKibana(); + + const { data = [] } = useFetcher(() => lens.getXyVisTypes(), [lens]); + + const icon = (data ?? []).find(({ id }) => id === seriesType)?.icon; + + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + return ( + setIsPopoverOpen(false)} + button={ + + setIsPopoverOpen((prevState) => !prevState)} + flush="both" + > + {icon && ( + id === seriesType)?.icon!} size="l" /> + )} + + + } + > + + + ); +} + +const EDIT_CHART_TYPE_LABEL = i18n.translate( + 'xpack.observability.expView.seriesEditor.editChartSeriesLabel', + { + defaultMessage: 'Edit chart type for series', + } +); + +const CHART_TYPE_LABEL = i18n.translate('xpack.observability.expView.chartTypes.label', { + defaultMessage: 'Chart type', +}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/chart_types.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.test.tsx similarity index 85% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/chart_types.test.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.test.tsx index c054853d9c877..8f196b8a05dda 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/chart_types.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.test.tsx @@ -7,12 +7,12 @@ import React from 'react'; import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { render } from '../../rtl_helpers'; +import { mockUxSeries, render } from '../../rtl_helpers'; import { SeriesChartTypesSelect, XYChartTypesSelect } from './chart_types'; describe.skip('SeriesChartTypesSelect', function () { it('should render properly', async function () { - render(); + render(); await waitFor(() => { screen.getByText(/chart type/i); @@ -21,7 +21,7 @@ describe.skip('SeriesChartTypesSelect', function () { it('should call set series on change', async function () { const { setSeries } = render( - + ); await waitFor(() => { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/chart_types.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.tsx similarity index 77% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/chart_types.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.tsx index 50c2f91e6067d..27d846502dbe6 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/chart_types.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.tsx @@ -6,11 +6,11 @@ */ import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSuperSelect } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiIcon, EuiSuperSelect } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public'; import { ObservabilityPublicPluginsStart } from '../../../../../plugin'; -import { useFetcher } from '../../../../..'; +import { SeriesUrl, useFetcher } from '../../../../..'; import { useSeriesStorage } from '../../hooks/use_series_storage'; import { SeriesType } from '../../../../../../../lens/public'; @@ -20,16 +20,14 @@ const CHART_TYPE_LABEL = i18n.translate('xpack.observability.expView.chartTypes. export function SeriesChartTypesSelect({ seriesId, - seriesTypes, + series, defaultChartType, }: { - seriesId: string; - seriesTypes?: SeriesType[]; + seriesId: number; + series: SeriesUrl; defaultChartType: SeriesType; }) { - const { getSeries, setSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); + const { setSeries } = useSeriesStorage(); const seriesType = series?.seriesType ?? defaultChartType; @@ -42,17 +40,15 @@ export function SeriesChartTypesSelect({ onChange={onChange} value={seriesType} excludeChartTypes={['bar_percentage_stacked']} - includeChartTypes={ - seriesTypes || [ - 'bar', - 'bar_horizontal', - 'line', - 'area', - 'bar_stacked', - 'area_stacked', - 'bar_horizontal_percentage_stacked', - ] - } + includeChartTypes={[ + 'bar', + 'bar_horizontal', + 'line', + 'area', + 'bar_stacked', + 'area_stacked', + 'bar_horizontal_percentage_stacked', + ]} label={CHART_TYPE_LABEL} /> ); @@ -105,14 +101,14 @@ export function XYChartTypesSelect({ }); return ( - + + + ); } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.test.tsx new file mode 100644 index 0000000000000..fc96ad0741ec5 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.test.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { fireEvent, screen } from '@testing-library/react'; +import { mockAppIndexPattern, mockUxSeries, render } from '../../rtl_helpers'; +import { DataTypesLabels, DataTypesSelect } from './data_type_select'; +import { DataTypes } from '../../configurations/constants'; + +describe('DataTypeSelect', function () { + const seriesId = 0; + + mockAppIndexPattern(); + + it('should render properly', function () { + render(); + }); + + it('should set series on change', async function () { + const seriesWithoutDataType = { + ...mockUxSeries, + dataType: undefined, + }; + const { setSeries } = render( + + ); + + fireEvent.click(await screen.findByText('Select data type')); + fireEvent.click(await screen.findByText(DataTypesLabels[DataTypes.SYNTHETICS])); + + expect(setSeries).toHaveBeenCalledTimes(1); + expect(setSeries).toHaveBeenCalledWith(seriesId, { + dataType: 'synthetics', + name: 'synthetics-series-1', + time: { + from: 'now-15m', + to: 'now', + }, + }); + }); +}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx new file mode 100644 index 0000000000000..71fd147e8e264 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { + EuiButton, + EuiPopover, + EuiListGroup, + EuiListGroupItem, + EuiBadge, + EuiToolTip, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useSeriesStorage } from '../../hooks/use_series_storage'; +import { AppDataType, SeriesUrl } from '../../types'; +import { DataTypes, ReportTypes } from '../../configurations/constants'; + +interface Props { + seriesId: number; + series: Omit & { + dataType?: SeriesUrl['dataType']; + }; +} + +export const DataTypesLabels = { + [DataTypes.UX]: i18n.translate('xpack.observability.overview.exploratoryView.uxLabel', { + defaultMessage: 'User experience (RUM)', + }), + + [DataTypes.SYNTHETICS]: i18n.translate( + 'xpack.observability.overview.exploratoryView.syntheticsLabel', + { + defaultMessage: 'Synthetics monitoring', + } + ), + + [DataTypes.MOBILE]: i18n.translate( + 'xpack.observability.overview.exploratoryView.mobileExperienceLabel', + { + defaultMessage: 'Mobile experience', + } + ), +}; + +export const dataTypes: Array<{ id: AppDataType; label: string }> = [ + { + id: DataTypes.SYNTHETICS, + label: DataTypesLabels[DataTypes.SYNTHETICS], + }, + { + id: DataTypes.UX, + label: DataTypesLabels[DataTypes.UX], + }, + { + id: DataTypes.MOBILE, + label: DataTypesLabels[DataTypes.MOBILE], + }, +]; + +const SELECT_DATA_TYPE = 'SELECT_DATA_TYPE'; + +export function DataTypesSelect({ seriesId, series }: Props) { + const { setSeries, reportType } = useSeriesStorage(); + const [showOptions, setShowOptions] = useState(false); + + const onDataTypeChange = (dataType: AppDataType) => { + if (String(dataType) !== SELECT_DATA_TYPE) { + setSeries(seriesId, { + dataType, + time: series.time, + name: `${dataType}-series-${seriesId + 1}`, + }); + } + }; + + const options = dataTypes + .filter(({ id }) => { + if (reportType === ReportTypes.DEVICE_DISTRIBUTION) { + return id === DataTypes.MOBILE; + } + if (reportType === ReportTypes.CORE_WEB_VITAL) { + return id === DataTypes.UX; + } + return true; + }) + .map(({ id, label }) => ({ + value: id, + inputDisplay: label, + })); + + return ( + <> + {!series.dataType && ( + setShowOptions((prevState) => !prevState)} + fill + size="s" + > + {SELECT_DATA_TYPE_LABEL} + + } + isOpen={showOptions} + closePopover={() => setShowOptions((prevState) => !prevState)} + > + + {options.map((option) => ( + onDataTypeChange(option.value)} + label={option.inputDisplay} + /> + ))} + + + )} + {series.dataType && ( + + {DataTypesLabels[series.dataType as DataTypes]} + + )} + + ); +} + +const SELECT_DATA_TYPE_LABEL = i18n.translate( + 'xpack.observability.overview.exploratoryView.selectDataType', + { + defaultMessage: 'Select data type', + } +); + +const SELECT_DATA_TYPE_TOOLTIP = i18n.translate( + 'xpack.observability.overview.exploratoryView.selectDataTypeTooltip', + { + defaultMessage: 'Data type cannot be edited.', + } +); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx index 41e83f407af2b..b01010e4b81f9 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx @@ -6,24 +6,80 @@ */ import React from 'react'; -import { SeriesDatePicker } from '../../series_date_picker'; +import styled from 'styled-components'; +import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { DateRangePicker } from '../../series_date_picker/date_range_picker'; +import { DateRangePicker } from '../../components/date_range_picker'; +import { SeriesDatePicker } from '../../components/series_date_picker'; +import { AppDataType, SeriesUrl } from '../../types'; +import { ReportTypes } from '../../configurations/constants'; +import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; +import { SyntheticsAddData } from '../../../add_data_buttons/synthetics_add_data'; +import { MobileAddData } from '../../../add_data_buttons/mobile_add_data'; +import { UXAddData } from '../../../add_data_buttons/ux_add_data'; interface Props { - seriesId: string; + seriesId: number; + series: SeriesUrl; } -export function DatePickerCol({ seriesId }: Props) { - const { firstSeriesId, getSeries } = useSeriesStorage(); - const { reportType } = getSeries(firstSeriesId); + +const AddDataComponents: Record = { + mobile: MobileAddData, + ux: UXAddData, + synthetics: SyntheticsAddData, + apm: null, + infra_logs: null, + infra_metrics: null, +}; + +export function DatePickerCol({ seriesId, series }: Props) { + const { reportType } = useSeriesStorage(); + + const { hasAppData } = useAppIndexPatternContext(); + + if (!series.dataType) { + return null; + } + + const AddDataButton = AddDataComponents[series.dataType]; + if (hasAppData[series.dataType] === false && AddDataButton !== null) { + return ( + + + + {i18n.translate('xpack.observability.overview.exploratoryView.noDataAvailable', { + defaultMessage: 'No {dataType} data available.', + values: { + dataType: series.dataType, + }, + })} + + + + + + + ); + } return ( -
    - {firstSeriesId === seriesId || reportType !== 'kpi-over-time' ? ( - + + {seriesId === 0 || reportType !== ReportTypes.KPI ? ( + ) : ( - + )} -
    + ); } + +const Wrapper = styled.div` + width: 100%; + .euiSuperDatePicker__flexWrapper { + width: 100%; + > .euiFlexItem { + margin-right: 0; + } + } +`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.test.tsx index 90a039f6b44d0..a88e2eadd10c9 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.test.tsx @@ -8,20 +8,24 @@ import React from 'react'; import { fireEvent, screen, waitFor } from '@testing-library/react'; import { FilterExpanded } from './filter_expanded'; -import { mockAppIndexPattern, mockUseValuesList, render } from '../../rtl_helpers'; +import { mockUxSeries, mockAppIndexPattern, mockUseValuesList, render } from '../../rtl_helpers'; import { USER_AGENT_NAME } from '../../configurations/constants/elasticsearch_fieldnames'; describe('FilterExpanded', function () { - it('should render properly', async function () { - const initSeries = { filters: [{ field: USER_AGENT_NAME, values: ['Chrome'] }] }; + const filters = [{ field: USER_AGENT_NAME, values: ['Chrome'] }]; + + const mockSeries = { ...mockUxSeries, filters }; + + it('render', async () => { + const initSeries = { filters }; mockAppIndexPattern(); render( , { initSeries } @@ -33,15 +37,14 @@ describe('FilterExpanded', function () { }); it('should call go back on click', async function () { - const initSeries = { filters: [{ field: USER_AGENT_NAME, values: ['Chrome'] }] }; - const goBack = jest.fn(); + const initSeries = { filters }; render( , { initSeries } @@ -49,28 +52,23 @@ describe('FilterExpanded', function () { await waitFor(() => { fireEvent.click(screen.getByText('Browser Family')); - - expect(goBack).toHaveBeenCalledTimes(1); - expect(goBack).toHaveBeenCalledWith(); }); }); - it('should call useValuesList on load', async function () { - const initSeries = { filters: [{ field: USER_AGENT_NAME, values: ['Chrome'] }] }; + it('calls useValuesList on load', async () => { + const initSeries = { filters }; const { spy } = mockUseValuesList([ { label: 'Chrome', count: 10 }, { label: 'Firefox', count: 5 }, ]); - const goBack = jest.fn(); - render( , { initSeries } @@ -87,8 +85,8 @@ describe('FilterExpanded', function () { }); }); - it('should filter display values', async function () { - const initSeries = { filters: [{ field: USER_AGENT_NAME, values: ['Chrome'] }] }; + it('filters display values', async () => { + const initSeries = { filters }; mockUseValuesList([ { label: 'Chrome', count: 10 }, @@ -97,18 +95,20 @@ describe('FilterExpanded', function () { render( , { initSeries } ); - expect(screen.getByText('Firefox')).toBeTruthy(); - await waitFor(() => { + fireEvent.click(screen.getByText('Browser Family')); + + expect(screen.queryByText('Firefox')).toBeTruthy(); + fireEvent.input(screen.getByRole('searchbox'), { target: { value: 'ch' } }); expect(screen.queryByText('Firefox')).toBeFalsy(); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx index 84c326f62f89d..693b79c6dc831 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx @@ -6,7 +6,14 @@ */ import React, { useState, Fragment } from 'react'; -import { EuiFieldSearch, EuiSpacer, EuiButtonEmpty, EuiFilterGroup, EuiText } from '@elastic/eui'; +import { + EuiFieldSearch, + EuiSpacer, + EuiFilterGroup, + EuiText, + EuiPopover, + EuiFilterButton, +} from '@elastic/eui'; import styled from 'styled-components'; import { rgba } from 'polished'; import { i18n } from '@kbn/i18n'; @@ -14,8 +21,7 @@ import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; import { map } from 'lodash'; import { ExistsFilter, isExistsFilter } from '@kbn/es-query'; import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { SeriesConfig, UrlFilter } from '../../types'; +import { SeriesConfig, SeriesUrl, UrlFilter } from '../../types'; import { FilterValueButton } from './filter_value_btn'; import { useValuesList } from '../../../../../hooks/use_values_list'; import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; @@ -23,31 +29,33 @@ import { ESFilter } from '../../../../../../../../../src/core/types/elasticsearc import { PersistableFilter } from '../../../../../../../lens/common'; interface Props { - seriesId: string; + seriesId: number; + series: SeriesUrl; label: string; field: string; isNegated?: boolean; - goBack: () => void; nestedField?: string; filters: SeriesConfig['baseFilters']; } +export interface NestedFilterOpen { + value: string; + negate: boolean; +} + export function FilterExpanded({ seriesId, + series, field, label, - goBack, nestedField, isNegated, filters: defaultFilters, }: Props) { const [value, setValue] = useState(''); - const [isOpen, setIsOpen] = useState({ value: '', negate: false }); - - const { getSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); + const [isOpen, setIsOpen] = useState(false); + const [isNestedOpen, setIsNestedOpen] = useState({ value: '', negate: false }); const queryFilters: ESFilter[] = []; @@ -80,62 +88,71 @@ export function FilterExpanded({ ); return ( - - goBack()}> - {label} - - { - setValue(evt.target.value); - }} - placeholder={i18n.translate('xpack.observability.filters.expanded.search', { - defaultMessage: 'Search for {label}', - values: { label }, - })} - /> - - - {displayValues.length === 0 && !loading && ( - - {i18n.translate('xpack.observability.filters.expanded.noFilter', { - defaultMessage: 'No filters found.', - })} - - )} - {displayValues.map((opt) => ( - - - {isNegated !== false && ( + setIsOpen((prevState) => !prevState)} iconType="arrowDown"> + {label} + + } + isOpen={isOpen} + closePopover={() => setIsOpen(false)} + > + + { + setValue(evt.target.value); + }} + placeholder={i18n.translate('xpack.observability.filters.expanded.search', { + defaultMessage: 'Search for {label}', + values: { label }, + })} + /> + + + {displayValues.length === 0 && !loading && ( + + {i18n.translate('xpack.observability.filters.expanded.noFilter', { + defaultMessage: 'No filters found.', + })} + + )} + {displayValues.map((opt) => ( + + + {isNegated !== false && ( + + )} - )} - - - - - ))} - - + + + + ))} + + + ); } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.test.tsx index a9609abc70d69..764a27fd663f5 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { fireEvent, screen, waitFor } from '@testing-library/react'; import { FilterValueButton } from './filter_value_btn'; -import { mockUseSeriesFilter, mockUseValuesList, render } from '../../rtl_helpers'; +import { mockUxSeries, mockUseSeriesFilter, mockUseValuesList, render } from '../../rtl_helpers'; import { USER_AGENT_NAME, USER_AGENT_VERSION, @@ -19,84 +19,98 @@ describe('FilterValueButton', function () { render( ); - screen.getByText('Chrome'); + await waitFor(() => { + expect(screen.getByText('Chrome')).toBeInTheDocument(); + }); }); - it('should render display negate state', async function () { - render( - - ); + describe('when negate is true', () => { + it('displays negate stats', async () => { + render( + + ); - await waitFor(() => { - screen.getByText('Not Chrome'); - screen.getByTitle('Not Chrome'); - const btn = screen.getByRole('button'); - expect(btn.classList).toContain('euiButtonEmpty--danger'); + await waitFor(() => { + expect(screen.getByText('Not Chrome')).toBeInTheDocument(); + expect(screen.getByTitle('Not Chrome')).toBeInTheDocument(); + const btn = screen.getByRole('button'); + expect(btn.classList).toContain('euiButtonEmpty--danger'); + }); }); - }); - it('should call set filter on click', async function () { - const { setFilter, removeFilter } = mockUseSeriesFilter(); + it('calls setFilter on click', async () => { + const { setFilter, removeFilter } = mockUseSeriesFilter(); - render( - - ); + render( + + ); - await waitFor(() => { fireEvent.click(screen.getByText('Not Chrome')); - expect(removeFilter).toHaveBeenCalledTimes(0); - expect(setFilter).toHaveBeenCalledTimes(1); - expect(setFilter).toHaveBeenCalledWith({ - field: 'user_agent.name', - negate: true, - value: 'Chrome', + + await waitFor(() => { + expect(removeFilter).toHaveBeenCalledTimes(0); + expect(setFilter).toHaveBeenCalledTimes(1); + + expect(setFilter).toHaveBeenCalledWith({ + field: 'user_agent.name', + negate: true, + value: 'Chrome', + }); }); }); }); - it('should remove filter on click if already selected', async function () { - const { removeFilter } = mockUseSeriesFilter(); + describe('when selected', () => { + it('removes the filter on click', async () => { + const { removeFilter } = mockUseSeriesFilter(); + + render( + + ); - render( - - ); - await waitFor(() => { fireEvent.click(screen.getByText('Chrome')); - expect(removeFilter).toHaveBeenCalledWith({ - field: 'user_agent.name', - negate: false, - value: 'Chrome', + + await waitFor(() => { + expect(removeFilter).toHaveBeenCalledWith({ + field: 'user_agent.name', + negate: false, + value: 'Chrome', + }); }); }); }); @@ -107,12 +121,13 @@ describe('FilterValueButton', function () { render( ); @@ -134,13 +149,14 @@ describe('FilterValueButton', function () { render( ); @@ -167,13 +183,14 @@ describe('FilterValueButton', function () { render( ); @@ -203,13 +220,14 @@ describe('FilterValueButton', function () { render( ); @@ -229,13 +247,14 @@ describe('FilterValueButton', function () { render( ); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx index bf4ca6eb83d94..11f29c0233ef5 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx @@ -5,13 +5,15 @@ * 2.0. */ import { i18n } from '@kbn/i18n'; + import React, { useMemo } from 'react'; import { EuiFilterButton, hexToRgb } from '@elastic/eui'; import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; import { useSeriesFilters } from '../../hooks/use_series_filters'; import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; import FieldValueSuggestions from '../../../field_value_suggestions'; +import { SeriesUrl } from '../../types'; +import { NestedFilterOpen } from './filter_expanded'; interface Props { value: string; @@ -19,12 +21,13 @@ interface Props { allSelectedValues?: string[]; negate: boolean; nestedField?: string; - seriesId: string; + seriesId: number; + series: SeriesUrl; isNestedOpen: { value: string; negate: boolean; }; - setIsNestedOpen: (val: { value: string; negate: boolean }) => void; + setIsNestedOpen: (val: NestedFilterOpen) => void; } export function FilterValueButton({ @@ -34,16 +37,13 @@ export function FilterValueButton({ field, negate, seriesId, + series, nestedField, allSelectedValues, }: Props) { - const { getSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); - const { indexPatterns } = useAppIndexPatternContext(series.dataType); - const { setFilter, removeFilter } = useSeriesFilters({ seriesId }); + const { setFilter, removeFilter } = useSeriesFilters({ seriesId, series }); const hasActiveFilters = (allSelectedValues ?? []).includes(value); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx new file mode 100644 index 0000000000000..4e1c385921908 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { isEmpty } from 'lodash'; +import { i18n } from '@kbn/i18n'; +import { EuiBadge } from '@elastic/eui'; +import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; +import { SeriesConfig, SeriesUrl } from '../../types'; + +interface Props { + series: SeriesUrl; + seriesConfig?: SeriesConfig; +} + +export function IncompleteBadge({ seriesConfig, series }: Props) { + const { loading } = useAppIndexPatternContext(); + + if (!seriesConfig) { + return null; + } + const { dataType, reportDefinitions, selectedMetricField } = series; + const { definitionFields, labels } = seriesConfig; + const isIncomplete = + (!dataType || isEmpty(reportDefinitions) || !selectedMetricField) && !loading; + + const incompleteDefinition = isEmpty(reportDefinitions) + ? i18n.translate('xpack.observability.overview.exploratoryView.missingReportDefinition', { + defaultMessage: 'Missing {reportDefinition}', + values: { reportDefinition: labels?.[definitionFields[0]] }, + }) + : ''; + + let incompleteMessage = !selectedMetricField ? MISSING_REPORT_METRIC_LABEL : incompleteDefinition; + + if (!dataType) { + incompleteMessage = MISSING_DATA_TYPE_LABEL; + } + + if (!isIncomplete) { + return null; + } + + return {incompleteMessage}; +} + +const MISSING_REPORT_METRIC_LABEL = i18n.translate( + 'xpack.observability.overview.exploratoryView.missingReportMetric', + { + defaultMessage: 'Missing report metric', + } +); + +const MISSING_DATA_TYPE_LABEL = i18n.translate( + 'xpack.observability.overview.exploratoryView.missingDataType', + { + defaultMessage: 'Missing data type', + } +); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/operation_type_select.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.test.tsx similarity index 69% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/operation_type_select.test.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.test.tsx index 516f04e3812ba..ced4d3af057ff 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/operation_type_select.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.test.tsx @@ -7,62 +7,66 @@ import React from 'react'; import { fireEvent, screen } from '@testing-library/react'; -import { render } from '../../rtl_helpers'; +import { mockUxSeries, render } from '../../rtl_helpers'; import { OperationTypeSelect } from './operation_type_select'; describe('OperationTypeSelect', function () { it('should render properly', function () { - render(); + render(); screen.getByText('Select an option: , is selected'); }); it('should display selected value', function () { const initSeries = { - data: { - 'performance-distribution': { + data: [ + { + name: 'performance-distribution', dataType: 'ux' as const, - reportType: 'kpi-over-time' as const, operationType: 'median' as const, time: { from: 'now-15m', to: 'now' }, }, - }, + ], }; - render(, { initSeries }); + render(, { + initSeries, + }); screen.getByText('Median'); }); it('should call set series on change', function () { const initSeries = { - data: { - 'series-id': { + data: [ + { + name: 'performance-distribution', dataType: 'ux' as const, - reportType: 'kpi-over-time' as const, operationType: 'median' as const, time: { from: 'now-15m', to: 'now' }, }, - }, + ], }; - const { setSeries } = render(, { initSeries }); + const { setSeries } = render(, { + initSeries, + }); fireEvent.click(screen.getByTestId('operationTypeSelect')); - expect(setSeries).toHaveBeenCalledWith('series-id', { + expect(setSeries).toHaveBeenCalledWith(0, { operationType: 'median', dataType: 'ux', - reportType: 'kpi-over-time', time: { from: 'now-15m', to: 'now' }, + name: 'performance-distribution', }); fireEvent.click(screen.getByText('95th Percentile')); - expect(setSeries).toHaveBeenCalledWith('series-id', { + expect(setSeries).toHaveBeenCalledWith(0, { operationType: '95th', dataType: 'ux', - reportType: 'kpi-over-time', time: { from: 'now-15m', to: 'now' }, + name: 'performance-distribution', }); }); }); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/operation_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.tsx similarity index 91% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/operation_type_select.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.tsx index fce1383f30f34..4c10c9311704d 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/operation_type_select.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.tsx @@ -11,17 +11,18 @@ import { EuiSuperSelect } from '@elastic/eui'; import { useSeriesStorage } from '../../hooks/use_series_storage'; import { OperationType } from '../../../../../../../lens/public'; +import { SeriesUrl } from '../../types'; export function OperationTypeSelect({ seriesId, + series, defaultOperationType, }: { - seriesId: string; + seriesId: number; + series: SeriesUrl; defaultOperationType?: OperationType; }) { - const { getSeries, setSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); + const { setSeries } = useSeriesStorage(); const operationType = series?.operationType; @@ -83,11 +84,7 @@ export function OperationTypeSelect({ return ( { removeSeries(seriesId); }; + + const isDisabled = seriesId === 0 && allSeries.length > 1; + return ( - + + + ); } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_col.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.test.tsx similarity index 65% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_col.test.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.test.tsx index 3d156e0ee9c2b..544a294e021e2 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_col.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.test.tsx @@ -12,14 +12,14 @@ import { mockAppIndexPattern, mockIndexPattern, mockUseValuesList, + mockUxSeries, render, } from '../../rtl_helpers'; import { ReportDefinitionCol } from './report_definition_col'; -import { SERVICE_NAME } from '../../configurations/constants/elasticsearch_fieldnames'; describe('Series Builder ReportDefinitionCol', function () { mockAppIndexPattern(); - const seriesId = 'test-series-id'; + const seriesId = 0; const seriesConfig = getDefaultConfigs({ reportType: 'data-distribution', @@ -27,36 +27,24 @@ describe('Series Builder ReportDefinitionCol', function () { dataType: 'ux', }); - const initSeries = { - data: { - [seriesId]: { - dataType: 'ux' as const, - reportType: 'data-distribution' as const, - time: { from: 'now-30d', to: 'now' }, - reportDefinitions: { [SERVICE_NAME]: ['elastic-co'] }, - }, - }, - }; - mockUseValuesList([{ label: 'elastic-co', count: 10 }]); - it('should render properly', async function () { - render(, { - initSeries, - }); + it('renders', async () => { + render( + + ); await waitFor(() => { - screen.getByText('Web Application'); - screen.getByText('Environment'); - screen.getByText('Select an option: Page load time, is selected'); - screen.getByText('Page load time'); + expect(screen.getByText('Web Application')).toBeInTheDocument(); + expect(screen.getByText('Environment')).toBeInTheDocument(); + expect(screen.getByText('Search Environment')).toBeInTheDocument(); }); }); it('should render selected report definitions', async function () { - render(, { - initSeries, - }); + render( + + ); expect(await screen.findByText('elastic-co')).toBeInTheDocument(); @@ -65,8 +53,7 @@ describe('Series Builder ReportDefinitionCol', function () { it('should be able to remove selected definition', async function () { const { setSeries } = render( - , - { initSeries } + ); expect( @@ -80,11 +67,14 @@ describe('Series Builder ReportDefinitionCol', function () { fireEvent.click(removeBtn); expect(setSeries).toHaveBeenCalledTimes(1); + expect(setSeries).toHaveBeenCalledWith(seriesId, { dataType: 'ux', + name: 'performance-distribution', + breakdown: 'user_agent.name', reportDefinitions: {}, - reportType: 'data-distribution', - time: { from: 'now-30d', to: 'now' }, + selectedMetricField: 'transaction.duration.us', + time: { from: 'now-15m', to: 'now' }, }); }); }); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.tsx new file mode 100644 index 0000000000000..fbd7c34303d94 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.tsx @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { useSeriesStorage } from '../../hooks/use_series_storage'; +import { SeriesConfig, SeriesUrl } from '../../types'; +import { ReportDefinitionField } from './report_definition_field'; + +export function ReportDefinitionCol({ + seriesId, + series, + seriesConfig, +}: { + seriesId: number; + series: SeriesUrl; + seriesConfig: SeriesConfig; +}) { + const { setSeries } = useSeriesStorage(); + + const { reportDefinitions: selectedReportDefinitions = {} } = series; + + const { definitionFields } = seriesConfig; + + const onChange = (field: string, value?: string[]) => { + if (!value?.[0]) { + delete selectedReportDefinitions[field]; + setSeries(seriesId, { + ...series, + reportDefinitions: { ...selectedReportDefinitions }, + }); + } else { + setSeries(seriesId, { + ...series, + reportDefinitions: { ...selectedReportDefinitions, [field]: value }, + }); + } + }; + + return ( + + {definitionFields.map((field) => ( + + + + ))} + + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_field.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx similarity index 69% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_field.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx index 8a83b5c2a8cb0..3651b4b7f075b 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_builder/columns/report_definition_field.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx @@ -6,30 +6,25 @@ */ import React, { useMemo } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { isEmpty } from 'lodash'; import { ExistsFilter } from '@kbn/es-query'; import FieldValueSuggestions from '../../../field_value_suggestions'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; import { ESFilter } from '../../../../../../../../../src/core/types/elasticsearch'; import { PersistableFilter } from '../../../../../../../lens/common'; import { buildPhrasesFilter } from '../../configurations/utils'; -import { SeriesConfig } from '../../types'; +import { SeriesConfig, SeriesUrl } from '../../types'; import { ALL_VALUES_SELECTED } from '../../../field_value_suggestions/field_value_combobox'; interface Props { - seriesId: string; + seriesId: number; + series: SeriesUrl; field: string; seriesConfig: SeriesConfig; onChange: (field: string, value?: string[]) => void; } -export function ReportDefinitionField({ seriesId, field, seriesConfig, onChange }: Props) { - const { getSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); - +export function ReportDefinitionField({ series, field, seriesConfig, onChange }: Props) { const { indexPattern } = useAppIndexPatternContext(series.dataType); const { reportDefinitions: selectedReportDefinitions = {} } = series; @@ -64,23 +59,26 @@ export function ReportDefinitionField({ seriesId, field, seriesConfig, onChange // eslint-disable-next-line react-hooks/exhaustive-deps }, [JSON.stringify(selectedReportDefinitions), JSON.stringify(baseFilters)]); + if (!indexPattern) { + return null; + } + return ( - - - {indexPattern && ( - onChange(field, val)} - filters={queryFilters} - time={series.time} - fullWidth={true} - allowAllValuesSelection={true} - /> - )} - - + onChange(field, val)} + filters={queryFilters} + time={series.time} + fullWidth={true} + asCombobox={true} + allowExclusions={false} + allowAllValuesSelection={true} + usePrependLabel={false} + compressed={false} + required={isEmpty(selectedReportDefinitions)} + /> ); } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_type_select.tsx new file mode 100644 index 0000000000000..31a8c7cb7bfae --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_type_select.tsx @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiSuperSelect } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useSeriesStorage } from '../../hooks/use_series_storage'; +import { ReportViewType } from '../../types'; +import { + CORE_WEB_VITALS_LABEL, + DEVICE_DISTRIBUTION_LABEL, + KPI_OVER_TIME_LABEL, + PERF_DIST_LABEL, +} from '../../configurations/constants/labels'; + +const SELECT_REPORT_TYPE = 'SELECT_REPORT_TYPE'; + +export const reportTypesList: Array<{ + reportType: ReportViewType | typeof SELECT_REPORT_TYPE; + label: string; +}> = [ + { + reportType: SELECT_REPORT_TYPE, + label: i18n.translate('xpack.observability.expView.reportType.selectLabel', { + defaultMessage: 'Select report type', + }), + }, + { reportType: 'kpi-over-time', label: KPI_OVER_TIME_LABEL }, + { reportType: 'data-distribution', label: PERF_DIST_LABEL }, + { reportType: 'core-web-vitals', label: CORE_WEB_VITALS_LABEL }, + { reportType: 'device-data-distribution', label: DEVICE_DISTRIBUTION_LABEL }, +]; + +export function ReportTypesSelect() { + const { setReportType, reportType: selectedReportType, allSeries } = useSeriesStorage(); + + const onReportTypeChange = (reportType: ReportViewType) => { + setReportType(reportType); + }; + + const options = reportTypesList + .filter(({ reportType }) => (selectedReportType ? reportType !== SELECT_REPORT_TYPE : true)) + .map(({ reportType, label }) => ({ + value: reportType, + inputDisplay: reportType === SELECT_REPORT_TYPE ? label : {label}, + dropdownDisplay: label, + })); + + return ( + onReportTypeChange(value as ReportViewType)} + style={{ minWidth: 200 }} + isInvalid={!selectedReportType && allSeries.length > 0} + disabled={allSeries.length > 0} + /> + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/selected_filters.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.test.tsx similarity index 59% rename from x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/selected_filters.test.tsx rename to x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.test.tsx index eb76772a66c7e..64291f84f7662 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/selected_filters.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.test.tsx @@ -7,10 +7,10 @@ import React from 'react'; import { screen, waitFor } from '@testing-library/react'; -import { mockAppIndexPattern, mockIndexPattern, render } from '../rtl_helpers'; +import { mockAppIndexPattern, mockIndexPattern, mockUxSeries, render } from '../../rtl_helpers'; import { SelectedFilters } from './selected_filters'; -import { getDefaultConfigs } from '../configurations/default_configs'; -import { USER_AGENT_NAME } from '../configurations/constants/elasticsearch_fieldnames'; +import { getDefaultConfigs } from '../../configurations/default_configs'; +import { USER_AGENT_NAME } from '../../configurations/constants/elasticsearch_fieldnames'; describe('SelectedFilters', function () { mockAppIndexPattern(); @@ -22,11 +22,19 @@ describe('SelectedFilters', function () { }); it('should render properly', async function () { - const initSeries = { filters: [{ field: USER_AGENT_NAME, values: ['Chrome'] }] }; + const filters = [{ field: USER_AGENT_NAME, values: ['Chrome'] }]; + const initSeries = { filters }; - render(, { - initSeries, - }); + render( + , + { + initSeries, + } + ); await waitFor(() => { screen.getByText('Chrome'); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.tsx new file mode 100644 index 0000000000000..3327ecf1fc9b6 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.tsx @@ -0,0 +1,101 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { Fragment } from 'react'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FilterLabel } from '../../components/filter_label'; +import { SeriesConfig, SeriesUrl, UrlFilter } from '../../types'; +import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; +import { useSeriesFilters } from '../../hooks/use_series_filters'; +import { useSeriesStorage } from '../../hooks/use_series_storage'; + +interface Props { + seriesId: number; + series: SeriesUrl; + seriesConfig: SeriesConfig; +} +export function SelectedFilters({ seriesId, series, seriesConfig }: Props) { + const { setSeries } = useSeriesStorage(); + + const { labels } = seriesConfig; + + const filters: UrlFilter[] = series.filters ?? []; + + const { removeFilter } = useSeriesFilters({ seriesId, series }); + + const { indexPattern } = useAppIndexPatternContext(series.dataType); + + if (filters.length === 0 || !indexPattern) { + return null; + } + + return ( + <> + + {filters.map(({ field, values, notValues }) => ( + + {(values ?? []).length > 0 && ( + + { + values?.forEach((val) => { + removeFilter({ field, value: val, negate: false }); + }); + }} + negate={false} + indexPattern={indexPattern} + /> + + )} + {(notValues ?? []).length > 0 && ( + + { + values?.forEach((val) => { + removeFilter({ field, value: val, negate: false }); + }); + }} + indexPattern={indexPattern} + /> + + )} + + ))} + + {(series.filters ?? []).length > 0 && ( + + { + setSeries(seriesId, { ...series, filters: undefined }); + }} + size="xs" + > + {i18n.translate('xpack.observability.expView.seriesEditor.clearFilter', { + defaultMessage: 'Clear filters', + })} + + + )} + + + + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx index 51ebe6c6bd9d5..37b5b1571f84d 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx @@ -6,98 +6,113 @@ */ import React from 'react'; -import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { isEmpty } from 'lodash'; import { RemoveSeries } from './remove_series'; import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { SeriesUrl } from '../../types'; +import { SeriesConfig, SeriesUrl } from '../../types'; +import { useDiscoverLink } from '../../hooks/use_discover_link'; interface Props { - seriesId: string; - editorMode?: boolean; + seriesId: number; + series: SeriesUrl; + seriesConfig?: SeriesConfig; + onEditClick?: () => void; } -export function SeriesActions({ seriesId, editorMode = false }: Props) { - const { getSeries, setSeries, allSeriesIds, removeSeries } = useSeriesStorage(); - const series = getSeries(seriesId); - const onEdit = () => { - setSeries(seriesId, { ...series, isNew: true }); - }; +export function SeriesActions({ seriesId, series, seriesConfig, onEditClick }: Props) { + const { setSeries, allSeries } = useSeriesStorage(); + + const { href: discoverHref } = useDiscoverLink({ series, seriesConfig }); const copySeries = () => { - let copySeriesId: string = `${seriesId}-copy`; - if (allSeriesIds.includes(copySeriesId)) { - copySeriesId = copySeriesId + allSeriesIds.length; + let copySeriesId: string = `${series.name}-copy`; + if (allSeries.find(({ name }) => name === copySeriesId)) { + copySeriesId = copySeriesId + allSeries.length; } - setSeries(copySeriesId, series); + setSeries(allSeries.length, { ...series, name: copySeriesId }); }; - const { reportType, reportDefinitions, isNew, ...restSeries } = series; - const isSaveAble = reportType && !isEmpty(reportDefinitions); - - const saveSeries = () => { - if (isSaveAble) { - const reportDefId = Object.values(reportDefinitions ?? {})[0]; - let newSeriesId = `${reportDefId}-${reportType}`; - - if (allSeriesIds.includes(newSeriesId)) { - newSeriesId = `${newSeriesId}-${allSeriesIds.length}`; - } - const newSeriesN: SeriesUrl = { - ...restSeries, - reportType, - reportDefinitions, - }; - - setSeries(newSeriesId, newSeriesN); - removeSeries(seriesId); + const toggleSeries = () => { + if (series.hidden) { + setSeries(seriesId, { ...series, hidden: undefined }); + } else { + setSeries(seriesId, { ...series, hidden: true }); } }; return ( - - {!editorMode && ( - + + + + + + + + - - )} - {editorMode && ( - + + + + + - - )} - {editorMode && ( - + + + + + - - )} + + ); } + +const EDIT_SERIES_LABEL = i18n.translate('xpack.observability.seriesEditor.edit', { + defaultMessage: 'Edit series', +}); + +const HIDE_SERIES_LABEL = i18n.translate('xpack.observability.seriesEditor.hide', { + defaultMessage: 'Hide series', +}); + +const COPY_SERIES_LABEL = i18n.translate('xpack.observability.seriesEditor.clone', { + defaultMessage: 'Copy series', +}); + +const VIEW_SAMPLE_DOCUMENTS_LABEL = i18n.translate( + 'xpack.observability.seriesEditor.sampleDocuments', + { + defaultMessage: 'View sample documents in new tab', + } +); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_filter.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_filter.tsx index 02144c6929b38..5b576d9da0172 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_filter.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_filter.tsx @@ -5,29 +5,17 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; -import React, { useState, Fragment } from 'react'; -import { - EuiButton, - EuiPopover, - EuiSpacer, - EuiButtonEmpty, - EuiFlexItem, - EuiFlexGroup, -} from '@elastic/eui'; +import React from 'react'; +import { EuiFilterGroup, EuiSpacer } from '@elastic/eui'; import { FilterExpanded } from './filter_expanded'; -import { SeriesConfig } from '../../types'; +import { SeriesConfig, SeriesUrl } from '../../types'; import { FieldLabels } from '../../configurations/constants/constants'; -import { SelectedFilters } from '../selected_filters'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; +import { SelectedFilters } from './selected_filters'; interface Props { - seriesId: string; - filterFields: SeriesConfig['filterFields']; - baseFilters: SeriesConfig['baseFilters']; + seriesId: number; seriesConfig: SeriesConfig; - isNew?: boolean; - labels?: Record; + series: SeriesUrl; } export interface Field { @@ -37,119 +25,38 @@ export interface Field { isNegated?: boolean; } -export function SeriesFilter({ - seriesConfig, - isNew, - seriesId, - filterFields = [], - baseFilters, - labels, -}: Props) { - const [isPopoverVisible, setIsPopoverVisible] = useState(false); - - const [selectedField, setSelectedField] = useState(); - - const options: Field[] = filterFields.map((field) => { +export function SeriesFilter({ series, seriesConfig, seriesId }: Props) { + const options: Field[] = seriesConfig.filterFields.map((field) => { if (typeof field === 'string') { - return { label: labels?.[field] ?? FieldLabels[field], field }; + return { label: seriesConfig.labels?.[field] ?? FieldLabels[field], field }; } return { field: field.field, nested: field.nested, isNegated: field.isNegated, - label: labels?.[field.field] ?? FieldLabels[field.field], + label: seriesConfig.labels?.[field.field] ?? FieldLabels[field.field], }; }); - const { setSeries, getSeries } = useSeriesStorage(); - const urlSeries = getSeries(seriesId); - - const button = ( - { - setIsPopoverVisible((prevState) => !prevState); - }} - size="s" - > - {i18n.translate('xpack.observability.expView.seriesEditor.addFilter', { - defaultMessage: 'Add filter', - })} - - ); - - const mainPanel = ( + return ( <> + + {options.map((opt) => ( + + ))} + - {options.map((opt) => ( - - { - setSelectedField(opt); - }} - > - {opt.label} - - - - ))} + ); - - const childPanel = selectedField ? ( - { - setSelectedField(undefined); - }} - filters={baseFilters} - /> - ) : null; - - const closePopover = () => { - setIsPopoverVisible(false); - setSelectedField(undefined); - }; - - return ( - - - - - {!selectedField ? mainPanel : childPanel} - - - {(urlSeries.filters ?? []).length > 0 && ( - - { - setSeries(seriesId, { ...urlSeries, filters: undefined }); - }} - size="s" - > - {i18n.translate('xpack.observability.expView.seriesEditor.clearFilter', { - defaultMessage: 'Clear filters', - })} - - - )} - - ); } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_info.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_info.tsx new file mode 100644 index 0000000000000..4c2e57e780550 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_info.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { SeriesConfig, SeriesUrl } from '../../types'; +import { SeriesColorPicker } from '../../components/series_color_picker'; +import { SeriesChartTypes } from './chart_type_select'; + +interface Props { + seriesId: number; + series: SeriesUrl; + seriesConfig?: SeriesConfig; +} + +export function SeriesInfo({ seriesId, series, seriesConfig }: Props) { + if (!seriesConfig) { + return null; + } + + return ( + + + + + + + + + ); + + return null; +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.test.tsx new file mode 100644 index 0000000000000..ccad461209313 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.test.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { fireEvent, screen, waitFor } from '@testing-library/react'; +import { mockUxSeries, render } from '../../rtl_helpers'; +import { SeriesName } from './series_name'; + +describe.skip('SeriesChartTypesSelect', function () { + it('should render properly', async function () { + render(); + + expect(screen.getByText(mockUxSeries.name)).toBeInTheDocument(); + }); + + it('should display input when editing name', async function () { + render(); + + let input = screen.queryByLabelText(mockUxSeries.name); + + // read only + expect(input).not.toBeInTheDocument(); + + const editButton = screen.getByRole('button'); + // toggle editing + fireEvent.click(editButton); + + await waitFor(() => { + input = screen.getByLabelText(mockUxSeries.name); + + expect(input).toBeInTheDocument(); + }); + + // toggle readonly + fireEvent.click(editButton); + + await waitFor(() => { + input = screen.getByLabelText(mockUxSeries.name); + + expect(input).not.toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.tsx new file mode 100644 index 0000000000000..cff30a2b35059 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.tsx @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState, ChangeEvent, useEffect, useRef } from 'react'; +import styled from 'styled-components'; +import { i18n } from '@kbn/i18n'; +import { + EuiFieldText, + EuiText, + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiOutsideClickDetector, +} from '@elastic/eui'; +import { useSeriesStorage } from '../../hooks/use_series_storage'; +import { SeriesUrl } from '../../types'; + +interface Props { + seriesId: number; + series: SeriesUrl; +} + +export const StyledText = styled(EuiText)` + &.euiText.euiText--constrainedWidth { + max-width: 200px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } +`; + +export function SeriesName({ series, seriesId }: Props) { + const { setSeries } = useSeriesStorage(); + + const [value, setValue] = useState(series.name); + const [isEditingEnabled, setIsEditingEnabled] = useState(false); + const inputRef = useRef(null); + const buttonRef = useRef(null); + + const onChange = (e: ChangeEvent) => { + setValue(e.target.value); + }; + + const onSave = () => { + if (value !== series.name) { + setSeries(seriesId, { ...series, name: value }); + } + }; + + const onOutsideClick = (event: Event) => { + if (event.target !== buttonRef.current) { + setIsEditingEnabled(false); + } + }; + + useEffect(() => { + setValue(series.name); + }, [series.name]); + + useEffect(() => { + if (isEditingEnabled && inputRef.current) { + inputRef.current.focus(); + } + }, [isEditingEnabled, inputRef]); + + return ( + + {isEditingEnabled ? ( + + + + + + ) : ( + + {value} + + )} + + setIsEditingEnabled(!isEditingEnabled)} + iconType="pencil" + aria-label={i18n.translate('xpack.observability.expView.seriesEditor.editName', { + defaultMessage: 'Edit name', + })} + color="text" + buttonRef={buttonRef} + /> + + + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.tsx new file mode 100644 index 0000000000000..9f4de1b6dd519 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.tsx @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; + +import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiHorizontalRule } from '@elastic/eui'; +import { SeriesConfig, SeriesUrl } from '../types'; +import { ReportDefinitionCol } from './columns/report_definition_col'; +import { OperationTypeSelect } from './columns/operation_type_select'; +import { parseCustomFieldName } from '../configurations/lens_attributes'; +import { SeriesFilter } from './columns/series_filter'; +import { DatePickerCol } from './columns/date_picker_col'; +import { Breakdowns } from './columns/breakdowns'; + +function getColumnType(seriesConfig: SeriesConfig, selectedMetricField?: string) { + const { columnType } = parseCustomFieldName(seriesConfig, selectedMetricField); + + return columnType; +} + +interface Props { + seriesId: number; + series: SeriesUrl; + seriesConfig?: SeriesConfig; +} +export function ExpandedSeriesRow(seriesProps: Props) { + const { seriesConfig, series, seriesId } = seriesProps; + + if (!seriesConfig) { + return null; + } + + const { selectedMetricField } = series ?? {}; + + const { hasOperationType, yAxisColumns } = seriesConfig; + + const columnType = getColumnType(seriesConfig, selectedMetricField); + + return ( +
    + + + + + + + + + + + + + + + + + + + + + {(hasOperationType || columnType === 'operation') && ( + + + + + + )} + +
    + ); +} + +const BREAKDOWNS_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.breakdowns', { + defaultMessage: 'Breakdowns', +}); + +const FILTERS_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.selectFilters', { + defaultMessage: 'Filters', +}); + +const OPERATION_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.operation', { + defaultMessage: 'Operation', +}); + +const DATE_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.date', { + defaultMessage: 'Date', +}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx new file mode 100644 index 0000000000000..496e7a10f9c44 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { + EuiToolTip, + EuiPopover, + EuiButton, + EuiListGroup, + EuiListGroupItem, + EuiBadge, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { useSeriesStorage } from '../hooks/use_series_storage'; +import { SeriesConfig, SeriesUrl } from '../types'; +import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern'; +import { RECORDS_FIELD, RECORDS_PERCENTAGE_FIELD } from '../configurations/constants'; + +interface Props { + seriesId: number; + series: SeriesUrl; + defaultValue?: string; + seriesConfig?: SeriesConfig; +} + +export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) { + const { setSeries } = useSeriesStorage(); + const [showOptions, setShowOptions] = useState(false); + const metricOptions = seriesConfig?.metricOptions; + + const { indexPatterns } = useAppIndexPatternContext(); + + const onChange = (value?: string) => { + setSeries(seriesId, { + ...series, + selectedMetricField: value, + }); + }; + + if (!series.dataType) { + return null; + } + + const indexPattern = indexPatterns?.[series.dataType]; + + const options = (metricOptions ?? []).map(({ label, field, id }) => { + let disabled = false; + + if (field !== RECORDS_FIELD && field !== RECORDS_PERCENTAGE_FIELD && field) { + disabled = !Boolean(indexPattern?.getFieldByName(field)); + } + return { + disabled, + value: field || id, + dropdownDisplay: disabled ? ( + {field}, + }} + /> + } + > + {label} + + ) : ( + label + ), + inputDisplay: label, + }; + }); + + return ( + <> + {!series.selectedMetricField && ( + setShowOptions((prevState) => !prevState)} + fill + size="s" + > + {SELECT_REPORT_METRIC_LABEL} + + } + isOpen={showOptions} + closePopover={() => setShowOptions((prevState) => !prevState)} + > + + {options.map((option) => ( + onChange(option.value)} + label={option.dropdownDisplay} + isDisabled={option.disabled} + /> + ))} + + + )} + {series.selectedMetricField && ( + onChange(undefined)} + iconOnClickAriaLabel={REMOVE_REPORT_METRIC_LABEL} + > + { + seriesConfig?.metricOptions?.find((option) => option.id === series.selectedMetricField) + ?.label + } + + )} + + ); +} + +const SELECT_REPORT_METRIC_LABEL = i18n.translate( + 'xpack.observability.expView.seriesEditor.selectReportMetric', + { + defaultMessage: 'Select report metric', + } +); + +const REMOVE_REPORT_METRIC_LABEL = i18n.translate( + 'xpack.observability.expView.seriesEditor.removeReportMetric', + { + defaultMessage: 'Remove report metric', + } +); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/selected_filters.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/selected_filters.tsx deleted file mode 100644 index 5d2ce6ba84951..0000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/selected_filters.tsx +++ /dev/null @@ -1,101 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { Fragment } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { useSeriesStorage } from '../hooks/use_series_storage'; -import { FilterLabel } from '../components/filter_label'; -import { SeriesConfig, UrlFilter } from '../types'; -import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern'; -import { useSeriesFilters } from '../hooks/use_series_filters'; -import { getFiltersFromDefs } from '../hooks/use_lens_attributes'; - -interface Props { - seriesId: string; - seriesConfig: SeriesConfig; - isNew?: boolean; -} -export function SelectedFilters({ seriesId, isNew, seriesConfig }: Props) { - const { getSeries } = useSeriesStorage(); - - const series = getSeries(seriesId); - - const { reportDefinitions = {} } = series; - - const { labels } = seriesConfig; - - const filters: UrlFilter[] = series.filters ?? []; - - let definitionFilters: UrlFilter[] = getFiltersFromDefs(reportDefinitions); - - // we don't want to display report definition filters in new series view - if (isNew) { - definitionFilters = []; - } - - const { removeFilter } = useSeriesFilters({ seriesId }); - - const { indexPattern } = useAppIndexPatternContext(series.dataType); - - return (filters.length > 0 || definitionFilters.length > 0) && indexPattern ? ( - - - {filters.map(({ field, values, notValues }) => ( - - {(values ?? []).map((val) => ( - - removeFilter({ field, value: val, negate: false })} - negate={false} - indexPattern={indexPattern} - /> - - ))} - {(notValues ?? []).map((val) => ( - - removeFilter({ field, value: val, negate: true })} - indexPattern={indexPattern} - /> - - ))} - - ))} - - {definitionFilters.map(({ field, values }) => ( - - {(values ?? []).map((val) => ( - - { - // FIXME handle this use case - }} - negate={false} - definitionFilter={true} - indexPattern={indexPattern} - /> - - ))} - - ))} - - - ) : null; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series.tsx new file mode 100644 index 0000000000000..ea47ccd0b0426 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series.tsx @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import styled from 'styled-components'; +import { EuiFlexItem, EuiFlexGroup, EuiPanel, EuiAccordion, EuiSpacer } from '@elastic/eui'; +import { BuilderItem } from '../types'; +import { SeriesActions } from './columns/series_actions'; +import { SeriesInfo } from './columns/series_info'; +import { DataTypesSelect } from './columns/data_type_select'; +import { IncompleteBadge } from './columns/incomplete_badge'; +import { ExpandedSeriesRow } from './expanded_series_row'; +import { SeriesName } from './columns/series_name'; +import { ReportMetricOptions } from './report_metric_options'; + +const StyledAccordion = styled(EuiAccordion)` + .euiAccordion__button { + width: auto; + flex-grow: 0; + } + + .euiAccordion__optionalAction { + flex-grow: 1; + flex-shrink: 1; + } +`; + +interface Props { + item: BuilderItem; + isExpanded: boolean; + toggleExpanded: () => void; +} + +export function Series({ item, isExpanded, toggleExpanded }: Props) { + const { id } = item; + const seriesProps = { + ...item, + seriesId: id, + }; + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + > + + + + + + + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series_editor.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series_editor.tsx index c3cc8484d1751..d13857b5e9663 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series_editor.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series_editor.tsx @@ -5,134 +5,226 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiBasicTable, EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { SeriesFilter } from './columns/series_filter'; -import { SeriesConfig } from '../types'; -import { NEW_SERIES_KEY, useSeriesStorage } from '../hooks/use_series_storage'; +import { + EuiSpacer, + EuiFormRow, + EuiFlexItem, + EuiFlexGroup, + EuiButtonEmpty, + EuiHorizontalRule, +} from '@elastic/eui'; +import { rgba } from 'polished'; +import { euiStyled } from './../../../../../../../../src/plugins/kibana_react/common'; +import { AppDataType, ReportViewType, BuilderItem } from '../types'; +import { SeriesContextValue, useSeriesStorage } from '../hooks/use_series_storage'; +import { IndexPatternState, useAppIndexPatternContext } from '../hooks/use_app_index_pattern'; import { getDefaultConfigs } from '../configurations/default_configs'; -import { DatePickerCol } from './columns/date_picker_col'; -import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern'; -import { SeriesActions } from './columns/series_actions'; -import { ChartEditOptions } from './chart_edit_options'; +import { ReportTypesSelect } from './columns/report_type_select'; +import { ViewActions } from '../views/view_actions'; +import { Series } from './series'; -interface EditItem { - seriesConfig: SeriesConfig; +export interface ReportTypeItem { id: string; + reportType: ReportViewType; + label: string; } -export function SeriesEditor() { - const { allSeries, allSeriesIds } = useSeriesStorage(); - - const columns = [ - { - name: i18n.translate('xpack.observability.expView.seriesEditor.name', { - defaultMessage: 'Name', - }), - field: 'id', - width: '15%', - render: (seriesId: string) => ( - - {' '} - {seriesId === NEW_SERIES_KEY ? 'series-preview' : seriesId} - - ), - }, - { - name: i18n.translate('xpack.observability.expView.seriesEditor.filters', { - defaultMessage: 'Filters', - }), - field: 'defaultFilters', - width: '15%', - render: (seriesId: string, { seriesConfig, id }: EditItem) => ( - - ), - }, - { - name: i18n.translate('xpack.observability.expView.seriesEditor.breakdowns', { - defaultMessage: 'Breakdowns', - }), - field: 'id', - width: '25%', - render: (seriesId: string, { seriesConfig, id }: EditItem) => ( - - ), - }, - { - name: ( -
    - -
    - ), - width: '20%', - field: 'id', - align: 'right' as const, - render: (seriesId: string, item: EditItem) => , - }, - { - name: i18n.translate('xpack.observability.expView.seriesEditor.actions', { - defaultMessage: 'Actions', - }), - align: 'center' as const, - width: '10%', - field: 'id', - render: (seriesId: string, item: EditItem) => , - }, - ]; - - const { indexPatterns } = useAppIndexPatternContext(); - const items: EditItem[] = []; - - allSeriesIds.forEach((seriesKey) => { - const series = allSeries[seriesKey]; - if (series?.reportType && indexPatterns[series.dataType] && !series.isNew) { - items.push({ - id: seriesKey, - seriesConfig: getDefaultConfigs({ - indexPattern: indexPatterns[series.dataType], - reportType: series.reportType, - dataType: series.dataType, - }), +type ExpandedRowMap = Record; + +export const getSeriesToEdit = ({ + indexPatterns, + allSeries, + reportType, +}: { + allSeries: SeriesContextValue['allSeries']; + indexPatterns: IndexPatternState; + reportType: ReportViewType; +}): BuilderItem[] => { + const getDataViewSeries = (dataType: AppDataType) => { + if (indexPatterns?.[dataType]) { + return getDefaultConfigs({ + dataType, + reportType, + indexPattern: indexPatterns[dataType], }); } + }; + + return allSeries.map((series, seriesIndex) => { + const seriesConfig = getDataViewSeries(series.dataType)!; + + return { id: seriesIndex, series, seriesConfig }; }); +}; - if (items.length === 0 && allSeriesIds.length > 0) { - return null; - } +export const SeriesEditor = React.memo(function () { + const [editorItems, setEditorItems] = useState([]); + + const { getSeries, allSeries, reportType, removeSeries } = useSeriesStorage(); + + const { loading, indexPatterns } = useAppIndexPatternContext(); + + const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState>({}); + + const [{ prevCount, curCount }, setSeriesCount] = useState<{ + prevCount?: number; + curCount: number; + }>({ + curCount: allSeries.length, + }); + + useEffect(() => { + setSeriesCount((oldParams) => ({ prevCount: oldParams.curCount, curCount: allSeries.length })); + if (typeof prevCount !== 'undefined' && !isNaN(prevCount) && prevCount < curCount) { + setItemIdToExpandedRowMap({}); + } + }, [allSeries.length, curCount, prevCount]); + + useEffect(() => { + const newExpandRows: ExpandedRowMap = {}; + + setEditorItems((prevState) => { + const newEditorItems = getSeriesToEdit({ + reportType, + allSeries, + indexPatterns, + }); + + newEditorItems.forEach(({ series, id }) => { + const prevSeriesItem = prevState.find(({ id: prevId }) => prevId === id); + if ( + prevSeriesItem && + series.selectedMetricField && + prevSeriesItem.series.selectedMetricField !== series.selectedMetricField + ) { + newExpandRows[id] = true; + } + }); + return [...newEditorItems]; + }); + + setItemIdToExpandedRowMap((prevState) => { + return { ...prevState, ...newExpandRows }; + }); + }, [allSeries, getSeries, indexPatterns, loading, reportType]); + + const toggleDetails = (item: BuilderItem) => { + const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap }; + if (itemIdToExpandedRowMapValues[item.id]) { + delete itemIdToExpandedRowMapValues[item.id]; + } else { + itemIdToExpandedRowMapValues[item.id] = true; + } + setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); + }; + + const resetView = () => { + const totalSeries = allSeries.length; + for (let i = totalSeries; i >= 0; i--) { + removeSeries(i); + } + setEditorItems([]); + setItemIdToExpandedRowMap({}); + }; return ( - <> - - - - + +
    + + + + + + + {reportType && ( + + resetView()} color="text"> + {RESET_LABEL} + + + )} + + + + + + + {editorItems.map((item) => ( +
    + toggleDetails(item)} + isExpanded={itemIdToExpandedRowMap[item.id]} + /> + +
    + ))} + +
    +
    ); -} +}); + +const Wrapper = euiStyled.div` + &::-webkit-scrollbar { + height: ${({ theme }) => theme.eui.euiScrollBar}; + width: ${({ theme }) => theme.eui.euiScrollBar}; + } + &::-webkit-scrollbar-thumb { + background-clip: content-box; + background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; + border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; + } + &::-webkit-scrollbar-corner, + &::-webkit-scrollbar-track { + background-color: transparent; + } + + &&& { + .euiTableRow-isExpandedRow .euiTableRowCell { + border-top: none; + background-color: #FFFFFF; + border-bottom: 2px solid #d3dae6; + border-right: 2px solid rgb(211, 218, 230); + border-left: 2px solid rgb(211, 218, 230); + } + + .isExpanded { + border-right: 2px solid rgb(211, 218, 230); + border-left: 2px solid rgb(211, 218, 230); + .euiTableRowCell { + border-bottom: none; + } + } + .isIncomplete .euiTableRowCell { + background-color: rgba(254, 197, 20, 0.1); + } + } +`; + +export const LOADING_VIEW = i18n.translate( + 'xpack.observability.expView.seriesBuilder.loadingView', + { + defaultMessage: 'Loading view ...', + } +); + +export const SELECT_REPORT_TYPE = i18n.translate( + 'xpack.observability.expView.seriesBuilder.selectReportType', + { + defaultMessage: 'No report type selected', + } +); + +export const RESET_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.reset', { + defaultMessage: 'Reset', +}); + +export const REPORT_TYPE_LABEL = i18n.translate( + 'xpack.observability.expView.seriesBuilder.reportType', + { + defaultMessage: 'Report type', + } +); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts index 9817899412ce3..f3592a749a2c0 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts @@ -6,7 +6,7 @@ */ import { PaletteOutput } from 'src/plugins/charts/public'; -import { ExistsFilter } from '@kbn/es-query'; +import { ExistsFilter, PhraseFilter } from '@kbn/es-query'; import { LastValueIndexPatternColumn, DateHistogramIndexPatternColumn, @@ -42,7 +42,7 @@ export interface MetricOption { field?: string; label: string; description?: string; - columnType?: 'range' | 'operation' | 'FILTER_RECORDS' | 'TERMS_COLUMN'; + columnType?: 'range' | 'operation' | 'FILTER_RECORDS' | 'TERMS_COLUMN' | 'unique_count'; columnFilters?: ColumnFilter[]; timeScale?: string; } @@ -55,7 +55,7 @@ export interface SeriesConfig { defaultSeriesType: SeriesType; filterFields: Array; seriesTypes: SeriesType[]; - baseFilters?: PersistableFilter[] | ExistsFilter[]; + baseFilters?: Array; definitionFields: string[]; metricOptions?: MetricOption[]; labels: Record; @@ -69,6 +69,7 @@ export interface SeriesConfig { export type URLReportDefinition = Record; export interface SeriesUrl { + name: string; time: { to: string; from: string; @@ -76,12 +77,12 @@ export interface SeriesUrl { breakdown?: string; filters?: UrlFilter[]; seriesType?: SeriesType; - reportType: ReportViewType; operationType?: OperationType; dataType: AppDataType; reportDefinitions?: URLReportDefinition; selectedMetricField?: string; - isNew?: boolean; + hidden?: boolean; + color?: string; } export interface UrlFilter { @@ -116,3 +117,9 @@ export interface FieldFormat { params: FieldFormatParams; }; } + +export interface BuilderItem { + id: number; + series: SeriesUrl; + seriesConfig?: SeriesConfig; +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.test.tsx new file mode 100644 index 0000000000000..978296a295efc --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.test.tsx @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { screen, waitFor, fireEvent } from '@testing-library/dom'; +import { render } from '../rtl_helpers'; +import { AddSeriesButton } from './add_series_button'; +import { DEFAULT_TIME, ReportTypes } from '../configurations/constants'; +import * as hooks from '../hooks/use_series_storage'; + +const setSeries = jest.fn(); + +describe('AddSeriesButton', () => { + beforeEach(() => { + jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ + ...jest.requireActual('../hooks/use_series_storage'), + allSeries: [], + setSeries, + reportType: ReportTypes.KPI, + }); + setSeries.mockClear(); + }); + + it('renders AddSeriesButton', async () => { + render(); + + expect(screen.getByText(/Add series/i)).toBeInTheDocument(); + }); + + it('calls setSeries when AddSeries Button is clicked', async () => { + const { rerender } = render(); + let addSeriesButton = screen.getByText(/Add series/i); + + fireEvent.click(addSeriesButton); + + await waitFor(() => { + expect(setSeries).toBeCalledTimes(1); + expect(setSeries).toBeCalledWith(0, { name: 'new-series-1', time: DEFAULT_TIME }); + }); + + jest.clearAllMocks(); + jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ + ...jest.requireActual('../hooks/use_series_storage'), + allSeries: new Array(1), + setSeries, + reportType: ReportTypes.KPI, + }); + + rerender(); + + addSeriesButton = screen.getByText(/Add series/i); + + fireEvent.click(addSeriesButton); + + await waitFor(() => { + expect(setSeries).toBeCalledTimes(1); + expect(setSeries).toBeCalledWith(1, { name: 'new-series-2', time: DEFAULT_TIME }); + }); + }); + + it.each([ReportTypes.DEVICE_DISTRIBUTION, ReportTypes.CORE_WEB_VITAL])( + 'does not allow adding more than 1 series for core web vitals or device distribution', + async (reportType) => { + jest.clearAllMocks(); + jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ + ...jest.requireActual('../hooks/use_series_storage'), + allSeries: new Array(1), // mock array of length 1 + setSeries, + reportType, + }); + + render(); + const addSeriesButton = screen.getByText(/Add series/i); + expect(addSeriesButton.closest('button')).toBeDisabled(); + + fireEvent.click(addSeriesButton); + + await waitFor(() => { + expect(setSeries).toBeCalledTimes(0); + }); + } + ); + + it('does not allow adding a series when the report type is undefined', async () => { + jest.clearAllMocks(); + jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ + ...jest.requireActual('../hooks/use_series_storage'), + allSeries: [], + setSeries, + }); + + render(); + const addSeriesButton = screen.getByText(/Add series/i); + expect(addSeriesButton.closest('button')).toBeDisabled(); + + fireEvent.click(addSeriesButton); + + await waitFor(() => { + expect(setSeries).toBeCalledTimes(0); + }); + }); +}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx new file mode 100644 index 0000000000000..71b16c9c0e682 --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useState } from 'react'; + +import { EuiToolTip, EuiButton } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { SeriesUrl, BuilderItem } from '../types'; +import { getSeriesToEdit } from '../series_editor/series_editor'; +import { NEW_SERIES_KEY, useSeriesStorage } from '../hooks/use_series_storage'; +import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern'; +import { DEFAULT_TIME, ReportTypes } from '../configurations/constants'; + +export function AddSeriesButton() { + const [editorItems, setEditorItems] = useState([]); + const { getSeries, allSeries, setSeries, reportType } = useSeriesStorage(); + + const { loading, indexPatterns } = useAppIndexPatternContext(); + + useEffect(() => { + setEditorItems(getSeriesToEdit({ allSeries, indexPatterns, reportType })); + }, [allSeries, getSeries, indexPatterns, loading, reportType]); + + const addSeries = () => { + const prevSeries = allSeries?.[0]; + const name = `${NEW_SERIES_KEY}-${editorItems.length + 1}`; + const nextSeries = { name } as SeriesUrl; + + const nextSeriesId = allSeries.length; + + if (reportType === 'data-distribution') { + setSeries(nextSeriesId, { + ...nextSeries, + time: prevSeries?.time || DEFAULT_TIME, + } as SeriesUrl); + } else { + setSeries( + nextSeriesId, + prevSeries ? nextSeries : ({ ...nextSeries, time: DEFAULT_TIME } as SeriesUrl) + ); + } + }; + + const isAddDisabled = + !reportType || + ((reportType === ReportTypes.CORE_WEB_VITAL || + reportType === ReportTypes.DEVICE_DISTRIBUTION) && + allSeries.length > 0); + + return ( + + addSeries()} + isDisabled={isAddDisabled} + iconType="plusInCircle" + size="s" + > + {i18n.translate('xpack.observability.expView.seriesBuilder.addSeries', { + defaultMessage: 'Add series', + })} + + + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/series_views.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/series_views.tsx new file mode 100644 index 0000000000000..00fbc8c0e522f --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/series_views.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { RefObject } from 'react'; + +import { SeriesEditor } from '../series_editor/series_editor'; +import { AddSeriesButton } from './add_series_button'; +import { PanelId } from '../exploratory_view'; + +export function SeriesViews({ + seriesBuilderRef, +}: { + seriesBuilderRef: RefObject; + onSeriesPanelCollapse: (panel: PanelId) => void; +}) { + return ( +
    + + +
    + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.tsx new file mode 100644 index 0000000000000..f4416ef60441d --- /dev/null +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { isEqual } from 'lodash'; +import { allSeriesKey, convertAllShortSeries, useSeriesStorage } from '../hooks/use_series_storage'; + +export function ViewActions() { + const { allSeries, storage, applyChanges } = useSeriesStorage(); + + const noChanges = isEqual(allSeries, convertAllShortSeries(storage.get(allSeriesKey) ?? [])); + + return ( + + + applyChanges()} isDisabled={noChanges} fill size="s"> + {i18n.translate('xpack.observability.expView.seriesBuilder.apply', { + defaultMessage: 'Apply changes', + })} + + + + ); +} diff --git a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_combobox.tsx b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_combobox.tsx index fc562fa80e26d..0735df53888aa 100644 --- a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_combobox.tsx +++ b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_combobox.tsx @@ -6,15 +6,24 @@ */ import React, { useEffect, useState } from 'react'; -import { union } from 'lodash'; -import { EuiComboBox, EuiFormControlLayout, EuiComboBoxOptionOption } from '@elastic/eui'; +import { union, isEmpty } from 'lodash'; +import { + EuiComboBox, + EuiFormControlLayout, + EuiComboBoxOptionOption, + EuiFormRow, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import styled from 'styled-components'; import { FieldValueSelectionProps } from './types'; export const ALL_VALUES_SELECTED = 'ALL_VALUES'; const formatOptions = (values?: string[], allowAllValuesSelection?: boolean) => { const uniqueValues = Array.from( - new Set(allowAllValuesSelection ? ['ALL_VALUES', ...(values ?? [])] : values) + new Set( + allowAllValuesSelection && (values ?? []).length > 0 + ? ['ALL_VALUES', ...(values ?? [])] + : values + ) ); return (uniqueValues ?? []).map((label) => ({ @@ -30,7 +39,9 @@ export function FieldValueCombobox({ loading, values, setQuery, + usePrependLabel = true, compressed = true, + required = true, allowAllValuesSelection, onChange: onSelectionChange, }: FieldValueSelectionProps) { @@ -54,29 +65,35 @@ export function FieldValueCombobox({ onSelectionChange(selectedValuesN.map(({ label: lbl }) => lbl)); }; - return ( + const comboBox = ( + { + setQuery(searchVal); + }} + options={options} + selectedOptions={options.filter((opt) => selectedValue?.includes(opt.label))} + onChange={onChange} + isInvalid={required && isEmpty(selectedValue)} + /> + ); + + return usePrependLabel ? ( - { - setQuery(searchVal); - }} - options={options} - selectedOptions={options.filter((opt) => selectedValue?.includes(opt.label))} - onChange={onChange} - /> + {comboBox} + ) : ( + + {comboBox} + ); } diff --git a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_selection.tsx b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_selection.tsx index aca29c4723688..dfcd917cf534b 100644 --- a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_selection.tsx +++ b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_selection.tsx @@ -70,8 +70,8 @@ export function FieldValueSelection({ values = [], selectedValue, excludedValue, - compressed = true, allowExclusions = true, + compressed = true, onChange: onSelectionChange, }: FieldValueSelectionProps) { const [options, setOptions] = useState(() => @@ -174,8 +174,8 @@ export function FieldValueSelection({ }} options={options} onChange={onChange} - isLoading={loading && !query && options.length === 0} allowExclusions={allowExclusions} + isLoading={loading && !query && options.length === 0} > {(list, search) => (
    diff --git a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/index.test.tsx b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/index.test.tsx index 556a8e7052347..6671c43dd8c7b 100644 --- a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/index.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/index.test.tsx @@ -95,6 +95,7 @@ describe('FieldValueSuggestions', () => { selectedValue={[]} filters={[]} asCombobox={false} + allowExclusions={true} /> ); @@ -119,6 +120,7 @@ describe('FieldValueSuggestions', () => { excludedValue={['Pak']} filters={[]} asCombobox={false} + allowExclusions={true} /> ); diff --git a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/index.tsx b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/index.tsx index 3de158ba0622f..1c5da15dd33df 100644 --- a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/index.tsx +++ b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/index.tsx @@ -28,9 +28,11 @@ export function FieldValueSuggestions({ singleSelection, compressed, asFilterButton, + usePrependLabel, allowAllValuesSelection, + required, + allowExclusions = true, cardinalityField, - allowExclusions, asCombobox = true, onChange: onSelectionChange, }: FieldValueSuggestionsProps) { @@ -67,8 +69,10 @@ export function FieldValueSuggestions({ width={width} compressed={compressed} asFilterButton={asFilterButton} - allowAllValuesSelection={allowAllValuesSelection} + usePrependLabel={usePrependLabel} allowExclusions={allowExclusions} + allowAllValuesSelection={allowAllValuesSelection} + required={required} /> ); } diff --git a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/types.ts b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/types.ts index 046f98748cdf2..b6de2bafdd852 100644 --- a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/types.ts +++ b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/types.ts @@ -23,10 +23,11 @@ interface CommonProps { compressed?: boolean; asFilterButton?: boolean; showCount?: boolean; + usePrependLabel?: boolean; + allowExclusions?: boolean; allowAllValuesSelection?: boolean; cardinalityField?: string; required?: boolean; - allowExclusions?: boolean; } export type FieldValueSuggestionsProps = CommonProps & { diff --git a/x-pack/plugins/observability/public/components/shared/filter_value_label/filter_value_label.tsx b/x-pack/plugins/observability/public/components/shared/filter_value_label/filter_value_label.tsx index 01d727071770d..9e7b96b02206f 100644 --- a/x-pack/plugins/observability/public/components/shared/filter_value_label/filter_value_label.tsx +++ b/x-pack/plugins/observability/public/components/shared/filter_value_label/filter_value_label.tsx @@ -18,21 +18,25 @@ export function buildFilterLabel({ negate, }: { label: string; - value: string; + value: string | string[]; negate: boolean; field: string; indexPattern: IndexPattern; }) { const indexField = indexPattern.getFieldByName(field)!; - const filter = esFilters.buildPhraseFilter(indexField, value, indexPattern); + const filter = + value instanceof Array && value.length > 1 + ? esFilters.buildPhrasesFilter(indexField, value, indexPattern) + : esFilters.buildPhraseFilter(indexField, value as string, indexPattern); - filter.meta.value = value; + filter.meta.type = value instanceof Array && value.length > 1 ? 'phrases' : 'phrase'; + + filter.meta.value = value as string; filter.meta.key = label; filter.meta.alias = null; filter.meta.negate = negate; filter.meta.disabled = false; - filter.meta.type = 'phrase'; return filter; } @@ -40,10 +44,10 @@ export function buildFilterLabel({ interface Props { field: string; label: string; - value: string; + value: string | string[]; negate: boolean; - removeFilter: (field: string, value: string, notVal: boolean) => void; - invertFilter: (val: { field: string; value: string; negate: boolean }) => void; + removeFilter: (field: string, value: string | string[], notVal: boolean) => void; + invertFilter: (val: { field: string; value: string | string[]; negate: boolean }) => void; indexPattern: IndexPattern; allowExclusion?: boolean; } diff --git a/x-pack/plugins/observability/public/components/shared/index.tsx b/x-pack/plugins/observability/public/components/shared/index.tsx index 9d557a40b7987..afc053604fcdf 100644 --- a/x-pack/plugins/observability/public/components/shared/index.tsx +++ b/x-pack/plugins/observability/public/components/shared/index.tsx @@ -6,6 +6,7 @@ */ import React, { lazy, Suspense } from 'react'; +import { EuiLoadingSpinner } from '@elastic/eui'; import type { CoreVitalProps, HeaderMenuPortalProps } from './types'; import type { FieldValueSuggestionsProps } from './field_value_suggestions/types'; @@ -26,7 +27,7 @@ const HeaderMenuPortalLazy = lazy(() => import('./header_menu_portal')); export function HeaderMenuPortal(props: HeaderMenuPortalProps) { return ( - + }> ); diff --git a/x-pack/plugins/observability/public/hooks/use_quick_time_ranges.tsx b/x-pack/plugins/observability/public/hooks/use_quick_time_ranges.tsx index 82a0fc39b8519..198b4092b0ed6 100644 --- a/x-pack/plugins/observability/public/hooks/use_quick_time_ranges.tsx +++ b/x-pack/plugins/observability/public/hooks/use_quick_time_ranges.tsx @@ -7,7 +7,7 @@ import { useUiSetting } from '../../../../../src/plugins/kibana_react/public'; import { UI_SETTINGS } from '../../../../../src/plugins/data/common'; -import { TimePickerQuickRange } from '../components/shared/exploratory_view/series_date_picker'; +import { TimePickerQuickRange } from '../components/shared/exploratory_view/components/series_date_picker'; export function useQuickTimeRanges() { const timePickerQuickRanges = useUiSetting( diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 118f0783f9688..10843bbd1d5b5 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -24,6 +24,7 @@ import type { DataPublicPluginSetup, DataPublicPluginStart, } from '../../../../src/plugins/data/public'; +import type { DiscoverStart } from '../../../../src/plugins/discover/public'; import type { EmbeddableStart } from '../../../../src/plugins/embeddable/public'; import type { HomePublicPluginSetup, @@ -58,6 +59,7 @@ export interface ObservabilityPublicPluginsStart { triggersActionsUi: TriggersAndActionsUIPublicPluginStart; data: DataPublicPluginStart; lens: LensPublicStart; + discover: DiscoverStart; } export type ObservabilityPublicStart = ReturnType; diff --git a/x-pack/plugins/observability/public/routes/index.tsx b/x-pack/plugins/observability/public/routes/index.tsx index 00e487da7f9b7..ff03379e39963 100644 --- a/x-pack/plugins/observability/public/routes/index.tsx +++ b/x-pack/plugins/observability/public/routes/index.tsx @@ -99,7 +99,7 @@ export const routes = { }), }, }, - '/exploratory-view': { + '/exploratory-view/': { handler: () => { return ; }, @@ -112,18 +112,4 @@ export const routes = { }), }, }, - // enable this to test multi series architecture - // '/exploratory-view/multi': { - // handler: () => { - // return ; - // }, - // params: { - // query: t.partial({ - // rangeFrom: t.string, - // rangeTo: t.string, - // refreshPaused: jsonRt.pipe(t.boolean), - // refreshInterval: jsonRt.pipe(t.number), - // }), - // }, - // }, }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index c2d46fa5762d2..5da17d8a746a0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -18947,36 +18947,19 @@ "xpack.observability.expView.operationType.95thPercentile": "95パーセンタイル", "xpack.observability.expView.operationType.99thPercentile": "99パーセンタイル", "xpack.observability.expView.operationType.average": "平均", - "xpack.observability.expView.operationType.label": "計算", "xpack.observability.expView.operationType.median": "中央", "xpack.observability.expView.operationType.sum": "合計", - "xpack.observability.expView.reportType.noDataType": "データ型が選択されていません。", "xpack.observability.expView.reportType.selectDataType": "ビジュアライゼーションを作成するデータ型を選択します。", - "xpack.observability.expView.seriesBuilder.actions": "アクション", "xpack.observability.expView.seriesBuilder.addSeries": "数列を追加", "xpack.observability.expView.seriesBuilder.apply": "変更を適用", - "xpack.observability.expView.seriesBuilder.autoApply": "自動適用", - "xpack.observability.expView.seriesBuilder.breakdown": "内訳", - "xpack.observability.expView.seriesBuilder.dataType": "データ型", - "xpack.observability.expView.seriesBuilder.definition": "定義", "xpack.observability.expView.seriesBuilder.emptyReportDefinition": "ビジュアライゼーションを作成するレポート定義を選択します。", "xpack.observability.expView.seriesBuilder.emptyview": "表示する情報がありません。", - "xpack.observability.expView.seriesBuilder.filters": "フィルター", "xpack.observability.expView.seriesBuilder.loadingView": "ビューを読み込んでいます...", - "xpack.observability.expView.seriesBuilder.report": "レポート", - "xpack.observability.expView.seriesBuilder.selectDataType": "データ型が選択されていません", "xpack.observability.expView.seriesBuilder.selectReportType": "レポートタイプが選択されていません", "xpack.observability.expView.seriesBuilder.selectReportType.empty": "レポートタイプを選択すると、ビジュアライゼーションを作成します。", - "xpack.observability.expView.seriesEditor.actions": "アクション", - "xpack.observability.expView.seriesEditor.addFilter": "フィルターを追加します", - "xpack.observability.expView.seriesEditor.breakdowns": "内訳", "xpack.observability.expView.seriesEditor.clearFilter": "フィルターを消去", - "xpack.observability.expView.seriesEditor.filters": "フィルター", - "xpack.observability.expView.seriesEditor.name": "名前", "xpack.observability.expView.seriesEditor.notFound": "系列が見つかりません。系列を追加してください。", "xpack.observability.expView.seriesEditor.removeSeries": "クリックすると、系列を削除します", - "xpack.observability.expView.seriesEditor.seriesNotFound": "系列が見つかりません。系列を追加してください。", - "xpack.observability.expView.seriesEditor.time": "時間", "xpack.observability.featureCatalogueDescription": "専用UIで、ログ、メトリック、アプリケーショントレース、システム可用性を連結します。", "xpack.observability.featureCatalogueTitle": "オブザーバビリティ", "xpack.observability.featureRegistry.linkObservabilityTitle": "ケース", @@ -19038,7 +19021,6 @@ "xpack.observability.overview.ux.title": "ユーザーエクスペリエンス", "xpack.observability.overviewLinkTitle": "概要", "xpack.observability.pageLayout.sideNavTitle": "オブザーバビリティ", - "xpack.observability.reportTypeCol.nodata": "利用可能なデータがありません", "xpack.observability.resources.documentation": "ドキュメント", "xpack.observability.resources.forum": "ディスカッションフォーラム", "xpack.observability.resources.quick_start": "クイックスタートビデオ", @@ -19054,8 +19036,6 @@ "xpack.observability.section.apps.uptime.title": "アップタイム", "xpack.observability.section.errorPanel": "データの取得時にエラーが発生しました。再試行してください", "xpack.observability.seriesEditor.clone": "系列をコピー", - "xpack.observability.seriesEditor.edit": "系列を編集", - "xpack.observability.seriesEditor.save": "系列を保存", "xpack.observability.transactionRateLabel": "{value} tpm", "xpack.observability.ux.coreVitals.average": "平均", "xpack.observability.ux.coreVitals.averageMessage": " {bad}未満", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e3f53a34449ef..6d5b94f49cb6f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -19220,36 +19220,19 @@ "xpack.observability.expView.operationType.95thPercentile": "第 95 个百分位", "xpack.observability.expView.operationType.99thPercentile": "第 99 个百分位", "xpack.observability.expView.operationType.average": "平均值", - "xpack.observability.expView.operationType.label": "计算", "xpack.observability.expView.operationType.median": "中值", "xpack.observability.expView.operationType.sum": "求和", - "xpack.observability.expView.reportType.noDataType": "未选择任何数据类型。", "xpack.observability.expView.reportType.selectDataType": "选择数据类型以创建可视化。", - "xpack.observability.expView.seriesBuilder.actions": "操作", "xpack.observability.expView.seriesBuilder.addSeries": "添加序列", "xpack.observability.expView.seriesBuilder.apply": "应用更改", - "xpack.observability.expView.seriesBuilder.autoApply": "自动应用", - "xpack.observability.expView.seriesBuilder.breakdown": "分解", - "xpack.observability.expView.seriesBuilder.dataType": "数据类型", - "xpack.observability.expView.seriesBuilder.definition": "定义", "xpack.observability.expView.seriesBuilder.emptyReportDefinition": "选择报告定义以创建可视化。", "xpack.observability.expView.seriesBuilder.emptyview": "没有可显示的内容。", - "xpack.observability.expView.seriesBuilder.filters": "筛选", "xpack.observability.expView.seriesBuilder.loadingView": "正在加载视图......", - "xpack.observability.expView.seriesBuilder.report": "报告", - "xpack.observability.expView.seriesBuilder.selectDataType": "未选择任何数据类型", "xpack.observability.expView.seriesBuilder.selectReportType": "未选择任何报告类型", "xpack.observability.expView.seriesBuilder.selectReportType.empty": "选择报告类型以创建可视化。", - "xpack.observability.expView.seriesEditor.actions": "操作", - "xpack.observability.expView.seriesEditor.addFilter": "添加筛选", - "xpack.observability.expView.seriesEditor.breakdowns": "分解", "xpack.observability.expView.seriesEditor.clearFilter": "清除筛选", - "xpack.observability.expView.seriesEditor.filters": "筛选", - "xpack.observability.expView.seriesEditor.name": "名称", "xpack.observability.expView.seriesEditor.notFound": "未找到任何序列。请添加序列。", "xpack.observability.expView.seriesEditor.removeSeries": "单击移除序列", - "xpack.observability.expView.seriesEditor.seriesNotFound": "未找到任何序列。请添加序列。", - "xpack.observability.expView.seriesEditor.time": "时间", "xpack.observability.featureCatalogueDescription": "通过专用 UI 整合您的日志、指标、应用程序跟踪和系统可用性。", "xpack.observability.featureCatalogueTitle": "可观测性", "xpack.observability.featureRegistry.linkObservabilityTitle": "案例", @@ -19311,7 +19294,6 @@ "xpack.observability.overview.ux.title": "用户体验", "xpack.observability.overviewLinkTitle": "概览", "xpack.observability.pageLayout.sideNavTitle": "可观测性", - "xpack.observability.reportTypeCol.nodata": "没有可用数据", "xpack.observability.resources.documentation": "文档", "xpack.observability.resources.forum": "讨论论坛", "xpack.observability.resources.quick_start": "快速入门视频", @@ -19327,8 +19309,6 @@ "xpack.observability.section.apps.uptime.title": "运行时间", "xpack.observability.section.errorPanel": "尝试提取数据时发生错误。请重试", "xpack.observability.seriesEditor.clone": "复制序列", - "xpack.observability.seriesEditor.edit": "编辑序列", - "xpack.observability.seriesEditor.save": "保存序列", "xpack.observability.transactionRateLabel": "{value} tpm", "xpack.observability.ux.coreVitals.average": "平均值", "xpack.observability.ux.coreVitals.averageMessage": " 且小于 {bad}", diff --git a/x-pack/plugins/uptime/public/components/common/charts/ping_histogram.tsx b/x-pack/plugins/uptime/public/components/common/charts/ping_histogram.tsx index 1a53a2c9b64a0..aa981071b7ee2 100644 --- a/x-pack/plugins/uptime/public/components/common/charts/ping_histogram.tsx +++ b/x-pack/plugins/uptime/public/components/common/charts/ping_histogram.tsx @@ -22,6 +22,7 @@ import React, { useContext } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import numeral from '@elastic/numeral'; import moment from 'moment'; +import { useSelector } from 'react-redux'; import { getChartDateLabel } from '../../../lib/helper'; import { ChartWrapper } from './chart_wrapper'; import { UptimeThemeContext } from '../../../contexts'; @@ -32,6 +33,7 @@ import { getDateRangeFromChartElement } from './utils'; import { STATUS_DOWN_LABEL, STATUS_UP_LABEL } from '../translations'; import { createExploratoryViewUrl } from '../../../../../observability/public'; import { useUptimeSettingsContext } from '../../../contexts/uptime_settings_context'; +import { monitorStatusSelector } from '../../../state/selectors'; export interface PingHistogramComponentProps { /** @@ -73,6 +75,8 @@ export const PingHistogramComponent: React.FC = ({ const monitorId = useMonitorId(); + const selectedMonitor = useSelector(monitorStatusSelector); + const { basePath } = useUptimeSettingsContext(); const [getUrlParams, updateUrlParams] = useUrlParams(); @@ -189,12 +193,21 @@ export const PingHistogramComponent: React.FC = ({ const pingHistogramExploratoryViewLink = createExploratoryViewUrl( { - 'pings-over-time': { - dataType: 'synthetics', - reportType: 'kpi-over-time', - time: { from: dateRangeStart, to: dateRangeEnd }, - ...(monitorId ? { filters: [{ field: 'monitor.id', values: [monitorId] }] } : {}), - }, + reportType: 'kpi-over-time', + allSeries: [ + { + name: `${monitorId}-pings`, + dataType: 'synthetics', + selectedMetricField: 'summary.up', + time: { from: dateRangeStart, to: dateRangeEnd }, + reportDefinitions: { + 'monitor.name': + monitorId && selectedMonitor?.monitor?.name + ? [selectedMonitor.monitor.name] + : ['ALL_VALUES'], + }, + }, + ], }, basePath ); diff --git a/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx b/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx index ef5e10394739a..c459fe46da975 100644 --- a/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx +++ b/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx @@ -10,13 +10,15 @@ import { EuiHeaderLinks, EuiToolTip, EuiHeaderLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { useHistory } from 'react-router-dom'; -import { createExploratoryViewUrl, SeriesUrl } from '../../../../../observability/public'; +import { useSelector } from 'react-redux'; +import { createExploratoryViewUrl } from '../../../../../observability/public'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { useUptimeSettingsContext } from '../../../contexts/uptime_settings_context'; import { useGetUrlParams } from '../../../hooks'; import { ToggleAlertFlyoutButton } from '../../overview/alerts/alerts_containers'; import { SETTINGS_ROUTE } from '../../../../common/constants'; import { stringifyUrlParams } from '../../../lib/helper/stringify_url_params'; +import { monitorStatusSelector } from '../../../state/selectors'; const ADD_DATA_LABEL = i18n.translate('xpack.uptime.addDataButtonLabel', { defaultMessage: 'Add data', @@ -38,13 +40,28 @@ export function ActionMenuContent(): React.ReactElement { const { dateRangeStart, dateRangeEnd } = params; const history = useHistory(); + const selectedMonitor = useSelector(monitorStatusSelector); + + const monitorId = selectedMonitor?.monitor?.id; + const syntheticExploratoryViewLink = createExploratoryViewUrl( { - 'synthetics-series': { - dataType: 'synthetics', - isNew: true, - time: { from: dateRangeStart, to: dateRangeEnd }, - } as unknown as SeriesUrl, + reportType: 'kpi-over-time', + allSeries: [ + { + dataType: 'synthetics', + seriesType: 'area_stacked', + selectedMetricField: 'monitor.duration.us', + time: { from: dateRangeStart, to: dateRangeEnd }, + breakdown: monitorId ? 'observer.geo.name' : 'monitor.type', + reportDefinitions: { + 'monitor.name': selectedMonitor?.monitor?.name + ? [selectedMonitor?.monitor?.name] + : ['ALL_VALUES'], + }, + name: monitorId ? `${monitorId}-response-duration` : 'All monitors response duration', + }, + ], }, basePath ); diff --git a/x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx b/x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx index cbfba4ffcb239..35eab80c15967 100644 --- a/x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx @@ -51,16 +51,19 @@ export const MonitorDuration: React.FC = ({ monitorId }) => { const exploratoryViewLink = createExploratoryViewUrl( { - [`monitor-duration`]: { - reportType: 'kpi-over-time', - time: { from: dateRangeStart, to: dateRangeEnd }, - reportDefinitions: { - 'monitor.id': [monitorId] as string[], + reportType: 'kpi-over-time', + allSeries: [ + { + name: `${monitorId}-response-duration`, + time: { from: dateRangeStart, to: dateRangeEnd }, + reportDefinitions: { + 'monitor.id': [monitorId] as string[], + }, + breakdown: 'observer.geo.name', + operationType: 'average', + dataType: 'synthetics', }, - breakdown: 'observer.geo.name', - operationType: 'average', - dataType: 'synthetics', - }, + ], }, basePath ); diff --git a/x-pack/test/observability_functional/apps/observability/exploratory_view.ts b/x-pack/test/observability_functional/apps/observability/exploratory_view.ts new file mode 100644 index 0000000000000..8f27f20ce30e6 --- /dev/null +++ b/x-pack/test/observability_functional/apps/observability/exploratory_view.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import Path from 'path'; +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['observability', 'common', 'header']); + const esArchiver = getService('esArchiver'); + const find = getService('find'); + + const testSubjects = getService('testSubjects'); + + const rangeFrom = '2021-01-17T16%3A46%3A15.338Z'; + const rangeTo = '2021-01-19T17%3A01%3A32.309Z'; + + // Failing: See https://github.com/elastic/kibana/issues/106934 + describe.skip('ExploratoryView', () => { + before(async () => { + await esArchiver.loadIfNeeded( + Path.join('x-pack/test/apm_api_integration/common/fixtures/es_archiver', '8.0.0') + ); + + await esArchiver.loadIfNeeded( + Path.join('x-pack/test/apm_api_integration/common/fixtures/es_archiver', 'rum_8.0.0') + ); + + await esArchiver.loadIfNeeded( + Path.join('x-pack/test/apm_api_integration/common/fixtures/es_archiver', 'rum_test_data') + ); + + await PageObjects.common.navigateToApp('ux', { + search: `?rangeFrom=${rangeFrom}&rangeTo=${rangeTo}`, + }); + await PageObjects.header.waitUntilLoadingHasFinished(); + }); + + after(async () => { + await esArchiver.unload( + Path.join('x-pack/test/apm_api_integration/common/fixtures/es_archiver', '8.0.0') + ); + + await esArchiver.unload( + Path.join('x-pack/test/apm_api_integration/common/fixtures/es_archiver', 'rum_8.0.0') + ); + }); + + it('should able to open exploratory view from ux app', async () => { + await testSubjects.exists('uxAnalyzeBtn'); + await testSubjects.click('uxAnalyzeBtn'); + expect(await find.existsByCssSelector('.euiBasicTable')).to.eql(true); + }); + + it('renders lens visualization', async () => { + expect(await testSubjects.exists('lnsVisualizationContainer')).to.eql(true); + + expect( + await find.existsByCssSelector('div[data-title="Prefilled from exploratory view app"]') + ).to.eql(true); + + expect((await find.byCssSelector('dd')).getVisibleText()).to.eql(true); + }); + + it('can do a breakdown per series', async () => { + await testSubjects.click('seriesBreakdown'); + + expect(await find.existsByCssSelector('[id="user_agent.name"]')).to.eql(true); + + await find.clickByCssSelector('[id="user_agent.name"]'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + + expect(await find.existsByCssSelector('[title="Chrome Mobile iOS"]')).to.eql(true); + expect(await find.existsByCssSelector('[title="Mobile Safari"]')).to.eql(true); + }); + }); +} diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/test/observability_functional/apps/observability/index.ts index 019fb0994715e..b163d4d6bb8d5 100644 --- a/x-pack/test/observability_functional/apps/observability/index.ts +++ b/x-pack/test/observability_functional/apps/observability/index.ts @@ -8,9 +8,10 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - describe('Observability specs', function () { + describe('ObservabilityApp', function () { this.tags('ciGroup6'); loadTestFile(require.resolve('./feature_controls')); + loadTestFile(require.resolve('./exploratory_view')); loadTestFile(require.resolve('./alerts')); loadTestFile(require.resolve('./alerts/workflow_status')); loadTestFile(require.resolve('./alerts/pagination')); From 8c89daedba4a9ca4b361bc72f9d00a6094d3c4bf Mon Sep 17 00:00:00 2001 From: ymao1 Date: Mon, 4 Oct 2021 10:06:07 -0400 Subject: [PATCH 36/98] Adding range filter to ownerId aggregation (#113557) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../monitoring/workload_statistics.test.ts | 27 +++++++++++++++---- .../server/monitoring/workload_statistics.ts | 21 ++++++++++++--- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts index 9c697be985155..9628e2807627a 100644 --- a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts +++ b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts @@ -65,7 +65,9 @@ describe('Workload Statistics Aggregator', () => { doc_count: 13, }, ownerIds: { - value: 1, + ownerIds: { + value: 1, + }, }, // The `FiltersAggregate` doesn't cover the case of a nested `AggregationsAggregationContainer`, in which `FiltersAggregate` // would not have a `buckets` property, but rather a keyed property that's inferred from the request. @@ -127,8 +129,19 @@ describe('Workload Statistics Aggregator', () => { missing: { field: 'task.schedule' }, }, ownerIds: { - cardinality: { - field: 'task.ownerId', + filter: { + range: { + 'task.startedAt': { + gte: 'now-1w/w', + }, + }, + }, + aggs: { + ownerIds: { + cardinality: { + field: 'task.ownerId', + }, + }, }, }, idleTasks: { @@ -264,7 +277,9 @@ describe('Workload Statistics Aggregator', () => { doc_count: 13, }, ownerIds: { - value: 1, + ownerIds: { + value: 1, + }, }, // The `FiltersAggregate` doesn't cover the case of a nested `AggregationsAggregationContainer`, in which `FiltersAggregate` // would not have a `buckets` property, but rather a keyed property that's inferred from the request. @@ -605,7 +620,9 @@ describe('Workload Statistics Aggregator', () => { doc_count: 13, }, ownerIds: { - value: 3, + ownerIds: { + value: 3, + }, }, // The `FiltersAggregate` doesn't cover the case of a nested `AggregationContainer`, in which `FiltersAggregate` // would not have a `buckets` property, but rather a keyed property that's inferred from the request. diff --git a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts index b833e4ed57530..9ac528cfd1ced 100644 --- a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts +++ b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts @@ -147,8 +147,19 @@ export function createWorkloadAggregator( missing: { field: 'task.schedule' }, }, ownerIds: { - cardinality: { - field: 'task.ownerId', + filter: { + range: { + 'task.startedAt': { + gte: 'now-1w/w', + }, + }, + }, + aggs: { + ownerIds: { + cardinality: { + field: 'task.ownerId', + }, + }, }, }, idleTasks: { @@ -213,7 +224,7 @@ export function createWorkloadAggregator( const taskTypes = aggregations.taskType.buckets; const nonRecurring = aggregations.nonRecurringTasks.doc_count; - const ownerIds = aggregations.ownerIds.value; + const ownerIds = aggregations.ownerIds.ownerIds.value; const { overdue: { @@ -448,7 +459,9 @@ export interface WorkloadAggregationResponse { doc_count: number; }; ownerIds: { - value: number; + ownerIds: { + value: number; + }; }; [otherAggs: string]: estypes.AggregationsAggregate; } From 69bee186c27aca043ab7393d91e4ad608ae6b35c Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" Date: Mon, 4 Oct 2021 09:48:01 -0500 Subject: [PATCH 37/98] [Security Solution] create task for auto restarting failed OLM transforms (#113686) --- .../security_solution/common/constants.ts | 21 +- .../common/endpoint/constants.ts | 7 +- .../management/pages/endpoint_hosts/mocks.ts | 8 +- .../pages/endpoint_hosts/store/middleware.ts | 6 +- .../store/mock_endpoint_result_list.ts | 4 +- .../management/pages/endpoint_hosts/types.ts | 20 +- .../pages/endpoint_hosts/view/index.test.tsx | 9 +- .../pages/endpoint_hosts/view/index.tsx | 2 +- .../check_metadata_transforms_task.test.ts | 250 ++++++++++++++++++ .../check_metadata_transforms_task.ts | 214 +++++++++++++++ .../server/endpoint/lib/metadata/index.ts | 8 + .../security_solution/server/plugin.ts | 12 + 12 files changed, 526 insertions(+), 35 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts create mode 100644 x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts create mode 100644 x-pack/plugins/security_solution/server/endpoint/lib/metadata/index.ts diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 4316b1c033ec6..e91f74320c026 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -7,7 +7,7 @@ import type { TransformConfigSchema } from './transforms/types'; import { ENABLE_CASE_CONNECTOR } from '../../cases/common'; -import { metadataTransformPattern } from './endpoint/constants'; +import { METADATA_TRANSFORMS_PATTERN } from './endpoint/constants'; export const APP_ID = 'securitySolution'; export const CASES_FEATURE_ID = 'securitySolutionCases'; @@ -331,6 +331,23 @@ export const showAllOthersBucket: string[] = [ */ export const ELASTIC_NAME = 'estc'; -export const TRANSFORM_STATS_URL = `/api/transform/transforms/${metadataTransformPattern}-*/_stats`; +export const METADATA_TRANSFORM_STATS_URL = `/api/transform/transforms/${METADATA_TRANSFORMS_PATTERN}/_stats`; export const RISKY_HOSTS_INDEX = 'ml_host_risk_score_latest'; + +export const TRANSFORM_STATES = { + ABORTING: 'aborting', + FAILED: 'failed', + INDEXING: 'indexing', + STARTED: 'started', + STOPPED: 'stopped', + STOPPING: 'stopping', + WAITING: 'waiting', +}; + +export const WARNING_TRANSFORM_STATES = new Set([ + TRANSFORM_STATES.ABORTING, + TRANSFORM_STATES.FAILED, + TRANSFORM_STATES.STOPPED, + TRANSFORM_STATES.STOPPING, +]); diff --git a/x-pack/plugins/security_solution/common/endpoint/constants.ts b/x-pack/plugins/security_solution/common/endpoint/constants.ts index a38266c414e6b..c7949299c68db 100644 --- a/x-pack/plugins/security_solution/common/endpoint/constants.ts +++ b/x-pack/plugins/security_solution/common/endpoint/constants.ts @@ -20,10 +20,13 @@ export const metadataCurrentIndexPattern = 'metrics-endpoint.metadata_current_*' /** The metadata Transform Name prefix with NO (package) version) */ export const metadataTransformPrefix = 'endpoint.metadata_current-default'; -/** The metadata Transform Name prefix with NO namespace and NO (package) version) */ -export const metadataTransformPattern = 'endpoint.metadata_current-*'; +// metadata transforms pattern for matching all metadata transform ids +export const METADATA_TRANSFORMS_PATTERN = 'endpoint.metadata_*'; +// united metadata transform id export const METADATA_UNITED_TRANSFORM = 'endpoint.metadata_united-default'; + +// united metadata transform destination index export const METADATA_UNITED_INDEX = '.metrics-endpoint.metadata_united_default'; export const policyIndexPattern = 'metrics-endpoint.policy-*'; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts index cf3f53b5b2ea9..010fe48f29418 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/mocks.ts @@ -37,8 +37,8 @@ import { PendingActionsHttpMockInterface, pendingActionsHttpMock, } from '../../../common/lib/endpoint_pending_actions/mocks'; -import { TRANSFORM_STATS_URL } from '../../../../common/constants'; -import { TransformStatsResponse, TRANSFORM_STATE } from './types'; +import { METADATA_TRANSFORM_STATS_URL, TRANSFORM_STATES } from '../../../../common/constants'; +import { TransformStatsResponse } from './types'; type EndpointMetadataHttpMocksInterface = ResponseProvidersInterface<{ metadataList: () => HostResultList; @@ -238,14 +238,14 @@ export const failedTransformStateMock = { count: 1, transforms: [ { - state: TRANSFORM_STATE.FAILED, + state: TRANSFORM_STATES.FAILED, }, ], }; export const transformsHttpMocks = httpHandlerMockFactory([ { id: 'metadataTransformStats', - path: TRANSFORM_STATS_URL, + path: METADATA_TRANSFORM_STATS_URL, method: 'get', handler: () => failedTransformStateMock, }, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts index 84cf3513d5d3a..7a45ff06c496b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts @@ -78,7 +78,7 @@ import { resolvePathVariables } from '../../../../common/utils/resolve_path_vari import { EndpointPackageInfoStateChanged } from './action'; import { fetchPendingActionsByAgentId } from '../../../../common/lib/endpoint_pending_actions'; import { getIsInvalidDateRange } from '../utils'; -import { TRANSFORM_STATS_URL } from '../../../../../common/constants'; +import { METADATA_TRANSFORM_STATS_URL } from '../../../../../common/constants'; type EndpointPageStore = ImmutableMiddlewareAPI; @@ -785,7 +785,9 @@ export async function handleLoadMetadataTransformStats(http: HttpStart, store: E }); try { - const transformStatsResponse: TransformStatsResponse = await http.get(TRANSFORM_STATS_URL); + const transformStatsResponse: TransformStatsResponse = await http.get( + METADATA_TRANSFORM_STATS_URL + ); dispatch({ type: 'metadataTransformStatsChanged', diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts index 8e8e5a61221a9..2e3de427e6960 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/mock_endpoint_result_list.ts @@ -30,7 +30,7 @@ import { import { GetPolicyListResponse } from '../../policy/types'; import { pendingActionsResponseMock } from '../../../../common/lib/endpoint_pending_actions/mocks'; import { ACTION_STATUS_ROUTE } from '../../../../../common/endpoint/constants'; -import { TRANSFORM_STATS_URL } from '../../../../../common/constants'; +import { METADATA_TRANSFORM_STATS_URL } from '../../../../../common/constants'; import { TransformStats, TransformStatsResponse } from '../types'; const generator = new EndpointDocGenerator('seed'); @@ -163,7 +163,7 @@ const endpointListApiPathHandlerMocks = ({ return pendingActionsResponseMock(); }, - [TRANSFORM_STATS_URL]: (): TransformStatsResponse => ({ + [METADATA_TRANSFORM_STATS_URL]: (): TransformStatsResponse => ({ count: transforms.length, transforms, }), diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts index dd0bc79f1ba52..0fa96fe00fd2c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts @@ -22,6 +22,7 @@ import { ServerApiError } from '../../../common/types'; import { GetPackagesResponse } from '../../../../../fleet/common'; import { IIndexPattern } from '../../../../../../../src/plugins/data/public'; import { AsyncResourceState } from '../../state'; +import { TRANSFORM_STATES } from '../../../../common/constants'; export interface EndpointState { /** list of host **/ @@ -143,24 +144,7 @@ export interface EndpointIndexUIQueryParams { admin_query?: string; } -export const TRANSFORM_STATE = { - ABORTING: 'aborting', - FAILED: 'failed', - INDEXING: 'indexing', - STARTED: 'started', - STOPPED: 'stopped', - STOPPING: 'stopping', - WAITING: 'waiting', -}; - -export const WARNING_TRANSFORM_STATES = new Set([ - TRANSFORM_STATE.ABORTING, - TRANSFORM_STATE.FAILED, - TRANSFORM_STATE.STOPPED, - TRANSFORM_STATE.STOPPING, -]); - -const transformStates = Object.values(TRANSFORM_STATE); +const transformStates = Object.values(TRANSFORM_STATES); export type TransformState = typeof transformStates[number]; export interface TransformStats { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index 33c45e6e2f548..b2c438659b771 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -46,8 +46,9 @@ import { APP_PATH, MANAGEMENT_PATH, DEFAULT_TIMEPICKER_QUICK_RANGES, + TRANSFORM_STATES, } from '../../../../../common/constants'; -import { TransformStats, TRANSFORM_STATE } from '../types'; +import { TransformStats } from '../types'; import { metadataTransformPrefix } from '../../../../../common/endpoint/constants'; // not sure why this can't be imported from '../../../../common/mock/formatted_relative'; @@ -1403,7 +1404,7 @@ describe('when on the endpoint list page', () => { const transforms: TransformStats[] = [ { id: `${metadataTransformPrefix}-0.20.0`, - state: TRANSFORM_STATE.STARTED, + state: TRANSFORM_STATES.STARTED, } as TransformStats, ]; setEndpointListApiMockImplementation(coreStart.http, { transforms }); @@ -1414,7 +1415,7 @@ describe('when on the endpoint list page', () => { it('is not displayed when non-relevant transform is failing', () => { const transforms: TransformStats[] = [ - { id: 'not-metadata', state: TRANSFORM_STATE.FAILED } as TransformStats, + { id: 'not-metadata', state: TRANSFORM_STATES.FAILED } as TransformStats, ]; setEndpointListApiMockImplementation(coreStart.http, { transforms }); render(); @@ -1426,7 +1427,7 @@ describe('when on the endpoint list page', () => { const transforms: TransformStats[] = [ { id: `${metadataTransformPrefix}-0.20.0`, - state: TRANSFORM_STATE.FAILED, + state: TRANSFORM_STATES.FAILED, } as TransformStats, ]; setEndpointListApiMockImplementation(coreStart.http, { transforms }); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx index e71474321c868..7845409353898 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.tsx @@ -58,8 +58,8 @@ import { LinkToApp } from '../../../../common/components/endpoint/link_to_app'; import { TableRowActions } from './components/table_row_actions'; import { EndpointAgentStatus } from './components/endpoint_agent_status'; import { CallOut } from '../../../../common/components/callouts'; -import { WARNING_TRANSFORM_STATES } from '../types'; import { metadataTransformPrefix } from '../../../../../common/endpoint/constants'; +import { WARNING_TRANSFORM_STATES } from '../../../../../common/constants'; const MAX_PAGINATED_ITEM = 9999; const TRANSFORM_URL = '/data/transform'; diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts new file mode 100644 index 0000000000000..0510743fdf05b --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts @@ -0,0 +1,250 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { ApiResponse } from '@elastic/elasticsearch'; +import { TransformGetTransformStatsResponse } from '@elastic/elasticsearch/api/types'; +import { + CheckMetadataTransformsTask, + TYPE, + VERSION, + BASE_NEXT_ATTEMPT_DELAY, +} from './check_metadata_transforms_task'; +import { createMockEndpointAppContext } from '../../mocks'; +import { coreMock } from '../../../../../../../src/core/server/mocks'; +import { taskManagerMock } from '../../../../../task_manager/server/mocks'; +import { TaskManagerSetupContract, TaskStatus } from '../../../../../task_manager/server'; +import { CoreSetup } from '../../../../../../../src/core/server'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ElasticsearchClientMock } from '../../../../../../../src/core/server/elasticsearch/client/mocks'; +import { TRANSFORM_STATES } from '../../../../common/constants'; +import { METADATA_TRANSFORMS_PATTERN } from '../../../../common/endpoint/constants'; +import { RunResult } from '../../../../../task_manager/server/task'; + +const MOCK_TASK_INSTANCE = { + id: `${TYPE}:${VERSION}`, + runAt: new Date(), + attempts: 0, + ownerId: '', + status: TaskStatus.Running, + startedAt: new Date(), + scheduledAt: new Date(), + retryAt: new Date(), + params: {}, + state: {}, + taskType: TYPE, +}; +const failedTransformId = 'failing-transform'; +const goodTransformId = 'good-transform'; + +describe('check metadata transforms task', () => { + const { createSetup: coreSetupMock } = coreMock; + const { createSetup: tmSetupMock, createStart: tmStartMock } = taskManagerMock; + + let mockTask: CheckMetadataTransformsTask; + let mockCore: CoreSetup; + let mockTaskManagerSetup: jest.Mocked; + beforeAll(() => { + mockCore = coreSetupMock(); + mockTaskManagerSetup = tmSetupMock(); + mockTask = new CheckMetadataTransformsTask({ + endpointAppContext: createMockEndpointAppContext(), + core: mockCore, + taskManager: mockTaskManagerSetup, + }); + }); + + describe('task lifecycle', () => { + it('should create task', () => { + expect(mockTask).toBeInstanceOf(CheckMetadataTransformsTask); + }); + + it('should register task', () => { + expect(mockTaskManagerSetup.registerTaskDefinitions).toHaveBeenCalled(); + }); + + it('should schedule task', async () => { + const mockTaskManagerStart = tmStartMock(); + await mockTask.start({ taskManager: mockTaskManagerStart }); + expect(mockTaskManagerStart.ensureScheduled).toHaveBeenCalled(); + }); + }); + + describe('task logic', () => { + let esClient: ElasticsearchClientMock; + beforeEach(async () => { + const [{ elasticsearch }] = await mockCore.getStartServices(); + esClient = elasticsearch.client.asInternalUser as ElasticsearchClientMock; + }); + + const runTask = async (taskInstance = MOCK_TASK_INSTANCE) => { + const mockTaskManagerStart = tmStartMock(); + await mockTask.start({ taskManager: mockTaskManagerStart }); + const createTaskRunner = + mockTaskManagerSetup.registerTaskDefinitions.mock.calls[0][0][TYPE].createTaskRunner; + const taskRunner = createTaskRunner({ taskInstance }); + return taskRunner.run(); + }; + + const buildFailedStatsResponse = () => + ({ + body: { + transforms: [ + { + id: goodTransformId, + state: TRANSFORM_STATES.STARTED, + }, + { + id: failedTransformId, + state: TRANSFORM_STATES.FAILED, + }, + ], + }, + } as unknown as ApiResponse); + + it('should stop task if transform stats response fails', async () => { + esClient.transform.getTransformStats.mockRejectedValue({}); + await runTask(); + expect(esClient.transform.getTransformStats).toHaveBeenCalledWith({ + transform_id: METADATA_TRANSFORMS_PATTERN, + }); + expect(esClient.transform.stopTransform).not.toHaveBeenCalled(); + expect(esClient.transform.startTransform).not.toHaveBeenCalled(); + }); + + it('should attempt transform restart if failing state', async () => { + const transformStatsResponseMock = buildFailedStatsResponse(); + esClient.transform.getTransformStats.mockResolvedValue(transformStatsResponseMock); + + const taskResponse = (await runTask()) as RunResult; + + expect(esClient.transform.getTransformStats).toHaveBeenCalledWith({ + transform_id: METADATA_TRANSFORMS_PATTERN, + }); + expect(esClient.transform.stopTransform).toHaveBeenCalledWith({ + transform_id: failedTransformId, + allow_no_match: true, + wait_for_completion: true, + force: true, + }); + expect(esClient.transform.startTransform).toHaveBeenCalledWith({ + transform_id: failedTransformId, + }); + expect(taskResponse?.state?.attempts).toEqual({ + [goodTransformId]: 0, + [failedTransformId]: 0, + }); + }); + + it('should correctly track transform restart attempts', async () => { + const transformStatsResponseMock = buildFailedStatsResponse(); + esClient.transform.getTransformStats.mockResolvedValue(transformStatsResponseMock); + + esClient.transform.stopTransform.mockRejectedValueOnce({}); + let taskResponse = (await runTask()) as RunResult; + expect(taskResponse?.state?.attempts).toEqual({ + [goodTransformId]: 0, + [failedTransformId]: 1, + }); + + esClient.transform.startTransform.mockRejectedValueOnce({}); + taskResponse = (await runTask({ + ...MOCK_TASK_INSTANCE, + state: taskResponse.state, + })) as RunResult; + expect(taskResponse?.state?.attempts).toEqual({ + [goodTransformId]: 0, + [failedTransformId]: 2, + }); + + taskResponse = (await runTask({ + ...MOCK_TASK_INSTANCE, + state: taskResponse.state, + })) as RunResult; + expect(taskResponse?.state?.attempts).toEqual({ + [goodTransformId]: 0, + [failedTransformId]: 0, + }); + }); + + it('should correctly back off subsequent restart attempts', async () => { + let transformStatsResponseMock = buildFailedStatsResponse(); + esClient.transform.getTransformStats.mockResolvedValue(transformStatsResponseMock); + + esClient.transform.stopTransform.mockRejectedValueOnce({}); + let taskStartedAt = new Date(); + let taskResponse = (await runTask()) as RunResult; + let delay = BASE_NEXT_ATTEMPT_DELAY * 60000; + let expectedRunAt = taskStartedAt.getTime() + delay; + expect(taskResponse?.runAt?.getTime()).toBeGreaterThanOrEqual(expectedRunAt); + // we don't have the exact timestamp it uses so give a buffer + let expectedRunAtUpperBound = expectedRunAt + 1000; + expect(taskResponse?.runAt?.getTime()).toBeLessThanOrEqual(expectedRunAtUpperBound); + + esClient.transform.startTransform.mockRejectedValueOnce({}); + taskStartedAt = new Date(); + taskResponse = (await runTask({ + ...MOCK_TASK_INSTANCE, + state: taskResponse.state, + })) as RunResult; + // should be exponential on second+ attempt + delay = BASE_NEXT_ATTEMPT_DELAY ** 2 * 60000; + expectedRunAt = taskStartedAt.getTime() + delay; + expect(taskResponse?.runAt?.getTime()).toBeGreaterThanOrEqual(expectedRunAt); + // we don't have the exact timestamp it uses so give a buffer + expectedRunAtUpperBound = expectedRunAt + 1000; + expect(taskResponse?.runAt?.getTime()).toBeLessThanOrEqual(expectedRunAtUpperBound); + + esClient.transform.stopTransform.mockRejectedValueOnce({}); + taskStartedAt = new Date(); + taskResponse = (await runTask({ + ...MOCK_TASK_INSTANCE, + state: taskResponse.state, + })) as RunResult; + // should be exponential on second+ attempt + delay = BASE_NEXT_ATTEMPT_DELAY ** 3 * 60000; + expectedRunAt = taskStartedAt.getTime() + delay; + expect(taskResponse?.runAt?.getTime()).toBeGreaterThanOrEqual(expectedRunAt); + // we don't have the exact timestamp it uses so give a buffer + expectedRunAtUpperBound = expectedRunAt + 1000; + expect(taskResponse?.runAt?.getTime()).toBeLessThanOrEqual(expectedRunAtUpperBound); + + taskStartedAt = new Date(); + taskResponse = (await runTask({ + ...MOCK_TASK_INSTANCE, + state: taskResponse.state, + })) as RunResult; + // back to base delay after success + delay = BASE_NEXT_ATTEMPT_DELAY * 60000; + expectedRunAt = taskStartedAt.getTime() + delay; + expect(taskResponse?.runAt?.getTime()).toBeGreaterThanOrEqual(expectedRunAt); + // we don't have the exact timestamp it uses so give a buffer + expectedRunAtUpperBound = expectedRunAt + 1000; + expect(taskResponse?.runAt?.getTime()).toBeLessThanOrEqual(expectedRunAtUpperBound); + + transformStatsResponseMock = { + body: { + transforms: [ + { + id: goodTransformId, + state: TRANSFORM_STATES.STARTED, + }, + { + id: failedTransformId, + state: TRANSFORM_STATES.STARTED, + }, + ], + }, + } as unknown as ApiResponse; + esClient.transform.getTransformStats.mockResolvedValue(transformStatsResponseMock); + taskResponse = (await runTask({ + ...MOCK_TASK_INSTANCE, + state: taskResponse.state, + })) as RunResult; + // no more explicit runAt after subsequent success + expect(taskResponse?.runAt).toBeUndefined(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts new file mode 100644 index 0000000000000..68f149bcc64c4 --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts @@ -0,0 +1,214 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { ApiResponse } from '@elastic/elasticsearch'; +import { + TransformGetTransformStatsResponse, + TransformGetTransformStatsTransformStats, +} from '@elastic/elasticsearch/api/types'; +import { CoreSetup, ElasticsearchClient, Logger } from 'src/core/server'; +import { + ConcreteTaskInstance, + TaskManagerSetupContract, + TaskManagerStartContract, + throwUnrecoverableError, +} from '../../../../../task_manager/server'; +import { EndpointAppContext } from '../../types'; +import { METADATA_TRANSFORMS_PATTERN } from '../../../../common/endpoint/constants'; +import { WARNING_TRANSFORM_STATES } from '../../../../common/constants'; +import { wrapErrorIfNeeded } from '../../utils'; + +const SCOPE = ['securitySolution']; +const INTERVAL = '2h'; +const TIMEOUT = '4m'; +export const TYPE = 'endpoint:metadata-check-transforms-task'; +export const VERSION = '0.0.1'; +const MAX_ATTEMPTS = 5; +export const BASE_NEXT_ATTEMPT_DELAY = 5; // minutes + +export interface CheckMetadataTransformsTaskSetupContract { + endpointAppContext: EndpointAppContext; + core: CoreSetup; + taskManager: TaskManagerSetupContract; +} + +export interface CheckMetadataTransformsTaskStartContract { + taskManager: TaskManagerStartContract; +} + +export class CheckMetadataTransformsTask { + private logger: Logger; + private wasStarted: boolean = false; + + constructor(setupContract: CheckMetadataTransformsTaskSetupContract) { + const { endpointAppContext, core, taskManager } = setupContract; + this.logger = endpointAppContext.logFactory.get(this.getTaskId()); + taskManager.registerTaskDefinitions({ + [TYPE]: { + title: 'Security Solution Endpoint Metadata Periodic Tasks', + timeout: TIMEOUT, + createTaskRunner: ({ taskInstance }: { taskInstance: ConcreteTaskInstance }) => { + return { + run: async () => { + return this.runTask(taskInstance, core); + }, + cancel: async () => {}, + }; + }, + }, + }); + } + + public start = async ({ taskManager }: CheckMetadataTransformsTaskStartContract) => { + if (!taskManager) { + this.logger.error('missing required service during start'); + return; + } + + this.wasStarted = true; + + try { + await taskManager.ensureScheduled({ + id: this.getTaskId(), + taskType: TYPE, + scope: SCOPE, + schedule: { + interval: INTERVAL, + }, + state: { + attempts: {}, + }, + params: { version: VERSION }, + }); + } catch (e) { + this.logger.debug(`Error scheduling task, received ${e.message}`); + } + }; + + private runTask = async (taskInstance: ConcreteTaskInstance, core: CoreSetup) => { + // if task was not `.start()`'d yet, then exit + if (!this.wasStarted) { + this.logger.debug('[runTask()] Aborted. MetadataTask not started yet'); + return; + } + + // Check that this task is current + if (taskInstance.id !== this.getTaskId()) { + // old task, die + throwUnrecoverableError(new Error('Outdated task version')); + } + + const [{ elasticsearch }] = await core.getStartServices(); + const esClient = elasticsearch.client.asInternalUser; + + let transformStatsResponse: ApiResponse; + try { + transformStatsResponse = await esClient?.transform.getTransformStats({ + transform_id: METADATA_TRANSFORMS_PATTERN, + }); + } catch (e) { + const err = wrapErrorIfNeeded(e); + const errMessage = `failed to get transform stats with error: ${err}`; + this.logger.error(errMessage); + + return; + } + + const { transforms } = transformStatsResponse.body; + if (!transforms.length) { + this.logger.info('no OLM metadata transforms found'); + return; + } + + let didAttemptRestart: boolean = false; + let highestAttempt: number = 0; + const attempts = { ...taskInstance.state.attempts }; + + for (const transform of transforms) { + const restartedTransform = await this.restartTransform( + esClient, + transform, + attempts[transform.id] + ); + if (restartedTransform.didAttemptRestart) { + didAttemptRestart = true; + } + attempts[transform.id] = restartedTransform.attempts; + highestAttempt = Math.max(attempts[transform.id], highestAttempt); + } + + // after a restart attempt run next check sooner with exponential backoff + let runAt: Date | undefined; + if (didAttemptRestart) { + const delay = BASE_NEXT_ATTEMPT_DELAY ** Math.max(highestAttempt, 1) * 60000; + runAt = new Date(new Date().getTime() + delay); + } + + const nextState = { attempts }; + const nextTask = runAt ? { state: nextState, runAt } : { state: nextState }; + return nextTask; + }; + + private restartTransform = async ( + esClient: ElasticsearchClient, + transform: TransformGetTransformStatsTransformStats, + currentAttempts: number = 0 + ) => { + let attempts = currentAttempts; + let didAttemptRestart = false; + + if (!WARNING_TRANSFORM_STATES.has(transform.state)) { + return { + attempts, + didAttemptRestart, + }; + } + + if (attempts > MAX_ATTEMPTS) { + this.logger.warn( + `transform ${transform.id} has failed to restart ${attempts} times. stopping auto restart attempts.` + ); + return { + attempts, + didAttemptRestart, + }; + } + + try { + this.logger.info(`failed transform detected with id: ${transform.id}. attempting restart.`); + await esClient.transform.stopTransform({ + transform_id: transform.id, + allow_no_match: true, + wait_for_completion: true, + force: true, + }); + await esClient.transform.startTransform({ + transform_id: transform.id, + }); + + // restart succeeded, reset attempt count + attempts = 0; + } catch (e) { + const err = wrapErrorIfNeeded(e); + const errMessage = `failed to restart transform ${transform.id} with error: ${err}`; + this.logger.error(errMessage); + + // restart failed, increment attempt count + attempts = attempts + 1; + } finally { + didAttemptRestart = true; + } + + return { + attempts, + didAttemptRestart, + }; + }; + + private getTaskId = (): string => { + return `${TYPE}:${VERSION}`; + }; +} diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/index.ts b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/index.ts new file mode 100644 index 0000000000000..6f5d6f5a4121b --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/index.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './check_metadata_transforms_task'; diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 391beb3c40121..f69565cacceb5 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -59,6 +59,7 @@ import { initRoutes } from './routes'; import { isAlertExecutor } from './lib/detection_engine/signals/types'; import { signalRulesAlertType } from './lib/detection_engine/signals/signal_rule_alert_type'; import { ManifestTask } from './endpoint/lib/artifacts'; +import { CheckMetadataTransformsTask } from './endpoint/lib/metadata'; import { initSavedObjects } from './saved_objects'; import { AppClientFactory } from './client'; import { createConfig, ConfigType } from './config'; @@ -157,6 +158,7 @@ export class Plugin implements IPlugin; private telemetryUsageCounter?: UsageCounter; @@ -363,6 +365,12 @@ export class Plugin implements IPlugin Date: Mon, 4 Oct 2021 10:52:05 -0400 Subject: [PATCH 38/98] [Fleet] Fix how we get the default output in the Fleet UI (#113620) --- .../fleet_server_on_prem_instructions.tsx | 6 ++---- .../public/components/settings_flyout/index.tsx | 5 ++--- .../fleet/public/hooks/use_request/outputs.ts | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions.tsx index 1d43f90b80def..a8cab77af447c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/components/fleet_server_on_prem_instructions.tsx @@ -31,7 +31,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { DownloadStep } from '../../../../components'; import { useStartServices, - useGetOutputs, + useDefaultOutput, sendGenerateServiceToken, usePlatform, PLATFORM_OPTIONS, @@ -242,7 +242,7 @@ export const FleetServerCommandStep = ({ }; export const useFleetServerInstructions = (policyId?: string) => { - const outputsRequest = useGetOutputs(); + const { output, refresh: refreshOutputs } = useDefaultOutput(); const { notifications } = useStartServices(); const [serviceToken, setServiceToken] = useState(); const [isLoadingServiceToken, setIsLoadingServiceToken] = useState(false); @@ -250,9 +250,7 @@ export const useFleetServerInstructions = (policyId?: string) => { const [deploymentMode, setDeploymentMode] = useState('production'); const { data: settings, resendRequest: refreshSettings } = useGetSettings(); const fleetServerHost = settings?.item.fleet_server_hosts?.[0]; - const output = outputsRequest.data?.items?.[0]; const esHost = output?.hosts?.[0]; - const refreshOutputs = outputsRequest.resendRequest; const installCommand = useMemo((): string => { if (!serviceToken || !esHost) { diff --git a/x-pack/plugins/fleet/public/components/settings_flyout/index.tsx b/x-pack/plugins/fleet/public/components/settings_flyout/index.tsx index e42733bbd2da0..9bedfca0d3bca 100644 --- a/x-pack/plugins/fleet/public/components/settings_flyout/index.tsx +++ b/x-pack/plugins/fleet/public/components/settings_flyout/index.tsx @@ -36,7 +36,7 @@ import { useGetSettings, useInput, sendPutSettings, - useGetOutputs, + useDefaultOutput, sendPutOutput, } from '../../hooks'; import { isDiffPathProtocol, normalizeHostsForAgents } from '../../../common'; @@ -258,8 +258,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { const settingsRequest = useGetSettings(); const settings = settingsRequest?.data?.item; - const outputsRequest = useGetOutputs(); - const output = outputsRequest.data?.items?.[0]; + const { output } = useDefaultOutput(); const { inputs, submit, validate, isLoading } = useSettingsForm(output?.id, onClose); const [isConfirmModalVisible, setConfirmModalVisible] = React.useState(false); diff --git a/x-pack/plugins/fleet/public/hooks/use_request/outputs.ts b/x-pack/plugins/fleet/public/hooks/use_request/outputs.ts index 0fcaa262cf321..2d623da505c65 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/outputs.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/outputs.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { useMemo, useCallback } from 'react'; + import { outputRoutesService } from '../../services'; import type { PutOutputRequest, GetOutputsResponse } from '../../types'; @@ -17,6 +19,21 @@ export function useGetOutputs() { }); } +export function useDefaultOutput() { + const outputsRequest = useGetOutputs(); + const output = useMemo(() => { + return outputsRequest.data?.items.find((o) => o.is_default); + }, [outputsRequest.data]); + + const refresh = useCallback(() => { + return outputsRequest.resendRequest(); + }, [outputsRequest]); + + return useMemo(() => { + return { output, refresh }; + }, [output, refresh]); +} + export function sendPutOutput(outputId: string, body: PutOutputRequest['body']) { return sendRequest({ method: 'put', From c558f26dd13e7949edf19071d9eaa15d5dd05bad Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Mon, 4 Oct 2021 17:55:49 +0300 Subject: [PATCH 39/98] [TSVB] Update the series and metrics Ids that are numbers to strings (#113619) * [TSVB] Update the series and metrics Ids that are numbers to strings * Minor changes * Adds a unit test to TSVB plugin to test this case Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../timeseries/public/vis_state.test.ts | 126 ++++++++++++++++++ .../public/legacy/vis_update_state.js | 28 ++++ .../public/legacy/vis_update_state.test.js | 83 ++++++++++++ 3 files changed, 237 insertions(+) create mode 100644 src/plugins/vis_types/timeseries/public/vis_state.test.ts diff --git a/src/plugins/vis_types/timeseries/public/vis_state.test.ts b/src/plugins/vis_types/timeseries/public/vis_state.test.ts new file mode 100644 index 0000000000000..82e52a0493391 --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/vis_state.test.ts @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { updateOldState } from '../../../visualizations/public'; + +/** + * The reason we add this test is to ensure that `convertNumIdsToStringsForTSVB` of the updateOldState runs correctly + * for the TSVB vis state. As the `updateOldState` runs on the visualizations plugin. a change to our objects structure can + * result to forget this case. + * Just for reference the `convertNumIdsToStringsForTSVB` finds and converts the series and metrics ids that have only digits to strings + * by adding an x prefix. Number ids are never been generated from the editor, only programmatically. + * See https://github.com/elastic/kibana/issues/113601. + */ +describe('TimeseriesVisState', () => { + test('should format the TSVB visState correctly', () => { + const visState = { + title: 'test', + type: 'metrics', + aggs: [], + params: { + time_range_mode: 'entire_time_range', + id: '0ecc58b1-30ba-43b9-aa3f-9ac32b482497', + type: 'timeseries', + series: [ + { + id: '1', + color: '#68BC00', + split_mode: 'terms', + palette: { + type: 'palette', + name: 'default', + }, + metrics: [ + { + id: '10', + type: 'count', + }, + ], + separate_axis: 0, + axis_position: 'right', + formatter: 'default', + chart_type: 'line', + line_width: 1, + point_size: 1, + fill: 0.5, + stacked: 'none', + terms_field: 'Cancelled', + }, + ], + time_field: '', + use_kibana_indexes: true, + interval: '', + axis_position: 'left', + axis_formatter: 'number', + axis_scale: 'normal', + show_legend: 1, + truncate_legend: 1, + max_lines_legend: 1, + show_grid: 1, + tooltip_mode: 'show_all', + drop_last_bucket: 0, + isModelInvalid: false, + index_pattern: { + id: '665cd2c0-21d6-11ec-b42f-f7077c64d21b', + }, + }, + }; + const newVisState = updateOldState(visState); + expect(newVisState).toEqual({ + aggs: [], + params: { + axis_formatter: 'number', + axis_position: 'left', + axis_scale: 'normal', + drop_last_bucket: 0, + id: '0ecc58b1-30ba-43b9-aa3f-9ac32b482497', + index_pattern: { + id: '665cd2c0-21d6-11ec-b42f-f7077c64d21b', + }, + interval: '', + isModelInvalid: false, + max_lines_legend: 1, + series: [ + { + axis_position: 'right', + chart_type: 'line', + color: '#68BC00', + fill: 0.5, + formatter: 'default', + id: 'x1', + line_width: 1, + metrics: [ + { + id: 'x10', + type: 'count', + }, + ], + palette: { + name: 'default', + type: 'palette', + }, + point_size: 1, + separate_axis: 0, + split_mode: 'terms', + stacked: 'none', + terms_field: 'Cancelled', + }, + ], + show_grid: 1, + show_legend: 1, + time_field: '', + time_range_mode: 'entire_time_range', + tooltip_mode: 'show_all', + truncate_legend: 1, + type: 'timeseries', + use_kibana_indexes: true, + }, + title: 'test', + type: 'metrics', + }); + }); +}); diff --git a/src/plugins/visualizations/public/legacy/vis_update_state.js b/src/plugins/visualizations/public/legacy/vis_update_state.js index d0ebe00b1a6f0..db6a9f2beb776 100644 --- a/src/plugins/visualizations/public/legacy/vis_update_state.js +++ b/src/plugins/visualizations/public/legacy/vis_update_state.js @@ -136,6 +136,30 @@ function convertSeriesParams(visState) { ]; } +/** + * This function is responsible for updating old TSVB visStates. + * Specifically, it identifies if the series and metrics ids are numbers + * and convert them to string with an x prefix. Number ids are never been generated + * from the editor, only programmatically. See https://github.com/elastic/kibana/issues/113601. + */ +function convertNumIdsToStringsForTSVB(visState) { + if (visState.params.series) { + visState.params.series.forEach((s) => { + const seriesId = s.id; + const metrics = s.metrics; + if (!isNaN(seriesId)) { + s.id = `x${seriesId}`; + } + metrics?.forEach((m) => { + const metricId = m.id; + if (!isNaN(metricId)) { + m.id = `x${metricId}`; + } + }); + }); + } +} + /** * This function is responsible for updating old visStates - the actual saved object * object - into the format, that will be required by the current Kibana version. @@ -155,6 +179,10 @@ export const updateOldState = (visState) => { convertSeriesParams(newState); } + if (visState.params && visState.type === 'metrics') { + convertNumIdsToStringsForTSVB(newState); + } + if (visState.type === 'gauge' && visState.fontSize) { delete newState.fontSize; set(newState, 'gauge.style.fontSize', visState.fontSize); diff --git a/src/plugins/visualizations/public/legacy/vis_update_state.test.js b/src/plugins/visualizations/public/legacy/vis_update_state.test.js index 3b0d732df2d1a..a7c2df506d313 100644 --- a/src/plugins/visualizations/public/legacy/vis_update_state.test.js +++ b/src/plugins/visualizations/public/legacy/vis_update_state.test.js @@ -93,4 +93,87 @@ describe('updateOldState', () => { expect(state.params.showMeticsAtAllLevels).toBe(undefined); }); }); + + describe('TSVB ids conversion', () => { + it('should update the seriesId from number to string with x prefix', () => { + const oldState = { + type: 'metrics', + params: { + series: [ + { + id: '10', + }, + { + id: 'ABC', + }, + { + id: 1, + }, + ], + }, + }; + const state = updateOldState(oldState); + expect(state.params.series).toEqual([ + { + id: 'x10', + }, + { + id: 'ABC', + }, + { + id: 'x1', + }, + ]); + }); + it('should update the metrics ids from number to string with x prefix', () => { + const oldState = { + type: 'metrics', + params: { + series: [ + { + id: '10', + metrics: [ + { + id: '1000', + }, + { + id: '74a66e70-ac44-11eb-9865-6b616e971cf8', + }, + ], + }, + { + id: 'ABC', + metrics: [ + { + id: null, + }, + ], + }, + ], + }, + }; + const state = updateOldState(oldState); + expect(state.params.series).toEqual([ + { + id: 'x10', + metrics: [ + { + id: 'x1000', + }, + { + id: '74a66e70-ac44-11eb-9865-6b616e971cf8', + }, + ], + }, + { + id: 'ABC', + metrics: [ + { + id: 'xnull', + }, + ], + }, + ]); + }); + }); }); From 252278a433850ed7775debcd1c74b8e63ef286ba Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Mon, 4 Oct 2021 10:57:32 -0400 Subject: [PATCH 40/98] [buildkite] Fix packer cache issues (#113769) --- .buildkite/scripts/common/env.sh | 4 ++-- .buildkite/scripts/packer_cache.sh | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.buildkite/scripts/common/env.sh b/.buildkite/scripts/common/env.sh index 89121581c75d1..ac80a66d33fa0 100755 --- a/.buildkite/scripts/common/env.sh +++ b/.buildkite/scripts/common/env.sh @@ -56,8 +56,8 @@ else fi # These are for backwards-compatibility -export GIT_COMMIT="$BUILDKITE_COMMIT" -export GIT_BRANCH="$BUILDKITE_BRANCH" +export GIT_COMMIT="${BUILDKITE_COMMIT:-}" +export GIT_BRANCH="${BUILDKITE_BRANCH:-}" export FLEET_PACKAGE_REGISTRY_PORT=6104 export TEST_CORS_SERVER_PORT=6105 diff --git a/.buildkite/scripts/packer_cache.sh b/.buildkite/scripts/packer_cache.sh index 45d3dc439ff4d..617ea79c827b0 100755 --- a/.buildkite/scripts/packer_cache.sh +++ b/.buildkite/scripts/packer_cache.sh @@ -2,6 +2,7 @@ set -euo pipefail +source .buildkite/scripts/common/util.sh source .buildkite/scripts/common/env.sh source .buildkite/scripts/common/setup_node.sh From 3d7e04b799b11407e2689cde532a7f82297b4874 Mon Sep 17 00:00:00 2001 From: Domenico Andreoli Date: Mon, 4 Oct 2021 17:04:24 +0200 Subject: [PATCH 41/98] [Security] Add EQL rule test in CCS config (#112852) --- .../event_correlation_rule.spec.ts | 55 ++ .../security_solution/cypress/objects/rule.ts | 23 + .../cypress/tasks/api_calls/rules.ts | 31 +- .../es_archives/linux_process/data.json | 135 +++ .../es_archives/linux_process/mappings.json | 935 ++++++++++++++++++ 5 files changed, 1178 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/security_solution/cypress/ccs_integration/detection_rules/event_correlation_rule.spec.ts create mode 100644 x-pack/test/security_solution_cypress/es_archives/linux_process/data.json create mode 100644 x-pack/test/security_solution_cypress/es_archives/linux_process/mappings.json diff --git a/x-pack/plugins/security_solution/cypress/ccs_integration/detection_rules/event_correlation_rule.spec.ts b/x-pack/plugins/security_solution/cypress/ccs_integration/detection_rules/event_correlation_rule.spec.ts new file mode 100644 index 0000000000000..c20e6cf6b6370 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/ccs_integration/detection_rules/event_correlation_rule.spec.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { esArchiverCCSLoad } from '../../tasks/es_archiver'; +import { getCCSEqlRule } from '../../objects/rule'; + +import { ALERT_DATA_GRID, NUMBER_OF_ALERTS } from '../../screens/alerts'; + +import { + filterByCustomRules, + goToRuleDetails, + waitForRulesTableToBeLoaded, +} from '../../tasks/alerts_detection_rules'; +import { createSignalsIndex, createEventCorrelationRule } from '../../tasks/api_calls/rules'; +import { cleanKibana } from '../../tasks/common'; +import { waitForAlertsToPopulate, waitForTheRuleToBeExecuted } from '../../tasks/create_new_rule'; +import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login'; + +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; + +describe('Detection rules', function () { + const expectedNumberOfAlerts = '1 alert'; + + beforeEach('Reset signals index', function () { + cleanKibana(); + createSignalsIndex(); + }); + + it('EQL rule on remote indices generates alerts', function () { + esArchiverCCSLoad('linux_process'); + this.rule = getCCSEqlRule(); + createEventCorrelationRule(this.rule); + + loginAndWaitForPageWithoutDateRange(DETECTIONS_RULE_MANAGEMENT_URL); + waitForRulesTableToBeLoaded(); + filterByCustomRules(); + goToRuleDetails(); + waitForTheRuleToBeExecuted(); + waitForAlertsToPopulate(); + + cy.get(NUMBER_OF_ALERTS).should('have.text', expectedNumberOfAlerts); + cy.get(ALERT_DATA_GRID) + .invoke('text') + .then((text) => { + cy.log('ALERT_DATA_GRID', text); + expect(text).contains(this.rule.name); + expect(text).contains(this.rule.severity.toLowerCase()); + expect(text).contains(this.rule.riskScore); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts index 173bfa524e66e..db76bfc3cf4df 100644 --- a/x-pack/plugins/security_solution/cypress/objects/rule.ts +++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts @@ -72,6 +72,10 @@ export interface OverrideRule extends CustomRule { timestampOverride: string; } +export interface EventCorrelationRule extends CustomRule { + language: string; +} + export interface ThreatIndicatorRule extends CustomRule { indicatorIndexPattern: string[]; indicatorMappingField: string; @@ -326,6 +330,25 @@ export const getEqlRule = (): CustomRule => ({ maxSignals: 100, }); +export const getCCSEqlRule = (): EventCorrelationRule => ({ + customQuery: 'any where process.name == "run-parts"', + name: 'New EQL Rule', + index: [`${ccsRemoteName}:run-parts`], + description: 'New EQL rule description.', + severity: 'High', + riskScore: '17', + tags: ['test', 'newRule'], + referenceUrls: ['http://example.com/', 'https://example.com/'], + falsePositivesExamples: ['False1', 'False2'], + mitre: [getMitre1(), getMitre2()], + note: '# test markdown', + runsEvery: getRunsEvery(), + lookBack: getLookBack(), + timeline: getTimeline(), + maxSignals: 100, + language: 'eql', +}); + export const getEqlSequenceRule = (): CustomRule => ({ customQuery: 'sequence with maxspan=30s\ diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts index 33bd8a06b9985..130467cde053d 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/rules.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CustomRule, ThreatIndicatorRule } from '../../objects/rule'; +import { CustomRule, EventCorrelationRule, ThreatIndicatorRule } from '../../objects/rule'; export const createCustomRule = (rule: CustomRule, ruleId = 'rule_testing', interval = '100m') => cy.request({ @@ -29,6 +29,27 @@ export const createCustomRule = (rule: CustomRule, ruleId = 'rule_testing', inte failOnStatusCode: false, }); +export const createEventCorrelationRule = (rule: EventCorrelationRule, ruleId = 'rule_testing') => + cy.request({ + method: 'POST', + url: 'api/detection_engine/rules', + body: { + rule_id: ruleId, + risk_score: parseInt(rule.riskScore, 10), + description: rule.description, + interval: `${rule.runsEvery.interval}${rule.runsEvery.type}`, + from: `now-${rule.lookBack.interval}${rule.lookBack.type}`, + name: rule.name, + severity: rule.severity.toLocaleLowerCase(), + type: 'eql', + index: rule.index, + query: rule.customQuery, + language: 'eql', + enabled: true, + }, + headers: { 'kbn-xsrf': 'cypress-creds' }, + }); + export const createCustomIndicatorRule = (rule: ThreatIndicatorRule, ruleId = 'rule_testing') => cy.request({ method: 'POST', @@ -107,6 +128,14 @@ export const deleteCustomRule = (ruleId = '1') => { }); }; +export const createSignalsIndex = () => { + cy.request({ + method: 'POST', + url: 'api/detection_engine/index', + headers: { 'kbn-xsrf': 'cypress-creds' }, + }); +}; + export const removeSignalsIndex = () => { cy.request({ url: '/api/detection_engine/index', failOnStatusCode: false }).then((response) => { if (response.status === 200) { diff --git a/x-pack/test/security_solution_cypress/es_archives/linux_process/data.json b/x-pack/test/security_solution_cypress/es_archives/linux_process/data.json new file mode 100644 index 0000000000000..ed29f3fe3e4e1 --- /dev/null +++ b/x-pack/test/security_solution_cypress/es_archives/linux_process/data.json @@ -0,0 +1,135 @@ +{ + "type": "doc", + "value": { + "id": "qxnqn3sBBf0WZxoXk7tg", + "index": "run-parts", + "source": { + "@timestamp": "2021-09-01T05:52:29.9451497Z", + "agent": { + "id": "cda623db-f791-4869-a63d-5b8352dfaa56", + "type": "endpoint", + "version": "7.14.0" + }, + "data_stream": { + "dataset": "endpoint.events.process", + "namespace": "default", + "type": "logs" + }, + "ecs": { + "version": "1.6.0" + }, + "elastic": { + "agent": { + "id": "cda623db-f791-4869-a63d-5b8352dfaa56" + } + }, + "event": { + "action": "exec", + "agent_id_status": "verified", + "category": [ + "process" + ], + "created": "2021-09-01T05:52:29.9451497Z", + "dataset": "endpoint.events.process", + "id": "MGwI0NpfzFKkX6gW+++++CVd", + "ingested": "2021-09-01T05:52:35.677424686Z", + "kind": "event", + "module": "endpoint", + "sequence": 3523, + "type": [ + "start" + ] + }, + "group": { + "Ext": { + "real": { + "id": 0, + "name": "root" + } + }, + "id": 0, + "name": "root" + }, + "host": { + "architecture": "x86_64", + "hostname": "localhost", + "id": "f5c59e5f0c963f828782bc413653d324", + "ip": [ + "127.0.0.1", + "::1" + ], + "mac": [ + "00:16:3e:10:96:79" + ], + "name": "localhost", + "os": { + "Ext": { + "variant": "Debian" + }, + "family": "debian", + "full": "Debian 10", + "kernel": "4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18)", + "name": "Linux", + "platform": "debian", + "version": "10" + } + }, + "message": "Endpoint process event", + "process": { + "Ext": { + "ancestry": [ + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEzNTAtMTMyNzQ5NDkxNDkuOTM2Njk1MDAw", + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEzNTAtMTMyNzQ5NDkxNDkuOTMwNzYyMTAw", + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEzNDktMTMyNzQ5NDkxNDkuOTI4OTI0ODAw", + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEzNDktMTMyNzQ5NDkxNDkuOTI3NDgwMzAw", + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEzNDEtMTMyNzQ5NDkxNDYuNTI3ODA5NTAw", + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEzNDEtMTMyNzQ5NDkxNDYuNTIzNzEzOTAw", + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTczOC0xMzI3NDk0ODg3OS4yNzgyMjQwMDA=", + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTczOC0xMzI3NDk0ODg3OS4yNTQ1MTUzMDA=", + "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEtMTMyNzQ5NDg4NjkuMA==" + ] + }, + "args": [ + "run-parts", + "--lsbsysinit", + "/etc/update-motd.d" + ], + "args_count": 3, + "command_line": "run-parts --lsbsysinit /etc/update-motd.d", + "entity_id": "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEzNTAtMTMyNzQ5NDkxNDkuOTQ1MTQ5NzAw", + "executable": "/usr/bin/run-parts", + "hash": { + "md5": "c83b0578484bf5267893d795b55928bd", + "sha1": "46b6e74e28e5daf69c1dd0f18a8e911ae2922dda", + "sha256": "3346b4d47c637a8c02cb6865eee42d2a5aa9c4e46c6371a9143621348d27420f" + }, + "name": "run-parts", + "parent": { + "args": [ + "sh", + "-c", + "/usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d > /run/motd.dynamic.new" + ], + "args_count": 0, + "command_line": "sh -c /usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d > /run/motd.dynamic.new", + "entity_id": "Y2ZhNjk5ZGItYzI5My00ODY5LWI2OGMtNWI4MzE0ZGZhYTU2LTEzNTAtMTMyNzQ5NDkxNDkuOTM2Njk1MDAw", + "executable": "/", + "name": "", + "pid": 1349 + }, + "pid": 1350 + }, + "user": { + "Ext": { + "real": { + "id": 0, + "name": "root" + } + }, + "id": 0, + "name": "root" + } + }, + "type": "_doc" + } +} diff --git a/x-pack/test/security_solution_cypress/es_archives/linux_process/mappings.json b/x-pack/test/security_solution_cypress/es_archives/linux_process/mappings.json new file mode 100644 index 0000000000000..d244defbdab0b --- /dev/null +++ b/x-pack/test/security_solution_cypress/es_archives/linux_process/mappings.json @@ -0,0 +1,935 @@ +{ + "type": "index", + "value": { + "aliases": { + }, + "index": "run-parts", + "mappings": { + "_data_stream_timestamp": { + "enabled": true + }, + "_meta": { + "managed": true, + "managed_by": "ingest-manager", + "package": { + "name": "endpoint" + } + }, + "date_detection": false, + "dynamic": "false", + "dynamic_templates": [ + { + "strings_as_keyword": { + "mapping": { + "ignore_above": 1024, + "type": "keyword" + }, + "match_mapping_type": "string" + } + } + ], + "properties": { + "@timestamp": { + "type": "date" + }, + "agent": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "data_stream": { + "properties": { + "dataset": { + "type": "constant_keyword", + "value": "endpoint.events.process" + }, + "namespace": { + "type": "constant_keyword", + "value": "default" + }, + "type": { + "type": "constant_keyword", + "value": "logs" + } + } + }, + "destination": { + "properties": { + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "agent_id_status": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "group": { + "properties": { + "Ext": { + "properties": { + "real": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "Ext": { + "properties": { + "variant": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "message": { + "type": "text" + }, + "package": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "properties": { + "Ext": { + "properties": { + "ancestry": { + "ignore_above": 1024, + "type": "keyword" + }, + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "authentication_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + }, + "type": "nested" + }, + "defense_evasions": { + "ignore_above": 1024, + "type": "keyword" + }, + "dll": { + "properties": { + "Ext": { + "properties": { + "mapped_address": { + "type": "unsigned_long" + }, + "mapped_size": { + "type": "unsigned_long" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "protection": { + "ignore_above": 1024, + "type": "keyword" + }, + "session": { + "ignore_above": 1024, + "type": "keyword" + }, + "token": { + "properties": { + "elevation": { + "type": "boolean" + }, + "elevation_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "elevation_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "integrity_level_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "Ext": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + }, + "type": "nested" + }, + "protection": { + "ignore_above": 1024, + "type": "keyword" + }, + "real": { + "properties": { + "pid": { + "type": "long" + } + } + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "thread": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + }, + "working_directory": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "thread": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + }, + "working_directory": { + "fields": { + "caseless": { + "ignore_above": 1024, + "normalizer": "lowercase", + "type": "keyword" + }, + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "source": { + "properties": { + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "user": { + "properties": { + "Ext": { + "properties": { + "real": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "Ext": { + "properties": { + "real": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} From 10ca6f42d6910352bb592ccc1d6ee8faf714488d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Mon, 4 Oct 2021 11:11:08 -0400 Subject: [PATCH 42/98] [APM] Show APM Server stand-alone mode in Kibana Upgrade Assistant (cloud-only) (#113567) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/deprecations/deprecations.test.ts | 70 ++++++++++++++++++ .../plugins/apm/server/deprecations/index.ts | 74 +++++++++++++++++++ x-pack/plugins/apm/server/plugin.ts | 7 ++ 3 files changed, 151 insertions(+) create mode 100644 x-pack/plugins/apm/server/deprecations/deprecations.test.ts create mode 100644 x-pack/plugins/apm/server/deprecations/index.ts diff --git a/x-pack/plugins/apm/server/deprecations/deprecations.test.ts b/x-pack/plugins/apm/server/deprecations/deprecations.test.ts new file mode 100644 index 0000000000000..d706146faf212 --- /dev/null +++ b/x-pack/plugins/apm/server/deprecations/deprecations.test.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { GetDeprecationsContext } from '../../../../../src/core/server'; +import { CloudSetup } from '../../../cloud/server'; +import { getDeprecations } from './'; +import { APMRouteHandlerResources } from '../'; +import { AgentPolicy } from '../../../fleet/common'; + +const deprecationContext = { + esClient: {}, + savedObjectsClient: {}, +} as GetDeprecationsContext; + +describe('getDeprecations', () => { + describe('when fleet is disabled', () => { + it('returns no deprecations', async () => { + const deprecationsCallback = getDeprecations({}); + const deprecations = await deprecationsCallback(deprecationContext); + expect(deprecations).toEqual([]); + }); + }); + + describe('when running on cloud with legacy apm-server', () => { + it('returns deprecations', async () => { + const deprecationsCallback = getDeprecations({ + cloudSetup: { isCloudEnabled: true } as unknown as CloudSetup, + fleet: { + start: () => ({ + agentPolicyService: { get: () => undefined }, + }), + } as unknown as APMRouteHandlerResources['plugins']['fleet'], + }); + const deprecations = await deprecationsCallback(deprecationContext); + expect(deprecations).not.toEqual([]); + }); + }); + + describe('when running on cloud with fleet', () => { + it('returns no deprecations', async () => { + const deprecationsCallback = getDeprecations({ + cloudSetup: { isCloudEnabled: true } as unknown as CloudSetup, + fleet: { + start: () => ({ + agentPolicyService: { get: () => ({ id: 'foo' } as AgentPolicy) }, + }), + } as unknown as APMRouteHandlerResources['plugins']['fleet'], + }); + const deprecations = await deprecationsCallback(deprecationContext); + expect(deprecations).toEqual([]); + }); + }); + + describe('when running on prem', () => { + it('returns no deprecations', async () => { + const deprecationsCallback = getDeprecations({ + cloudSetup: { isCloudEnabled: false } as unknown as CloudSetup, + fleet: { + start: () => ({ agentPolicyService: { get: () => undefined } }), + } as unknown as APMRouteHandlerResources['plugins']['fleet'], + }); + const deprecations = await deprecationsCallback(deprecationContext); + expect(deprecations).toEqual([]); + }); + }); +}); diff --git a/x-pack/plugins/apm/server/deprecations/index.ts b/x-pack/plugins/apm/server/deprecations/index.ts new file mode 100644 index 0000000000000..b592a2bf13268 --- /dev/null +++ b/x-pack/plugins/apm/server/deprecations/index.ts @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { GetDeprecationsContext, DeprecationsDetails } from 'src/core/server'; +import { i18n } from '@kbn/i18n'; +import { isEmpty } from 'lodash'; +import { CloudSetup } from '../../../cloud/server'; +import { getCloudAgentPolicy } from '../lib/fleet/get_cloud_apm_package_policy'; +import { APMRouteHandlerResources } from '../'; + +export function getDeprecations({ + cloudSetup, + fleet, +}: { + cloudSetup?: CloudSetup; + fleet?: APMRouteHandlerResources['plugins']['fleet']; +}) { + return async ({ + savedObjectsClient, + }: GetDeprecationsContext): Promise => { + const deprecations: DeprecationsDetails[] = []; + if (!fleet) { + return deprecations; + } + + const fleetPluginStart = await fleet.start(); + const cloudAgentPolicy = await getCloudAgentPolicy({ + fleetPluginStart, + savedObjectsClient, + }); + + const isCloudEnabled = !!cloudSetup?.isCloudEnabled; + + const hasCloudAgentPolicy = !isEmpty(cloudAgentPolicy); + + if (isCloudEnabled && !hasCloudAgentPolicy) { + deprecations.push({ + title: i18n.translate('xpack.apm.deprecations.legacyModeTitle', { + defaultMessage: 'APM Server running in legacy mode', + }), + message: i18n.translate('xpack.apm.deprecations.message', { + defaultMessage: + 'Running the APM Server binary directly is considered a legacy option and is deprecated since 7.16. Switch to APM Server managed by an Elastic Agent instead. Read our documentation to learn more.', + }), + documentationUrl: + 'https://www.elastic.co/guide/en/apm/server/current/apm-integration.html', + level: 'warning', + correctiveActions: { + manualSteps: [ + i18n.translate('xpack.apm.deprecations.steps.apm', { + defaultMessage: 'Navigate to Observability/APM', + }), + i18n.translate('xpack.apm.deprecations.steps.settings', { + defaultMessage: 'Click on "Settings"', + }), + i18n.translate('xpack.apm.deprecations.steps.schema', { + defaultMessage: 'Select "Schema" tab', + }), + i18n.translate('xpack.apm.deprecations.steps.switch', { + defaultMessage: + 'Click "Switch to data streams". You will be guided through the process', + }), + ], + }, + }); + } + + return deprecations; + }; +} diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index 56185d846562f..2296227de2a33 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -51,6 +51,7 @@ import { TRANSACTION_TYPE, } from '../common/elasticsearch_fieldnames'; import { tutorialProvider } from './tutorial'; +import { getDeprecations } from './deprecations'; export class APMPlugin implements @@ -222,6 +223,12 @@ export class APMPlugin ); })(); }); + core.deprecations.registerDeprecations({ + getDeprecations: getDeprecations({ + cloudSetup: plugins.cloud, + fleet: resourcePlugins.fleet, + }), + }); return { config$: mergedConfig$, From 4693c3812e5decfefcb6bc8835702e141a5f3ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 4 Oct 2021 16:19:03 +0100 Subject: [PATCH 43/98] =?UTF-8?q?[console]=C2=A0Deprecate=20"proxyFilter"?= =?UTF-8?q?=20and=20"proxyConfig"=20on=208.x=20(#113555)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/console/common/constants/index.ts | 9 ++ .../console/common/constants/plugin.ts | 9 ++ src/plugins/console/kibana.json | 4 +- src/plugins/console/server/config.ts | 87 ++++++++++----- src/plugins/console/server/index.ts | 9 +- src/plugins/console/server/plugin.ts | 22 +++- .../api/console/proxy/create_handler.ts | 44 +++++--- .../server/routes/api/console/proxy/mocks.ts | 32 ++++-- .../routes/api/console/proxy/params.test.ts | 104 ++++++++++-------- src/plugins/console/server/routes/index.ts | 6 +- 10 files changed, 214 insertions(+), 112 deletions(-) create mode 100644 src/plugins/console/common/constants/index.ts create mode 100644 src/plugins/console/common/constants/plugin.ts diff --git a/src/plugins/console/common/constants/index.ts b/src/plugins/console/common/constants/index.ts new file mode 100644 index 0000000000000..0a8dac9b7fff3 --- /dev/null +++ b/src/plugins/console/common/constants/index.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { MAJOR_VERSION } from './plugin'; diff --git a/src/plugins/console/common/constants/plugin.ts b/src/plugins/console/common/constants/plugin.ts new file mode 100644 index 0000000000000..cd301ec296395 --- /dev/null +++ b/src/plugins/console/common/constants/plugin.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const MAJOR_VERSION = '8.0.0'; diff --git a/src/plugins/console/kibana.json b/src/plugins/console/kibana.json index 69c7176ff6a47..e2345514d76b9 100644 --- a/src/plugins/console/kibana.json +++ b/src/plugins/console/kibana.json @@ -1,12 +1,14 @@ { "id": "console", - "version": "kibana", + "version": "8.0.0", + "kibanaVersion": "kibana", "server": true, "ui": true, "owner": { "name": "Stack Management", "githubTeam": "kibana-stack-management" }, + "configPath": ["console"], "requiredPlugins": ["devTools", "share"], "optionalPlugins": ["usageCollection", "home"], "requiredBundles": ["esUiShared", "kibanaReact", "kibanaUtils", "home"] diff --git a/src/plugins/console/server/config.ts b/src/plugins/console/server/config.ts index 4e42e3c21d2ad..6d667fed081e8 100644 --- a/src/plugins/console/server/config.ts +++ b/src/plugins/console/server/config.ts @@ -6,37 +6,70 @@ * Side Public License, v 1. */ +import { SemVer } from 'semver'; import { schema, TypeOf } from '@kbn/config-schema'; +import { PluginConfigDescriptor } from 'kibana/server'; -export type ConfigType = TypeOf; +import { MAJOR_VERSION } from '../common/constants'; -export const config = schema.object( - { - enabled: schema.boolean({ defaultValue: true }), - proxyFilter: schema.arrayOf(schema.string(), { defaultValue: ['.*'] }), - ssl: schema.object({ verify: schema.boolean({ defaultValue: false }) }, {}), - proxyConfig: schema.arrayOf( - schema.object({ - match: schema.object({ - protocol: schema.string({ defaultValue: '*' }), - host: schema.string({ defaultValue: '*' }), - port: schema.string({ defaultValue: '*' }), - path: schema.string({ defaultValue: '*' }), - }), - - timeout: schema.number(), - ssl: schema.object( - { - verify: schema.boolean(), - ca: schema.arrayOf(schema.string()), - cert: schema.string(), - key: schema.string(), - }, - { defaultValue: undefined } - ), +const kibanaVersion = new SemVer(MAJOR_VERSION); + +const baseSettings = { + enabled: schema.boolean({ defaultValue: true }), + ssl: schema.object({ verify: schema.boolean({ defaultValue: false }) }, {}), +}; + +// Settings only available in 7.x +const deprecatedSettings = { + proxyFilter: schema.arrayOf(schema.string(), { defaultValue: ['.*'] }), + proxyConfig: schema.arrayOf( + schema.object({ + match: schema.object({ + protocol: schema.string({ defaultValue: '*' }), + host: schema.string({ defaultValue: '*' }), + port: schema.string({ defaultValue: '*' }), + path: schema.string({ defaultValue: '*' }), }), - { defaultValue: [] } - ), + + timeout: schema.number(), + ssl: schema.object( + { + verify: schema.boolean(), + ca: schema.arrayOf(schema.string()), + cert: schema.string(), + key: schema.string(), + }, + { defaultValue: undefined } + ), + }), + { defaultValue: [] } + ), +}; + +const configSchema = schema.object( + { + ...baseSettings, }, { defaultValue: undefined } ); + +const configSchema7x = schema.object( + { + ...baseSettings, + ...deprecatedSettings, + }, + { defaultValue: undefined } +); + +export type ConfigType = TypeOf; +export type ConfigType7x = TypeOf; + +export const config: PluginConfigDescriptor = { + schema: kibanaVersion.major < 8 ? configSchema7x : configSchema, + deprecations: ({ deprecate, unused }) => [ + deprecate('enabled', '8.0.0'), + deprecate('proxyFilter', '8.0.0'), + deprecate('proxyConfig', '8.0.0'), + unused('ssl'), + ], +}; diff --git a/src/plugins/console/server/index.ts b/src/plugins/console/server/index.ts index cd05652c62838..6ae518f5dc796 100644 --- a/src/plugins/console/server/index.ts +++ b/src/plugins/console/server/index.ts @@ -6,16 +6,11 @@ * Side Public License, v 1. */ -import { PluginConfigDescriptor, PluginInitializerContext } from 'kibana/server'; +import { PluginInitializerContext } from 'kibana/server'; -import { ConfigType, config as configSchema } from './config'; import { ConsoleServerPlugin } from './plugin'; export { ConsoleSetup, ConsoleStart } from './types'; +export { config } from './config'; export const plugin = (ctx: PluginInitializerContext) => new ConsoleServerPlugin(ctx); - -export const config: PluginConfigDescriptor = { - deprecations: ({ deprecate, unused, rename }) => [deprecate('enabled', '8.0.0'), unused('ssl')], - schema: configSchema, -}; diff --git a/src/plugins/console/server/plugin.ts b/src/plugins/console/server/plugin.ts index a5f1ca6107600..613337b286fbf 100644 --- a/src/plugins/console/server/plugin.ts +++ b/src/plugins/console/server/plugin.ts @@ -7,10 +7,11 @@ */ import { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'kibana/server'; +import { SemVer } from 'semver'; import { ProxyConfigCollection } from './lib'; import { SpecDefinitionsService, EsLegacyConfigService } from './services'; -import { ConfigType } from './config'; +import { ConfigType, ConfigType7x } from './config'; import { registerRoutes } from './routes'; @@ -23,7 +24,7 @@ export class ConsoleServerPlugin implements Plugin { esLegacyConfigService = new EsLegacyConfigService(); - constructor(private readonly ctx: PluginInitializerContext) { + constructor(private readonly ctx: PluginInitializerContext) { this.log = this.ctx.logger.get(); } @@ -34,10 +35,17 @@ export class ConsoleServerPlugin implements Plugin { save: true, }, })); - + const kibanaVersion = new SemVer(this.ctx.env.packageInfo.version); const config = this.ctx.config.get(); const globalConfig = this.ctx.config.legacy.get(); - const proxyPathFilters = config.proxyFilter.map((str: string) => new RegExp(str)); + + let pathFilters: RegExp[] | undefined; + let proxyConfigCollection: ProxyConfigCollection | undefined; + if (kibanaVersion.major < 8) { + // "pathFilters" and "proxyConfig" are only used in 7.x + pathFilters = (config as ConfigType7x).proxyFilter.map((str: string) => new RegExp(str)); + proxyConfigCollection = new ProxyConfigCollection((config as ConfigType7x).proxyConfig); + } this.esLegacyConfigService.setup(elasticsearch.legacy.config$); @@ -51,7 +59,6 @@ export class ConsoleServerPlugin implements Plugin { specDefinitionService: this.specDefinitionsService, }, proxy: { - proxyConfigCollection: new ProxyConfigCollection(config.proxyConfig), readLegacyESConfig: async (): Promise => { const legacyConfig = await this.esLegacyConfigService.readConfig(); return { @@ -59,8 +66,11 @@ export class ConsoleServerPlugin implements Plugin { ...legacyConfig, }; }, - pathFilters: proxyPathFilters, + // Deprecated settings (only used in 7.x): + proxyConfigCollection, + pathFilters, }, + kibanaVersion, }); return { diff --git a/src/plugins/console/server/routes/api/console/proxy/create_handler.ts b/src/plugins/console/server/routes/api/console/proxy/create_handler.ts index 8ca5720d559ce..9ece066246e4a 100644 --- a/src/plugins/console/server/routes/api/console/proxy/create_handler.ts +++ b/src/plugins/console/server/routes/api/console/proxy/create_handler.ts @@ -9,6 +9,7 @@ import { Agent, IncomingMessage } from 'http'; import * as url from 'url'; import { pick, trimStart, trimEnd } from 'lodash'; +import { SemVer } from 'semver'; import { KibanaRequest, RequestHandler } from 'kibana/server'; @@ -58,17 +59,22 @@ function filterHeaders(originalHeaders: object, headersToKeep: string[]): object function getRequestConfig( headers: object, esConfig: ESConfigForProxy, - proxyConfigCollection: ProxyConfigCollection, - uri: string + uri: string, + kibanaVersion: SemVer, + proxyConfigCollection?: ProxyConfigCollection ): { agent: Agent; timeout: number; headers: object; rejectUnauthorized?: boolean } { const filteredHeaders = filterHeaders(headers, esConfig.requestHeadersWhitelist); const newHeaders = setHeaders(filteredHeaders, esConfig.customHeaders); - if (proxyConfigCollection.hasConfig()) { - return { - ...proxyConfigCollection.configForUri(uri), - headers: newHeaders, - }; + if (kibanaVersion.major < 8) { + // In 7.x we still support the proxyConfig setting defined in kibana.yml + // From 8.x we don't support it anymore so we don't try to read it here. + if (proxyConfigCollection!.hasConfig()) { + return { + ...proxyConfigCollection!.configForUri(uri), + headers: newHeaders, + }; + } } return { @@ -106,18 +112,23 @@ export const createHandler = ({ log, proxy: { readLegacyESConfig, pathFilters, proxyConfigCollection }, + kibanaVersion, }: RouteDependencies): RequestHandler => async (ctx, request, response) => { const { body, query } = request; const { path, method } = query; - if (!pathFilters.some((re) => re.test(path))) { - return response.forbidden({ - body: `Error connecting to '${path}':\n\nUnable to send requests to that path.`, - headers: { - 'Content-Type': 'text/plain', - }, - }); + if (kibanaVersion.major < 8) { + // The "console.proxyFilter" setting in kibana.yaml has been deprecated in 8.x + // We only read it on the 7.x branch + if (!pathFilters!.some((re) => re.test(path))) { + return response.forbidden({ + body: `Error connecting to '${path}':\n\nUnable to send requests to that path.`, + headers: { + 'Content-Type': 'text/plain', + }, + }); + } } const legacyConfig = await readLegacyESConfig(); @@ -134,8 +145,9 @@ export const createHandler = const { timeout, agent, headers, rejectUnauthorized } = getRequestConfig( request.headers, legacyConfig, - proxyConfigCollection, - uri.toString() + uri.toString(), + kibanaVersion, + proxyConfigCollection ); const requestHeaders = { diff --git a/src/plugins/console/server/routes/api/console/proxy/mocks.ts b/src/plugins/console/server/routes/api/console/proxy/mocks.ts index 010e35ab505af..d06ca90adf556 100644 --- a/src/plugins/console/server/routes/api/console/proxy/mocks.ts +++ b/src/plugins/console/server/routes/api/console/proxy/mocks.ts @@ -5,28 +5,41 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { SemVer } from 'semver'; jest.mock('../../../../lib/proxy_request', () => ({ proxyRequest: jest.fn(), })); import { duration } from 'moment'; +import { MAJOR_VERSION } from '../../../../../common/constants'; import { ProxyConfigCollection } from '../../../../lib'; import { RouteDependencies, ProxyDependencies } from '../../../../routes'; import { EsLegacyConfigService, SpecDefinitionsService } from '../../../../services'; import { coreMock, httpServiceMock } from '../../../../../../../core/server/mocks'; -const defaultProxyValue = Object.freeze({ - readLegacyESConfig: async () => ({ - requestTimeout: duration(30000), - customHeaders: {}, - requestHeadersWhitelist: [], - hosts: ['http://localhost:9200'], - }), - pathFilters: [/.*/], - proxyConfigCollection: new ProxyConfigCollection([]), +const kibanaVersion = new SemVer(MAJOR_VERSION); + +const readLegacyESConfig = async () => ({ + requestTimeout: duration(30000), + customHeaders: {}, + requestHeadersWhitelist: [], + hosts: ['http://localhost:9200'], +}); + +let defaultProxyValue = Object.freeze({ + readLegacyESConfig, }); +if (kibanaVersion.major < 8) { + // In 7.x we still support the "pathFilter" and "proxyConfig" kibana.yml settings + defaultProxyValue = Object.freeze({ + readLegacyESConfig, + pathFilters: [/.*/], + proxyConfigCollection: new ProxyConfigCollection([]), + }); +} + interface MockDepsArgument extends Partial> { proxy?: Partial; } @@ -51,5 +64,6 @@ export const getProxyRouteHandlerDeps = ({ } : defaultProxyValue, log, + kibanaVersion, }; }; diff --git a/src/plugins/console/server/routes/api/console/proxy/params.test.ts b/src/plugins/console/server/routes/api/console/proxy/params.test.ts index e08d2f8adecbf..edefb2f11f1f1 100644 --- a/src/plugins/console/server/routes/api/console/proxy/params.test.ts +++ b/src/plugins/console/server/routes/api/console/proxy/params.test.ts @@ -5,14 +5,17 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { SemVer } from 'semver'; import { kibanaResponseFactory } from '../../../../../../../core/server'; -import { getProxyRouteHandlerDeps } from './mocks'; -import { createResponseStub } from './stubs'; +import { getProxyRouteHandlerDeps } from './mocks'; // import need to come first +import { createResponseStub } from './stubs'; // import needs to come first +import { MAJOR_VERSION } from '../../../../../common/constants'; import * as requestModule from '../../../../lib/proxy_request'; - import { createHandler } from './create_handler'; +const kibanaVersion = new SemVer(MAJOR_VERSION); + describe('Console Proxy Route', () => { let handler: ReturnType; @@ -21,58 +24,71 @@ describe('Console Proxy Route', () => { }); describe('params', () => { - describe('pathFilters', () => { - describe('no matches', () => { - it('rejects with 403', async () => { - handler = createHandler( - getProxyRouteHandlerDeps({ proxy: { pathFilters: [/^\/foo\//, /^\/bar\//] } }) - ); + if (kibanaVersion.major < 8) { + describe('pathFilters', () => { + describe('no matches', () => { + it('rejects with 403', async () => { + handler = createHandler( + getProxyRouteHandlerDeps({ + proxy: { pathFilters: [/^\/foo\//, /^\/bar\//] }, + }) + ); - const { status } = await handler( - {} as any, - { query: { method: 'POST', path: '/baz/id' } } as any, - kibanaResponseFactory - ); + const { status } = await handler( + {} as any, + { query: { method: 'POST', path: '/baz/id' } } as any, + kibanaResponseFactory + ); - expect(status).toBe(403); + expect(status).toBe(403); + }); }); - }); - describe('one match', () => { - it('allows the request', async () => { - handler = createHandler( - getProxyRouteHandlerDeps({ proxy: { pathFilters: [/^\/foo\//, /^\/bar\//] } }) - ); - (requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub('foo')); + describe('one match', () => { + it('allows the request', async () => { + handler = createHandler( + getProxyRouteHandlerDeps({ + proxy: { pathFilters: [/^\/foo\//, /^\/bar\//] }, + }) + ); + + (requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub('foo')); - const { status } = await handler( - {} as any, - { headers: {}, query: { method: 'POST', path: '/foo/id' } } as any, - kibanaResponseFactory - ); + const { status } = await handler( + {} as any, + { headers: {}, query: { method: 'POST', path: '/foo/id' } } as any, + kibanaResponseFactory + ); - expect(status).toBe(200); - expect((requestModule.proxyRequest as jest.Mock).mock.calls.length).toBe(1); + expect(status).toBe(200); + expect((requestModule.proxyRequest as jest.Mock).mock.calls.length).toBe(1); + }); }); - }); - describe('all match', () => { - it('allows the request', async () => { - handler = createHandler( - getProxyRouteHandlerDeps({ proxy: { pathFilters: [/^\/foo\//] } }) - ); - (requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub('foo')); + describe('all match', () => { + it('allows the request', async () => { + handler = createHandler( + getProxyRouteHandlerDeps({ proxy: { pathFilters: [/^\/foo\//] } }) + ); + + (requestModule.proxyRequest as jest.Mock).mockResolvedValue(createResponseStub('foo')); - const { status } = await handler( - {} as any, - { headers: {}, query: { method: 'GET', path: '/foo/id' } } as any, - kibanaResponseFactory - ); + const { status } = await handler( + {} as any, + { headers: {}, query: { method: 'GET', path: '/foo/id' } } as any, + kibanaResponseFactory + ); - expect(status).toBe(200); - expect((requestModule.proxyRequest as jest.Mock).mock.calls.length).toBe(1); + expect(status).toBe(200); + expect((requestModule.proxyRequest as jest.Mock).mock.calls.length).toBe(1); + }); }); }); - }); + } else { + // jest requires to have at least one test in the file + test('dummy required test', () => { + expect(true).toBe(true); + }); + } }); }); diff --git a/src/plugins/console/server/routes/index.ts b/src/plugins/console/server/routes/index.ts index 2c46547f92f1b..3911e8cfabc60 100644 --- a/src/plugins/console/server/routes/index.ts +++ b/src/plugins/console/server/routes/index.ts @@ -7,6 +7,7 @@ */ import { IRouter, Logger } from 'kibana/server'; +import { SemVer } from 'semver'; import { EsLegacyConfigService, SpecDefinitionsService } from '../services'; import { ESConfigForProxy } from '../types'; @@ -18,8 +19,8 @@ import { registerSpecDefinitionsRoute } from './api/console/spec_definitions'; export interface ProxyDependencies { readLegacyESConfig: () => Promise; - pathFilters: RegExp[]; - proxyConfigCollection: ProxyConfigCollection; + pathFilters?: RegExp[]; // Only present in 7.x + proxyConfigCollection?: ProxyConfigCollection; // Only present in 7.x } export interface RouteDependencies { @@ -30,6 +31,7 @@ export interface RouteDependencies { esLegacyConfigService: EsLegacyConfigService; specDefinitionService: SpecDefinitionsService; }; + kibanaVersion: SemVer; } export const registerRoutes = (dependencies: RouteDependencies) => { From 3d0da7f0f69aa37db96db7489566c8bd2198be58 Mon Sep 17 00:00:00 2001 From: Sandra G Date: Mon, 4 Oct 2021 11:37:19 -0400 Subject: [PATCH 44/98] [Stack Monitoring] Migrate Index Views to React (#113660) * index views * fix type Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../monitoring/public/application/index.tsx | 17 +++ .../elasticsearch/index_advanced_page.tsx | 77 +++++++++++++ .../pages/elasticsearch/index_page.tsx | 106 ++++++++++++++++++ .../pages/elasticsearch/item_template.tsx | 36 ++++++ .../pages/elasticsearch/node_page.tsx | 56 +++++---- .../elasticsearch/index/index_react.js | 70 ++++++++++++ .../components/cluster_view_react.js | 5 +- 7 files changed, 335 insertions(+), 32 deletions(-) create mode 100644 x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_advanced_page.tsx create mode 100644 x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_page.tsx create mode 100644 x-pack/plugins/monitoring/public/application/pages/elasticsearch/item_template.tsx create mode 100644 x-pack/plugins/monitoring/public/components/elasticsearch/index/index_react.js diff --git a/x-pack/plugins/monitoring/public/application/index.tsx b/x-pack/plugins/monitoring/public/application/index.tsx index acdf3b0986a64..a958e6061215d 100644 --- a/x-pack/plugins/monitoring/public/application/index.tsx +++ b/x-pack/plugins/monitoring/public/application/index.tsx @@ -27,6 +27,8 @@ import { KibanaOverviewPage } from './pages/kibana/overview'; import { CODE_PATH_ELASTICSEARCH, CODE_PATH_BEATS, CODE_PATH_KIBANA } from '../../common/constants'; import { ElasticsearchNodesPage } from './pages/elasticsearch/nodes_page'; import { ElasticsearchIndicesPage } from './pages/elasticsearch/indices_page'; +import { ElasticsearchIndexPage } from './pages/elasticsearch/index_page'; +import { ElasticsearchIndexAdvancedPage } from './pages/elasticsearch/index_advanced_page'; import { ElasticsearchNodePage } from './pages/elasticsearch/node_page'; import { MonitoringTimeContainer } from './hooks/use_monitoring_time'; import { BreadcrumbContainer } from './hooks/use_breadcrumbs'; @@ -84,6 +86,21 @@ const MonitoringApp: React.FC<{ /> {/* ElasticSearch Views */} + + + + + = ({ clusters }) => { + const globalState = useContext(GlobalStateContext); + const { services } = useKibana<{ data: any }>(); + const { index }: { index: string } = useParams(); + const { zoomInfo, onBrush } = useCharts(); + const clusterUuid = globalState.cluster_uuid; + const [data, setData] = useState({} as any); + + const title = i18n.translate('xpack.monitoring.elasticsearch.index.advanced.title', { + defaultMessage: 'Elasticsearch - Indices - {indexName} - Advanced', + values: { + indexName: index, + }, + }); + + const getPageData = useCallback(async () => { + const bounds = services.data?.query.timefilter.timefilter.getBounds(); + const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/indices/${index}`; + const response = await services.http?.fetch(url, { + method: 'POST', + body: JSON.stringify({ + timeRange: { + min: bounds.min.toISOString(), + max: bounds.max.toISOString(), + }, + is_advanced: true, + }), + }); + setData(response); + }, [clusterUuid, services.data?.query.timefilter.timefilter, services.http, index]); + + return ( + + ( + + {flyoutComponent} + + {bottomBarComponent} + + )} + /> + + ); +}; diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_page.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_page.tsx new file mode 100644 index 0000000000000..b23f9c71a98bf --- /dev/null +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_page.tsx @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useContext, useState, useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; +import { useParams } from 'react-router-dom'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { GlobalStateContext } from '../../global_state_context'; +// @ts-ignore +import { IndexReact } from '../../../components/elasticsearch/index/index_react'; +import { ComponentProps } from '../../route_init'; +import { SetupModeRenderer } from '../../setup_mode/setup_mode_renderer'; +import { SetupModeContext } from '../../../components/setup_mode/setup_mode_context'; +import { useCharts } from '../../hooks/use_charts'; +import { ItemTemplate } from './item_template'; +// @ts-ignore +import { indicesByNodes } from '../../../components/elasticsearch/shard_allocation/transformers/indices_by_nodes'; +// @ts-ignore +import { labels } from '../../../components/elasticsearch/shard_allocation/lib/labels'; + +interface SetupModeProps { + setupMode: any; + flyoutComponent: any; + bottomBarComponent: any; +} + +export const ElasticsearchIndexPage: React.FC = ({ clusters }) => { + const globalState = useContext(GlobalStateContext); + const { services } = useKibana<{ data: any }>(); + const { index }: { index: string } = useParams(); + const { zoomInfo, onBrush } = useCharts(); + const clusterUuid = globalState.cluster_uuid; + const [data, setData] = useState({} as any); + const [indexLabel, setIndexLabel] = useState(labels.index as any); + const [nodesByIndicesData, setNodesByIndicesData] = useState([]); + + const title = i18n.translate('xpack.monitoring.elasticsearch.index.overview.title', { + defaultMessage: 'Elasticsearch - Indices - {indexName} - Overview', + values: { + indexName: index, + }, + }); + + const pageTitle = i18n.translate('xpack.monitoring.elasticsearch.index.overview.pageTitle', { + defaultMessage: 'Index: {indexName}', + values: { + indexName: index, + }, + }); + + const getPageData = useCallback(async () => { + const bounds = services.data?.query.timefilter.timefilter.getBounds(); + const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/indices/${index}`; + const response = await services.http?.fetch(url, { + method: 'POST', + body: JSON.stringify({ + timeRange: { + min: bounds.min.toISOString(), + max: bounds.max.toISOString(), + }, + is_advanced: false, + }), + }); + setData(response); + const transformer = indicesByNodes(); + setNodesByIndicesData(transformer(response.shards, response.nodes)); + + const shards = response.shards; + if (shards.some((shard: any) => shard.state === 'UNASSIGNED')) { + setIndexLabel(labels.indexWithUnassigned); + } + }, [clusterUuid, services.data?.query.timefilter.timefilter, services.http, index]); + + return ( + + ( + + {flyoutComponent} + + {bottomBarComponent} + + )} + /> + + ); +}; diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/item_template.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/item_template.tsx new file mode 100644 index 0000000000000..1f06ba18bf102 --- /dev/null +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/item_template.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { PageTemplate } from '../page_template'; +import { TabMenuItem, PageTemplateProps } from '../page_template'; + +interface ItemTemplateProps extends PageTemplateProps { + id: string; + pageType: string; +} +export const ItemTemplate: React.FC = (props) => { + const { pageType, id, ...rest } = props; + const tabs: TabMenuItem[] = [ + { + id: 'overview', + label: i18n.translate('xpack.monitoring.esItemNavigation.overviewLinkText', { + defaultMessage: 'Overview', + }), + route: `/elasticsearch/${pageType}/${id}`, + }, + { + id: 'advanced', + label: i18n.translate('xpack.monitoring.esItemNavigation.advancedLinkText', { + defaultMessage: 'Advanced', + }), + route: `/elasticsearch/${pageType}/${id}/advanced`, + }, + ]; + + return ; +}; diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx index ffbde2efcac6b..9b3a67f612e5c 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx @@ -7,8 +7,7 @@ import React, { useContext, useState, useCallback } from 'react'; import { useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; -import { find } from 'lodash'; -import { ElasticsearchTemplate } from './elasticsearch_template'; +import { ItemTemplate } from './item_template'; import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import { GlobalStateContext } from '../../global_state_context'; import { NodeReact } from '../../../components/elasticsearch'; @@ -18,6 +17,8 @@ import { SetupModeContext } from '../../../components/setup_mode/setup_mode_cont import { useLocalStorage } from '../../hooks/use_local_storage'; import { useCharts } from '../../hooks/use_charts'; import { nodesByIndices } from '../../../components/elasticsearch/shard_allocation/transformers/nodes_by_indices'; +// @ts-ignore +import { labels } from '../../../components/elasticsearch/shard_allocation/lib/labels'; interface SetupModeProps { setupMode: any; @@ -38,9 +39,6 @@ export const ElasticsearchNodePage: React.FC = ({ clusters }) => const clusterUuid = globalState.cluster_uuid; const ccs = globalState.ccs; - const cluster = find(clusters, { - cluster_uuid: clusterUuid, - }); const [data, setData] = useState({} as any); const [nodesByIndicesData, setNodesByIndicesData] = useState([]); @@ -92,33 +90,33 @@ export const ElasticsearchNodePage: React.FC = ({ clusters }) => }, [showSystemIndices, setShowSystemIndices]); return ( - -
    - ( - - {flyoutComponent} - - {bottomBarComponent} - - )} - /> -
    -
    + ( + + {flyoutComponent} + + {bottomBarComponent} + + )} + /> + ); }; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/index/index_react.js b/x-pack/plugins/monitoring/public/components/elasticsearch/index/index_react.js new file mode 100644 index 0000000000000..70bac52a0926c --- /dev/null +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/index/index_react.js @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { + EuiPage, + EuiPageContent, + EuiPageBody, + EuiPanel, + EuiSpacer, + EuiFlexGrid, + EuiFlexItem, +} from '@elastic/eui'; +import { IndexDetailStatus } from '../index_detail_status'; +import { MonitoringTimeseriesContainer } from '../../chart'; +import { ShardAllocationReact } from '../shard_allocation/shard_allocation_react'; +import { Logs } from '../../logs'; +import { AlertsCallout } from '../../../alerts/callout'; + +export const IndexReact = ({ + indexSummary, + metrics, + clusterUuid, + indexUuid, + logs, + alerts, + ...props +}) => { + const metricsToShow = [ + metrics.index_mem, + metrics.index_size, + metrics.index_search_request_rate, + metrics.index_request_rate, + metrics.index_segment_count, + metrics.index_document_count, + ]; + + return ( + + + + + + + + + + + {metricsToShow.map((metric, index) => ( + + + + + ))} + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/cluster_view_react.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/cluster_view_react.js index 987ca467931f4..2d0c4b59df4b8 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/cluster_view_react.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/cluster_view_react.js @@ -8,13 +8,12 @@ import React from 'react'; import { TableHeadReact } from './table_head_react'; import { TableBody } from './table_body'; -import { labels } from '../lib/labels'; export const ClusterViewReact = (props) => { return ( @@ -22,7 +21,7 @@ export const ClusterViewReact = (props) => { filter={props.filter} totalCount={props.totalCount} rows={props.nodesByIndices} - cols={labels.node.length} + cols={props.labels.length} shardStats={props.shardStats} />
    From 59b15df115f5f0ed8f6d6a54c862594534dcd13a Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Mon, 4 Oct 2021 17:49:14 +0200 Subject: [PATCH 45/98] fix priority reset bug (#113626) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../jira/jira_params.test.tsx | 18 ++++++++++++++++++ .../builtin_action_types/jira/jira_params.tsx | 4 ++-- .../jira/use_get_fields_by_issue_type.tsx | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.test.tsx index a05db00f141ab..812c234e80d9e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.test.tsx @@ -95,6 +95,10 @@ describe('JiraParamsFields renders', () => { description: { allowedValues: [], defaultValue: {} }, }, }; + const useGetFieldsByIssueTypeResponseLoading = { + isLoading: true, + fields: {}, + }; beforeEach(() => { jest.clearAllMocks(); @@ -421,5 +425,19 @@ describe('JiraParamsFields renders', () => { expect(editAction.mock.calls[0][1].incident.priority).toEqual('Medium'); expect(editAction.mock.calls[1][1].incident.priority).toEqual(null); }); + + test('Preserve priority when the issue type fields are loading and hasPriority becomes stale', () => { + useGetFieldsByIssueTypeMock + .mockReturnValueOnce(useGetFieldsByIssueTypeResponseLoading) + .mockReturnValue(useGetFieldsByIssueTypeResponse); + const wrapper = mount(); + + expect(editAction).not.toBeCalled(); + + wrapper.setProps({ ...defaultProps }); // just to force component call useGetFieldsByIssueType again + + expect(editAction).toBeCalledTimes(1); + expect(editAction.mock.calls[0][1].incident.priority).toEqual('Medium'); + }); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.tsx index 834892f2bf374..32390c163cf2a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.tsx @@ -147,11 +147,11 @@ const JiraParamsFields: React.FunctionComponent { - if (!hasPriority && incident.priority != null) { + if (!isLoadingFields && !hasPriority && incident.priority != null) { editSubActionProperty('priority', null); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [hasPriority]); + }, [hasPriority, isLoadingFields]); const labelOptions = useMemo( () => (incident.labels ? incident.labels.map((label: string) => ({ label })) : []), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/use_get_fields_by_issue_type.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/use_get_fields_by_issue_type.tsx index 38be618119c4a..61db73c129db6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/use_get_fields_by_issue_type.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/use_get_fields_by_issue_type.tsx @@ -62,8 +62,8 @@ export const useGetFieldsByIssueType = ({ }); if (!didCancel) { - setIsLoading(false); setFields(res.data ?? {}); + setIsLoading(false); if (res.status && res.status === 'error') { toastNotifications.addDanger({ title: i18n.FIELDS_API_ERROR, From a9c100768e7c5407739da69d64e5b8250fe52f87 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 4 Oct 2021 11:56:00 -0400 Subject: [PATCH 46/98] Increase timeout for long-running unit test assertions. (#113122) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../uptime/public/hooks/use_composite_image.test.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/uptime/public/hooks/use_composite_image.test.tsx b/x-pack/plugins/uptime/public/hooks/use_composite_image.test.tsx index 79e0cde1eaab8..9e2cb1e498b73 100644 --- a/x-pack/plugins/uptime/public/hooks/use_composite_image.test.tsx +++ b/x-pack/plugins/uptime/public/hooks/use_composite_image.test.tsx @@ -191,10 +191,13 @@ describe('use composite image', () => { expect(composeSpy.mock.calls[0][1]).toBe(canvasMock); expect(composeSpy.mock.calls[0][2]).toBe(blocks); - await waitFor(() => { - expect(onComposeImageSuccess).toHaveBeenCalledTimes(1); - expect(onComposeImageSuccess).toHaveBeenCalledWith('compose success'); - }); + await waitFor( + () => { + expect(onComposeImageSuccess).toHaveBeenCalledTimes(1); + expect(onComposeImageSuccess).toHaveBeenCalledWith('compose success'); + }, + { timeout: 10000 } + ); }); }); }); From 9df505181739b27265d6e44de0c404449a187cc1 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 4 Oct 2021 15:52:42 +0000 Subject: [PATCH 47/98] Revert "Revert "chore: add modifications to staging automatically after eslint fix (#113443)"" This reverts commit cc73577f84fc3d1c93d30832423f5cfd8b410609. --- src/dev/run_precommit_hook.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/dev/run_precommit_hook.js b/src/dev/run_precommit_hook.js index e1eafaf28d95d..0a594a232cc22 100644 --- a/src/dev/run_precommit_hook.js +++ b/src/dev/run_precommit_hook.js @@ -6,6 +6,9 @@ * Side Public License, v 1. */ +import SimpleGit from 'simple-git/promise'; + +import { REPO_ROOT } from '@kbn/utils'; import { run, combineErrors, createFlagError, createFailError } from '@kbn/dev-utils'; import * as Eslint from './eslint'; import * as Stylelint from './stylelint'; @@ -48,6 +51,11 @@ run( await Linter.lintFiles(log, filesToLint, { fix: flags.fix, }); + + if (flags.fix) { + const simpleGit = new SimpleGit(REPO_ROOT); + await simpleGit.add(filesToLint); + } } catch (error) { errors.push(error); } From 2b401d06df0e523804a1bafa33a5acfdc41043ec Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 4 Oct 2021 15:59:25 +0000 Subject: [PATCH 48/98] Revert "Lint git index content on commit (#113300)" This reverts commit 92fe7f8ab36be27a42bb96073996e6101331ae58. --- src/dev/eslint/lint_files.ts | 42 +--------- src/dev/file.ts | 18 ----- .../precommit_hook/get_files_for_commit.js | 81 ++++--------------- src/dev/run_precommit_hook.js | 14 +--- src/dev/stylelint/lint_files.js | 56 +++---------- 5 files changed, 31 insertions(+), 180 deletions(-) diff --git a/src/dev/eslint/lint_files.ts b/src/dev/eslint/lint_files.ts index 77fe941fb7aeb..5c6118edeb2ec 100644 --- a/src/dev/eslint/lint_files.ts +++ b/src/dev/eslint/lint_files.ts @@ -12,41 +12,6 @@ import { REPO_ROOT } from '@kbn/utils'; import { createFailError, ToolingLog } from '@kbn/dev-utils'; import { File } from '../file'; -// For files living on the filesystem -function lintFilesOnFS(cli: CLIEngine, files: File[]) { - const paths = files.map((file) => file.getRelativePath()); - return cli.executeOnFiles(paths); -} - -// For files living somewhere else (ie. git object) -async function lintFilesOnContent(cli: CLIEngine, files: File[]) { - const report: CLIEngine.LintReport = { - results: [], - errorCount: 0, - warningCount: 0, - fixableErrorCount: 0, - fixableWarningCount: 0, - usedDeprecatedRules: [], - }; - - for (let i = 0; i < files.length; i++) { - const r = cli.executeOnText(await files[i].getContent(), files[i].getRelativePath()); - // Despite a relative path was given, the result would contain an absolute one. Work around it. - r.results[0].filePath = r.results[0].filePath.replace( - files[i].getAbsolutePath(), - files[i].getRelativePath() - ); - report.results.push(...r.results); - report.errorCount += r.errorCount; - report.warningCount += r.warningCount; - report.fixableErrorCount += r.fixableErrorCount; - report.fixableWarningCount += r.fixableWarningCount; - report.usedDeprecatedRules.push(...r.usedDeprecatedRules); - } - - return report; -} - /** * Lints a list of files with eslint. eslint reports are written to the log * and a FailError is thrown when linting errors occur. @@ -55,16 +20,15 @@ async function lintFilesOnContent(cli: CLIEngine, files: File[]) { * @param {Array} files * @return {undefined} */ -export async function lintFiles(log: ToolingLog, files: File[], { fix }: { fix?: boolean } = {}) { +export function lintFiles(log: ToolingLog, files: File[], { fix }: { fix?: boolean } = {}) { const cli = new CLIEngine({ cache: true, cwd: REPO_ROOT, fix, }); - const virtualFilesCount = files.filter((file) => file.isVirtual()).length; - const report = - virtualFilesCount && !fix ? await lintFilesOnContent(cli, files) : lintFilesOnFS(cli, files); + const paths = files.map((file) => file.getRelativePath()); + const report = cli.executeOnFiles(paths); if (fix) { CLIEngine.outputFixes(report); diff --git a/src/dev/file.ts b/src/dev/file.ts index 01005b257a403..b532a7bb70602 100644 --- a/src/dev/file.ts +++ b/src/dev/file.ts @@ -7,13 +7,11 @@ */ import { dirname, extname, join, relative, resolve, sep, basename } from 'path'; -import { createFailError } from '@kbn/dev-utils'; export class File { private path: string; private relativePath: string; private ext: string; - private fileReader: undefined | (() => Promise); constructor(path: string) { this.path = resolve(path); @@ -57,11 +55,6 @@ export class File { ); } - // Virtual files cannot be read as usual, an helper is needed - public isVirtual() { - return this.fileReader !== undefined; - } - public getRelativeParentDirs() { const parents: string[] = []; @@ -88,15 +81,4 @@ export class File { public toJSON() { return this.relativePath; } - - public setFileReader(fileReader: () => Promise) { - this.fileReader = fileReader; - } - - public getContent() { - if (this.fileReader) { - return this.fileReader(); - } - throw createFailError('getContent() was invoked on a non-virtual File'); - } } diff --git a/src/dev/precommit_hook/get_files_for_commit.js b/src/dev/precommit_hook/get_files_for_commit.js index 52dfab49c5c64..44c8c9d5e6bc0 100644 --- a/src/dev/precommit_hook/get_files_for_commit.js +++ b/src/dev/precommit_hook/get_files_for_commit.js @@ -6,65 +6,12 @@ * Side Public License, v 1. */ -import { format } from 'util'; import SimpleGit from 'simple-git'; import { fromNode as fcb } from 'bluebird'; import { REPO_ROOT } from '@kbn/utils'; import { File } from '../file'; -/** - * Return the `git diff` argument used for building the list of files - * - * @param {String} gitRef - * @return {String} - * - * gitRef return - * '' '--cached' - * '' '~1..' - * '..' '..' - * '...' '...' - * '..' '..' - * '...' '...' - * '..' '..' - * '...' '...' - */ -function getRefForDiff(gitRef) { - if (!gitRef) { - return '--cached'; - } else if (gitRef.includes('..')) { - return gitRef; - } else { - return format('%s~1..%s', gitRef, gitRef); - } -} - -/** - * Return the used for reading files content - * - * @param {String} gitRef - * @return {String} - * - * gitRef return - * '' '' - * '' '' - * '..' 'HEAD' - * '...' 'HEAD' - * '..' '' - * '...' '' - * '..' '' - * '...' '' - */ -function getRefForCat(gitRef) { - if (!gitRef) { - return ''; - } else if (gitRef.includes('..')) { - return gitRef.endsWith('..') ? 'HEAD' : gitRef.slice(gitRef.lastIndexOf('..') + 2); - } else { - return gitRef; - } -} - /** * Get the files that are staged for commit (excluding deleted files) * as `File` objects that are aware of their commit status. @@ -74,23 +21,29 @@ function getRefForCat(gitRef) { */ export async function getFilesForCommit(gitRef) { const simpleGit = new SimpleGit(REPO_ROOT); - const gitRefForDiff = getRefForDiff(gitRef); - const gitRefForCat = getRefForCat(gitRef); - - const output = await fcb((cb) => { - simpleGit.diff(['--diff-filter=d', '--name-only', gitRefForDiff], cb); - }); + const gitRefForDiff = gitRef ? gitRef : '--cached'; + const output = await fcb((cb) => simpleGit.diff(['--name-status', gitRefForDiff], cb)); return ( output .split('\n') // Ignore blank lines .filter((line) => line.trim().length > 0) - .map((path) => { - const file = new File(path); - const object = format('%s:%s', gitRefForCat, path); - file.setFileReader(() => fcb((cb) => simpleGit.catFile(['-p', object], cb))); - return file; + // git diff --name-status outputs lines with two OR three parts + // separated by a tab character + .map((line) => line.trim().split('\t')) + .map(([status, ...paths]) => { + // ignore deleted files + if (status === 'D') { + return undefined; + } + + // the status is always in the first column + // .. If the file is edited the line will only have two columns + // .. If the file is renamed it will have three columns + // .. In any case, the last column is the CURRENT path to the file + return new File(paths[paths.length - 1]); }) + .filter(Boolean) ); } diff --git a/src/dev/run_precommit_hook.js b/src/dev/run_precommit_hook.js index 0a594a232cc22..a7bd0a9f57f6e 100644 --- a/src/dev/run_precommit_hook.js +++ b/src/dev/run_precommit_hook.js @@ -8,8 +8,7 @@ import SimpleGit from 'simple-git/promise'; -import { REPO_ROOT } from '@kbn/utils'; -import { run, combineErrors, createFlagError, createFailError } from '@kbn/dev-utils'; +import { run, combineErrors, createFlagError, REPO_ROOT } from '@kbn/dev-utils'; import * as Eslint from './eslint'; import * as Stylelint from './stylelint'; import { getFilesForCommit, checkFileCasing } from './precommit_hook'; @@ -26,11 +25,6 @@ run( throw createFlagError('expected --max-files to be a number greater than 0'); } - const virtualFilesCount = files.filter((file) => file.isVirtual()).length; - if (virtualFilesCount > 0 && virtualFilesCount < files.length) { - throw createFailError('Mixing of virtual and on-filesystem files is unsupported'); - } - if (maxFilesCount && files.length > maxFilesCount) { log.warning( `--max-files is set to ${maxFilesCount} and ${files.length} were discovered. The current script execution will be skipped.` @@ -79,11 +73,7 @@ run( help: ` --fix Execute eslint in --fix mode --max-files Max files number to check against. If exceeded the script will skip the execution - --ref Run checks against git ref files instead of running against staged ones - Examples: - HEAD~1..HEAD files changed in the commit at HEAD - HEAD equivalent to HEAD~1..HEAD - main... files changed in current branch since the common ancestor with main + --ref Run checks against any git ref files (example HEAD or ) instead of running against staged ones `, }, } diff --git a/src/dev/stylelint/lint_files.js b/src/dev/stylelint/lint_files.js index 1ebc981728814..6e62c85d44ae8 100644 --- a/src/dev/stylelint/lint_files.js +++ b/src/dev/stylelint/lint_files.js @@ -16,51 +16,6 @@ import { createFailError } from '@kbn/dev-utils'; const stylelintPath = path.resolve(__dirname, '..', '..', '..', '.stylelintrc'); const styleLintConfig = safeLoad(fs.readFileSync(stylelintPath)); -// For files living on the filesystem -function lintFilesOnFS(files) { - const paths = files.map((file) => file.getRelativePath()); - - const options = { - files: paths, - config: styleLintConfig, - formatter: 'string', - ignorePath: path.resolve(__dirname, '..', '..', '..', '.stylelintignore'), - }; - - return stylelint.lint(options); -} - -// For files living somewhere else (ie. git object) -async function lintFilesOnContent(files) { - const report = { - errored: false, - output: '', - postcssResults: [], - results: [], - maxWarningsExceeded: { - maxWarnings: 0, - foundWarnings: 0, - }, - }; - - for (let i = 0; i < files.length; i++) { - const options = { - code: await files[i].getContent(), - config: styleLintConfig, - formatter: 'string', - ignorePath: path.resolve(__dirname, '..', '..', '..', '.stylelintignore'), - }; - const r = await stylelint.lint(options); - report.errored = report.errored || r.errored; - report.output += r.output.replace(//, files[i].getRelativePath()).slice(0, -1); - report.postcssResults.push(...(r.postcssResults || [])); - report.maxWarnings = r.maxWarnings; - report.foundWarnings += r.foundWarnings; - } - - return report; -} - /** * Lints a list of files with eslint. eslint reports are written to the log * and a FailError is thrown when linting errors occur. @@ -70,9 +25,16 @@ async function lintFilesOnContent(files) { * @return {undefined} */ export async function lintFiles(log, files) { - const virtualFilesCount = files.filter((file) => file.isVirtual()).length; - const report = virtualFilesCount ? await lintFilesOnContent(files) : await lintFilesOnFS(files); + const paths = files.map((file) => file.getRelativePath()); + + const options = { + files: paths, + config: styleLintConfig, + formatter: 'string', + ignorePath: path.resolve(__dirname, '..', '..', '..', '.stylelintignore'), + }; + const report = await stylelint.lint(options); if (report.errored) { log.error(report.output); throw createFailError('[stylelint] errors'); From fed0dc6563979f3d18a04458723c9ec7d2704e82 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 4 Oct 2021 18:10:27 +0200 Subject: [PATCH 49/98] [Uptime] Supress fetch errors on no data screen (#113458) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../plugins/uptime/public/apps/uptime_page_template.tsx | 8 +++++--- .../components/overview/empty_state/use_has_data.tsx | 3 ++- .../public/contexts/uptime_index_pattern_context.tsx | 8 +++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/uptime/public/apps/uptime_page_template.tsx b/x-pack/plugins/uptime/public/apps/uptime_page_template.tsx index 829f587e248e7..033fdcb61b28b 100644 --- a/x-pack/plugins/uptime/public/apps/uptime_page_template.tsx +++ b/x-pack/plugins/uptime/public/apps/uptime_page_template.tsx @@ -38,12 +38,14 @@ export const UptimePageTemplateComponent: React.FC = ({ path, pageHeader, const noDataConfig = useNoDataConfig(); - const { loading, error } = useHasData(); + const { loading, error, data } = useHasData(); if (error) { return ; } + const showLoading = loading && path === OVERVIEW_ROUTE && !data; + return ( <>
    @@ -51,9 +53,9 @@ export const UptimePageTemplateComponent: React.FC = ({ path, pageHeader, pageHeader={pageHeader} noDataConfig={path === OVERVIEW_ROUTE && !loading ? noDataConfig : undefined} > - {loading && path === OVERVIEW_ROUTE && } + {showLoading && }
    {children} diff --git a/x-pack/plugins/uptime/public/components/overview/empty_state/use_has_data.tsx b/x-pack/plugins/uptime/public/components/overview/empty_state/use_has_data.tsx index 66c68834f285f..01ca9d9927e1b 100644 --- a/x-pack/plugins/uptime/public/components/overview/empty_state/use_has_data.tsx +++ b/x-pack/plugins/uptime/public/components/overview/empty_state/use_has_data.tsx @@ -13,7 +13,7 @@ import { UptimeRefreshContext } from '../../../contexts'; import { getDynamicSettings } from '../../../state/actions/dynamic_settings'; export const useHasData = () => { - const { loading, error } = useSelector(indexStatusSelector); + const { loading, error, data } = useSelector(indexStatusSelector); const { lastRefresh } = useContext(UptimeRefreshContext); const { settings } = useSelector(selectDynamicSettings); @@ -29,6 +29,7 @@ export const useHasData = () => { }, [dispatch]); return { + data, error, loading, settings, diff --git a/x-pack/plugins/uptime/public/contexts/uptime_index_pattern_context.tsx b/x-pack/plugins/uptime/public/contexts/uptime_index_pattern_context.tsx index 580160bac4012..8171f7e19865f 100644 --- a/x-pack/plugins/uptime/public/contexts/uptime_index_pattern_context.tsx +++ b/x-pack/plugins/uptime/public/contexts/uptime_index_pattern_context.tsx @@ -9,7 +9,7 @@ import React, { createContext, useContext, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useFetcher } from '../../../observability/public'; import { DataPublicPluginStart, IndexPattern } from '../../../../../src/plugins/data/public'; -import { selectDynamicSettings } from '../state/selectors'; +import { indexStatusSelector, selectDynamicSettings } from '../state/selectors'; import { getDynamicSettings } from '../state/actions/dynamic_settings'; export const UptimeIndexPatternContext = createContext({} as IndexPattern); @@ -19,6 +19,8 @@ export const UptimeIndexPatternContextProvider: React.FC<{ data: DataPublicPlugi data: { indexPatterns }, }) => { const { settings } = useSelector(selectDynamicSettings); + const { data: indexStatus } = useSelector(indexStatusSelector); + const dispatch = useDispatch(); useEffect(() => { @@ -30,11 +32,11 @@ export const UptimeIndexPatternContextProvider: React.FC<{ data: DataPublicPlugi const heartbeatIndices = settings?.heartbeatIndices || ''; const { data } = useFetcher>(async () => { - if (heartbeatIndices) { + if (heartbeatIndices && indexStatus?.indexExists) { // this only creates an index pattern in memory, not as saved object return indexPatterns.create({ title: heartbeatIndices }); } - }, [heartbeatIndices]); + }, [heartbeatIndices, indexStatus?.indexExists]); return ; }; From 0d9825d03c22785be491a89c450fb3dbc44f2c4a Mon Sep 17 00:00:00 2001 From: Michael Dokolin Date: Mon, 4 Oct 2021 18:30:10 +0200 Subject: [PATCH 50/98] [Expressions] Remove the `any` type usages (#113477) * Update ESLint config to disallow usage of the any type * Remove the any type usages from the expressions plugin * Update plugins using expressions according to the updated public API --- .../public/actions_and_expressions.tsx | 4 +- .../public/actions_and_expressions2.tsx | 2 +- .../public/renderers/button.tsx | 4 +- .../tagcloud_function.test.ts | 10 ++- src/plugins/expressions/.eslintrc.json | 3 +- .../common/ast/build_expression.ts | 8 +- src/plugins/expressions/common/ast/types.ts | 2 +- .../execution/execution.abortion.test.ts | 2 +- .../common/execution/execution.test.ts | 46 ++++++---- .../expressions/common/execution/execution.ts | 83 +++++++++++++------ .../expressions/common/execution/types.ts | 7 +- .../expressions/common/executor/container.ts | 4 +- .../executor/executor.execution.test.ts | 26 +++--- .../common/executor/executor.test.ts | 6 +- .../expressions/common/executor/executor.ts | 16 ++-- .../common/expression_functions/arguments.ts | 20 ++--- .../expression_function.ts | 15 ++-- .../expression_function_parameter.ts | 14 ++-- .../expression_function_parameters.test.ts | 2 +- .../specs/create_table.ts | 6 +- .../common/expression_functions/specs/font.ts | 9 +- .../expression_functions/specs/map_column.ts | 2 +- .../common/expression_functions/specs/math.ts | 13 ++- .../expression_functions/specs/math_column.ts | 2 +- .../specs/tests/font.test.ts | 29 +++---- .../specs/tests/math.test.ts | 20 ++--- .../specs/tests/theme.test.ts | 8 +- .../specs/tests/ui_setting.test.ts | 18 ++-- .../expression_functions/specs/tests/utils.ts | 10 ++- .../specs/tests/var.test.ts | 6 +- .../specs/tests/var_set.test.ts | 8 +- .../expression_functions/specs/theme.ts | 4 +- .../common/expression_functions/specs/var.ts | 3 +- .../expression_functions/specs/var_set.ts | 6 +- .../common/expression_functions/types.ts | 4 +- .../common/expression_renderers/types.ts | 31 +++++-- .../expression_types/expression_type.ts | 9 +- .../common/expression_types/get_type.ts | 22 +++-- .../expression_types/specs/datatable.ts | 7 +- .../common/expression_types/specs/error.ts | 2 +- .../expression_types/specs/pointseries.ts | 4 +- .../common/expression_types/specs/shape.ts | 2 +- .../common/expression_types/types.ts | 18 ++-- src/plugins/expressions/common/mocks.ts | 8 +- .../common/service/expressions_services.ts | 6 +- .../expression_functions/access.ts | 8 +- .../test_helpers/expression_functions/add.ts | 4 +- .../introspect_context.ts | 6 +- .../expression_functions/sleep.ts | 2 +- .../expressions/common/types/common.ts | 3 +- .../util/expressions_inspector_adapter.ts | 7 +- .../expressions/common/util/test_utils.ts | 4 +- src/plugins/expressions/public/loader.test.ts | 22 +++-- src/plugins/expressions/public/loader.ts | 8 +- .../public/react_expression_renderer.test.tsx | 3 +- src/plugins/expressions/public/render.test.ts | 23 ++--- src/plugins/expressions/public/render.ts | 48 +++++------ src/plugins/expressions/public/types/index.ts | 2 +- .../public/markdown_fn.test.ts | 3 +- .../metric/public/metric_vis_fn.test.ts | 6 +- .../vis_types/pie/public/pie_fn.test.ts | 5 +- .../table/public/table_vis_fn.test.ts | 5 +- .../vis_types/vislib/public/pie_fn.test.ts | 3 +- .../canvas_plugin_src/functions/common/as.ts | 11 ++- .../generate_function_reference.ts | 2 +- .../format_column/format_column.test.ts | 5 +- 66 files changed, 415 insertions(+), 296 deletions(-) diff --git a/examples/expressions_explorer/public/actions_and_expressions.tsx b/examples/expressions_explorer/public/actions_and_expressions.tsx index f802a78faf06e..6d0c8886a79f3 100644 --- a/examples/expressions_explorer/public/actions_and_expressions.tsx +++ b/examples/expressions_explorer/public/actions_and_expressions.tsx @@ -47,11 +47,11 @@ export function ActionsExpressionsExample({ expressions, actions }: Props) { }; const handleEvents = (event: any) => { - if (event.id !== 'NAVIGATE') return; + if (event.name !== 'NAVIGATE') return; // enrich event context with some extra data event.baseUrl = 'http://www.google.com'; - actions.executeTriggerActions(NAVIGATE_TRIGGER_ID, event.value); + actions.executeTriggerActions(NAVIGATE_TRIGGER_ID, event.data); }; return ( diff --git a/examples/expressions_explorer/public/actions_and_expressions2.tsx b/examples/expressions_explorer/public/actions_and_expressions2.tsx index 31ba903ad91ac..e7dc28b8b97cd 100644 --- a/examples/expressions_explorer/public/actions_and_expressions2.tsx +++ b/examples/expressions_explorer/public/actions_and_expressions2.tsx @@ -50,7 +50,7 @@ export function ActionsExpressionsExample2({ expressions, actions }: Props) { }; const handleEvents = (event: any) => { - updateVariables({ color: event.value.href === 'http://www.google.com' ? 'red' : 'blue' }); + updateVariables({ color: event.data.href === 'http://www.google.com' ? 'red' : 'blue' }); }; return ( diff --git a/examples/expressions_explorer/public/renderers/button.tsx b/examples/expressions_explorer/public/renderers/button.tsx index 68add91c3cbc9..557180ab73a35 100644 --- a/examples/expressions_explorer/public/renderers/button.tsx +++ b/examples/expressions_explorer/public/renderers/button.tsx @@ -18,8 +18,8 @@ export const buttonRenderer: ExpressionRenderDefinition = { render(domNode, config, handlers) { const buttonClick = () => { handlers.event({ - id: 'NAVIGATE', - value: { + name: 'NAVIGATE', + data: { href: config.href, }, }); diff --git a/src/plugins/chart_expressions/expression_tagcloud/common/expression_functions/tagcloud_function.test.ts b/src/plugins/chart_expressions/expression_tagcloud/common/expression_functions/tagcloud_function.test.ts index 8abdc36704b45..86a371afd6912 100644 --- a/src/plugins/chart_expressions/expression_tagcloud/common/expression_functions/tagcloud_function.test.ts +++ b/src/plugins/chart_expressions/expression_tagcloud/common/expression_functions/tagcloud_function.test.ts @@ -12,6 +12,8 @@ import { functionWrapper } from '../../../../expressions/common/expression_funct import { ExpressionValueVisDimension } from '../../../../visualizations/public'; import { Datatable } from '../../../../expressions/common/expression_types/specs'; +type Arguments = Parameters['fn']>[1]; + describe('interpreter/functions#tagcloud', () => { const fn = functionWrapper(tagcloudFunction()); const column1 = 'Count'; @@ -26,7 +28,7 @@ describe('interpreter/functions#tagcloud', () => { { [column1]: 0, [column2]: 'US' }, { [column1]: 10, [column2]: 'UK' }, ], - }; + } as unknown as Datatable; const visConfig = { scale: 'linear', orientation: 'single', @@ -73,12 +75,12 @@ describe('interpreter/functions#tagcloud', () => { }; it('returns an object with the correct structure for number accessors', () => { - const actual = fn(context, { ...visConfig, ...numberAccessors }, undefined); + const actual = fn(context, { ...visConfig, ...numberAccessors } as Arguments, undefined); expect(actual).toMatchSnapshot(); }); it('returns an object with the correct structure for string accessors', () => { - const actual = fn(context, { ...visConfig, ...stringAccessors }, undefined); + const actual = fn(context, { ...visConfig, ...stringAccessors } as Arguments, undefined); expect(actual).toMatchSnapshot(); }); @@ -93,7 +95,7 @@ describe('interpreter/functions#tagcloud', () => { }, }, }; - await fn(context, { ...visConfig, ...numberAccessors }, handlers as any); + await fn(context, { ...visConfig, ...numberAccessors } as Arguments, handlers as any); expect(loggedTable!).toMatchSnapshot(); }); diff --git a/src/plugins/expressions/.eslintrc.json b/src/plugins/expressions/.eslintrc.json index 2aab6c2d9093b..d1dbca41acc81 100644 --- a/src/plugins/expressions/.eslintrc.json +++ b/src/plugins/expressions/.eslintrc.json @@ -1,5 +1,6 @@ { "rules": { - "@typescript-eslint/consistent-type-definitions": 0 + "@typescript-eslint/consistent-type-definitions": 0, + "@typescript-eslint/no-explicit-any": ["error", { "ignoreRestArgs": true }] } } diff --git a/src/plugins/expressions/common/ast/build_expression.ts b/src/plugins/expressions/common/ast/build_expression.ts index 0f4618b3e699c..6e84594022fdf 100644 --- a/src/plugins/expressions/common/ast/build_expression.ts +++ b/src/plugins/expressions/common/ast/build_expression.ts @@ -32,13 +32,13 @@ import { parse } from './parse'; * @param val Value you want to check. * @return boolean */ -export function isExpressionAstBuilder(val: any): val is ExpressionAstExpressionBuilder { - return val?.type === 'expression_builder'; +export function isExpressionAstBuilder(val: unknown): val is ExpressionAstExpressionBuilder { + return (val as Record | undefined)?.type === 'expression_builder'; } /** @internal */ -export function isExpressionAst(val: any): val is ExpressionAstExpression { - return val?.type === 'expression'; +export function isExpressionAst(val: unknown): val is ExpressionAstExpression { + return (val as Record | undefined)?.type === 'expression'; } export interface ExpressionAstExpressionBuilder { diff --git a/src/plugins/expressions/common/ast/types.ts b/src/plugins/expressions/common/ast/types.ts index e5a79a0a5ddaf..8f376ac547d26 100644 --- a/src/plugins/expressions/common/ast/types.ts +++ b/src/plugins/expressions/common/ast/types.ts @@ -64,7 +64,7 @@ export type ExpressionAstFunctionDebug = { /** * Raw error that was thrown by the function, if any. */ - rawError?: any | Error; + rawError?: any | Error; // eslint-disable-line @typescript-eslint/no-explicit-any /** * Time in milliseconds it took to execute the function. Duration can be diff --git a/src/plugins/expressions/common/execution/execution.abortion.test.ts b/src/plugins/expressions/common/execution/execution.abortion.test.ts index 798558ba7ffb6..fca030fb9a080 100644 --- a/src/plugins/expressions/common/execution/execution.abortion.test.ts +++ b/src/plugins/expressions/common/execution/execution.abortion.test.ts @@ -90,7 +90,7 @@ describe('Execution abortion tests', () => { const completed = jest.fn(); const aborted = jest.fn(); - const defer: ExpressionFunctionDefinition<'defer', any, { time: number }, any> = { + const defer: ExpressionFunctionDefinition<'defer', unknown, { time: number }, unknown> = { name: 'defer', args: { time: { diff --git a/src/plugins/expressions/common/execution/execution.test.ts b/src/plugins/expressions/common/execution/execution.test.ts index c478977f60764..9b889c62e9ff5 100644 --- a/src/plugins/expressions/common/execution/execution.test.ts +++ b/src/plugins/expressions/common/execution/execution.test.ts @@ -17,7 +17,7 @@ import { ExecutionContract } from './execution_contract'; beforeAll(() => { if (typeof performance === 'undefined') { - (global as any).performance = { now: Date.now }; + global.performance = { now: Date.now } as typeof performance; } }); @@ -41,7 +41,7 @@ const createExecution = ( const run = async ( expression: string = 'foo bar=123', context?: Record, - input: any = null + input: unknown = null ) => { const execution = createExecution(expression, context); execution.start(input); @@ -262,45 +262,45 @@ describe('Execution', () => { describe('execution context', () => { test('context.variables is an object', async () => { - const { result } = (await run('introspectContext key="variables"')) as any; + const { result } = await run('introspectContext key="variables"'); expect(result).toHaveProperty('result', expect.any(Object)); }); test('context.types is an object', async () => { - const { result } = (await run('introspectContext key="types"')) as any; + const { result } = await run('introspectContext key="types"'); expect(result).toHaveProperty('result', expect.any(Object)); }); test('context.abortSignal is an object', async () => { - const { result } = (await run('introspectContext key="abortSignal"')) as any; + const { result } = await run('introspectContext key="abortSignal"'); expect(result).toHaveProperty('result', expect.any(Object)); }); test('context.inspectorAdapters is an object', async () => { - const { result } = (await run('introspectContext key="inspectorAdapters"')) as any; + const { result } = await run('introspectContext key="inspectorAdapters"'); expect(result).toHaveProperty('result', expect.any(Object)); }); test('context.getKibanaRequest is a function if provided', async () => { - const { result } = (await run('introspectContext key="getKibanaRequest"', { + const { result } = await run('introspectContext key="getKibanaRequest"', { kibanaRequest: {}, - })) as any; + }); expect(result).toHaveProperty('result', expect.any(Function)); }); test('context.getKibanaRequest is undefined if not provided', async () => { - const { result } = (await run('introspectContext key="getKibanaRequest"')) as any; + const { result } = await run('introspectContext key="getKibanaRequest"'); expect(result).toHaveProperty('result', undefined); }); test('unknown context key is undefined', async () => { - const { result } = (await run('introspectContext key="foo"')) as any; + const { result } = await run('introspectContext key="foo"'); expect(result).toHaveProperty('result', undefined); }); @@ -314,7 +314,7 @@ describe('Execution', () => { describe('inspector adapters', () => { test('by default, "tables" and "requests" inspector adapters are available', async () => { - const { result } = (await run('introspectContext key="inspectorAdapters"')) as any; + const { result } = await run('introspectContext key="inspectorAdapters"'); expect(result).toHaveProperty( 'result', expect.objectContaining({ @@ -326,9 +326,9 @@ describe('Execution', () => { test('can set custom inspector adapters', async () => { const inspectorAdapters = {}; - const { result } = (await run('introspectContext key="inspectorAdapters"', { + const { result } = await run('introspectContext key="inspectorAdapters"', { inspectorAdapters, - })) as any; + }); expect(result).toHaveProperty('result', inspectorAdapters); }); @@ -351,7 +351,7 @@ describe('Execution', () => { describe('expression abortion', () => { test('context has abortSignal object', async () => { - const { result } = (await run('introspectContext key="abortSignal"')) as any; + const { result } = await run('introspectContext key="abortSignal"'); expect(result).toHaveProperty('result.aborted', false); }); @@ -400,7 +400,7 @@ describe('Execution', () => { testScheduler.run(({ cold, expectObservable }) => { const arg = cold(' -a-b-c|', { a: 1, b: 2, c: 3 }); const expected = ' -a-b-c|'; - const observable: ExpressionFunctionDefinition<'observable', any, {}, any> = { + const observable: ExpressionFunctionDefinition<'observable', unknown, {}, unknown> = { name: 'observable', args: {}, help: '', @@ -468,7 +468,7 @@ describe('Execution', () => { }); test('does not execute remaining functions in pipeline', async () => { - const spy: ExpressionFunctionDefinition<'spy', any, {}, any> = { + const spy: ExpressionFunctionDefinition<'spy', unknown, {}, unknown> = { name: 'spy', args: {}, help: '', @@ -621,7 +621,12 @@ describe('Execution', () => { help: '', fn: () => arg2, }; - const max: ExpressionFunctionDefinition<'max', any, { val1: number; val2: number }, any> = { + const max: ExpressionFunctionDefinition< + 'max', + unknown, + { val1: number; val2: number }, + unknown + > = { name: 'max', args: { val1: { help: '', types: ['number'] }, @@ -679,7 +684,12 @@ describe('Execution', () => { describe('when arguments are missing', () => { it('when required argument is missing and has not alias, returns error', async () => { - const requiredArg: ExpressionFunctionDefinition<'requiredArg', any, { arg: any }, any> = { + const requiredArg: ExpressionFunctionDefinition< + 'requiredArg', + unknown, + { arg: unknown }, + unknown + > = { name: 'requiredArg', args: { arg: { diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index 0bb12951202a5..54a4800ec7c34 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -8,6 +8,7 @@ import { i18n } from '@kbn/i18n'; import { isPromise } from '@kbn/std'; +import { ObservableLike, UnwrapObservable, UnwrapPromiseOrReturn } from '@kbn/utility-types'; import { keys, last, mapValues, reduce, zipObject } from 'lodash'; import { combineLatest, @@ -44,6 +45,18 @@ import { ExecutionContract } from './execution_contract'; import { ExpressionExecutionParams } from '../service'; import { createDefaultInspectorAdapters } from '../util/create_default_inspector_adapters'; +type UnwrapReturnType unknown> = + ReturnType extends ObservableLike + ? UnwrapObservable> + : UnwrapPromiseOrReturn>; + +// type ArgumentsOf = Function extends ExpressionFunction< +// unknown, +// infer Arguments +// > +// ? Arguments +// : never; + /** * The result returned after an expression function execution. */ @@ -83,7 +96,7 @@ const createAbortErrorValue = () => }); export interface ExecutionParams { - executor: Executor; + executor: Executor; ast?: ExpressionAstExpression; expression?: string; params: ExpressionExecutionParams; @@ -107,7 +120,7 @@ export class Execution< * N.B. It is initialized to `null` rather than `undefined` for legacy reasons, * because in legacy interpreter it was set to `null` by default. */ - public input: Input = null as any; + public input = null as unknown as Input; /** * Input of the started execution. @@ -186,13 +199,13 @@ export class Execution< }); const inspectorAdapters = - execution.params.inspectorAdapters || createDefaultInspectorAdapters(); + (execution.params.inspectorAdapters as InspectorAdapters) || createDefaultInspectorAdapters(); this.context = { getSearchContext: () => this.execution.params.searchContext || {}, getSearchSessionId: () => execution.params.searchSessionId, getKibanaRequest: execution.params.kibanaRequest - ? () => execution.params.kibanaRequest + ? () => execution.params.kibanaRequest! : undefined, variables: execution.params.variables || {}, types: executor.getTypes(), @@ -201,14 +214,14 @@ export class Execution< logDatatable: (name: string, datatable: Datatable) => { inspectorAdapters.tables[name] = datatable; }, - isSyncColorsEnabled: () => execution.params.syncColors, - ...(execution.params as any).extraContext, + isSyncColorsEnabled: () => execution.params.syncColors!, + ...execution.params.extraContext, getExecutionContext: () => execution.params.executionContext, }; this.result = this.input$.pipe( switchMap((input) => - this.race(this.invokeChain(this.state.get().ast.chain, input)).pipe( + this.race(this.invokeChain(this.state.get().ast.chain, input)).pipe( (source) => new Observable>((subscriber) => { let latest: ExecutionResult | undefined; @@ -270,8 +283,8 @@ export class Execution< * N.B. `input` is initialized to `null` rather than `undefined` for legacy reasons, * because in legacy interpreter it was set to `null` by default. */ - public start( - input: Input = null as any, + start( + input = null as unknown as Input, isSubExpression?: boolean ): Observable> { if (this.hasStarted) throw new Error('Execution already started.'); @@ -294,7 +307,10 @@ export class Execution< return this.result; } - invokeChain(chainArr: ExpressionAstFunction[], input: unknown): Observable { + invokeChain( + chainArr: ExpressionAstFunction[], + input: unknown + ): Observable { return of(input).pipe( ...(chainArr.map((link) => switchMap((currentInput) => { @@ -364,19 +380,24 @@ export class Execution< }) ) as Parameters['pipe']>), catchError((error) => of(error)) - ); + ) as Observable; } - invokeFunction( - fn: ExpressionFunction, + invokeFunction( + fn: Fn, input: unknown, args: Record - ): Observable { + ): Observable> { return of(input).pipe( map((currentInput) => this.cast(currentInput, fn.inputTypes)), switchMap((normalizedInput) => this.race(of(fn.fn(normalizedInput, args, this.context)))), - switchMap((fnResult: any) => - isObservable(fnResult) ? fnResult : from(isPromise(fnResult) ? fnResult : [fnResult]) + switchMap( + (fnResult) => + (isObservable(fnResult) + ? fnResult + : from(isPromise(fnResult) ? fnResult : [fnResult])) as Observable< + UnwrapReturnType + > ), map((output) => { // Validate that the function returned the type it said it would. @@ -405,39 +426,49 @@ export class Execution< ); } - public cast(value: any, toTypeNames?: string[]) { + public cast(value: unknown, toTypeNames?: string[]): Type { // If you don't give us anything to cast to, you'll get your input back - if (!toTypeNames || toTypeNames.length === 0) return value; + if (!toTypeNames?.length) { + return value as Type; + } // No need to cast if node is already one of the valid types const fromTypeName = getType(value); - if (toTypeNames.includes(fromTypeName)) return value; + if (toTypeNames.includes(fromTypeName)) { + return value as Type; + } const { types } = this.state.get(); const fromTypeDef = types[fromTypeName]; for (const toTypeName of toTypeNames) { // First check if the current type can cast to this type - if (fromTypeDef && fromTypeDef.castsTo(toTypeName)) { + if (fromTypeDef?.castsTo(toTypeName)) { return fromTypeDef.to(value, toTypeName, types); } // If that isn't possible, check if this type can cast from the current type const toTypeDef = types[toTypeName]; - if (toTypeDef && toTypeDef.castsFrom(fromTypeName)) return toTypeDef.from(value, types); + if (toTypeDef?.castsFrom(fromTypeName)) { + return toTypeDef.from(value, types); + } } throw new Error(`Can not cast '${fromTypeName}' to any of '${toTypeNames.join(', ')}'`); } // Processes the multi-valued AST argument values into arguments that can be passed to the function - resolveArgs(fnDef: ExpressionFunction, input: unknown, argAsts: any): Observable { + resolveArgs( + fnDef: Fn, + input: unknown, + argAsts: Record + ): Observable> { return defer(() => { const { args: argDefs } = fnDef; // Use the non-alias name from the argument definition const dealiasedArgAsts = reduce( - argAsts as Record, + argAsts, (acc, argAst, argName) => { const argDef = getByAlias(argDefs, argName); if (!argDef) { @@ -452,7 +483,7 @@ export class Execution< // Check for missing required arguments. for (const { aliases, default: argDefault, name, required } of Object.values(argDefs)) { if (!(name in dealiasedArgAsts) && typeof argDefault !== 'undefined') { - dealiasedArgAsts[name] = [parse(argDefault, 'argument')]; + dealiasedArgAsts[name] = [parse(argDefault as string, 'argument')]; } if (!required || name in dealiasedArgAsts) { @@ -490,7 +521,7 @@ export class Execution< const argNames = keys(resolveArgFns); if (!argNames.length) { - return from([[]]); + return from([{}]); } const resolvedArgValuesObservable = combineLatest( @@ -523,7 +554,7 @@ export class Execution< }); } - public interpret(ast: ExpressionAstNode, input: T): Observable> { + interpret(ast: ExpressionAstNode, input: T): Observable> { switch (getType(ast)) { case 'expression': const execution = this.execution.executor.createExecution( diff --git a/src/plugins/expressions/common/execution/types.ts b/src/plugins/expressions/common/execution/types.ts index 06eac98feba67..9264891b2e0b8 100644 --- a/src/plugins/expressions/common/execution/types.ts +++ b/src/plugins/expressions/common/execution/types.ts @@ -11,7 +11,7 @@ import type { SerializableRecord } from '@kbn/utility-types'; import type { KibanaRequest } from 'src/core/server'; import type { KibanaExecutionContext } from 'src/core/public'; -import { ExpressionType } from '../expression_types'; +import { Datatable, ExpressionType } from '../expression_types'; import { Adapters, RequestAdapter } from '../../../inspector/common'; import { TablesAdapter } from '../util/tables_adapter'; @@ -69,6 +69,11 @@ export interface ExecutionContext< * Contains the meta-data about the source of the expression. */ getExecutionContext: () => KibanaExecutionContext | undefined; + + /** + * Logs datatable. + */ + logDatatable?(name: string, datatable: Datatable): void; } /** diff --git a/src/plugins/expressions/common/executor/container.ts b/src/plugins/expressions/common/executor/container.ts index 9d3796ac64f45..c8e24974126ff 100644 --- a/src/plugins/expressions/common/executor/container.ts +++ b/src/plugins/expressions/common/executor/container.ts @@ -19,7 +19,7 @@ export interface ExecutorState = Record< context: Context; } -export const defaultState: ExecutorState = { +export const defaultState: ExecutorState = { functions: {}, types: {}, context: {}, @@ -61,7 +61,7 @@ export type ExecutorContainer = Record = Record >( - state: ExecutorState = defaultState + state = defaultState as ExecutorState ): ExecutorContainer => { const container = createStateContainer< ExecutorState, diff --git a/src/plugins/expressions/common/executor/executor.execution.test.ts b/src/plugins/expressions/common/executor/executor.execution.test.ts index 38022c0f7dc4b..ad7e6e6a014c1 100644 --- a/src/plugins/expressions/common/executor/executor.execution.test.ts +++ b/src/plugins/expressions/common/executor/executor.execution.test.ts @@ -8,20 +8,14 @@ import { Executor } from './executor'; import { parseExpression } from '../ast'; +import { Execution } from '../execution/execution'; -// eslint-disable-next-line -const { __getArgs } = require('../execution/execution'); +jest.mock('../execution/execution', () => ({ + Execution: jest.fn(), +})); -jest.mock('../execution/execution', () => { - const mockedModule = { - args: undefined, - __getArgs: () => mockedModule.args, - Execution: function ExecutionMock(...args: any) { - mockedModule.args = args; - }, - }; - - return mockedModule; +beforeEach(() => { + jest.clearAllMocks(); }); describe('Executor mocked execution tests', () => { @@ -31,7 +25,9 @@ describe('Executor mocked execution tests', () => { const executor = new Executor(); executor.createExecution('foo bar="baz"'); - expect(__getArgs()[0].expression).toBe('foo bar="baz"'); + expect(Execution).toHaveBeenCalledWith( + expect.objectContaining({ expression: 'foo bar="baz"' }) + ); }); }); @@ -41,7 +37,9 @@ describe('Executor mocked execution tests', () => { const ast = parseExpression('foo bar="baz"'); executor.createExecution(ast); - expect(__getArgs()[0].expression).toBe(undefined); + expect(Execution).toHaveBeenCalledWith( + expect.not.objectContaining({ expression: expect.anything() }) + ); }); }); }); diff --git a/src/plugins/expressions/common/executor/executor.test.ts b/src/plugins/expressions/common/executor/executor.test.ts index 4a3d6045a7b4a..60f0f0da4e152 100644 --- a/src/plugins/expressions/common/executor/executor.test.ts +++ b/src/plugins/expressions/common/executor/executor.test.ts @@ -145,7 +145,7 @@ describe('Executor', () => { executor.extendContext({ foo }); const execution = executor.createExecution('foo bar="baz"'); - expect((execution.context as any).foo).toBe(foo); + expect(execution.context).toHaveProperty('foo', foo); }); }); }); @@ -175,10 +175,10 @@ describe('Executor', () => { migrations: { '7.10.0': ((state: ExpressionAstFunction, version: string): ExpressionAstFunction => { return migrateFn(state, version); - }) as any as MigrateFunction, + }) as unknown as MigrateFunction, '7.10.1': ((state: ExpressionAstFunction, version: string): ExpressionAstFunction => { return migrateFn(state, version); - }) as any as MigrateFunction, + }) as unknown as MigrateFunction, }, fn: jest.fn(), }; diff --git a/src/plugins/expressions/common/executor/executor.ts b/src/plugins/expressions/common/executor/executor.ts index ce411ea94eafe..f4913c4953bac 100644 --- a/src/plugins/expressions/common/executor/executor.ts +++ b/src/plugins/expressions/common/executor/executor.ts @@ -40,7 +40,7 @@ export interface ExpressionExecOptions { } export class TypesRegistry implements IRegistry { - constructor(private readonly executor: Executor) {} + constructor(private readonly executor: Executor) {} public register( typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition) @@ -62,7 +62,7 @@ export class TypesRegistry implements IRegistry { } export class FunctionsRegistry implements IRegistry { - constructor(private readonly executor: Executor) {} + constructor(private readonly executor: Executor) {} public register( functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition) @@ -100,12 +100,12 @@ export class Executor = Record; @@ -207,15 +207,15 @@ export class Executor = Record { - const executionParams: ExecutionParams = { + const executionParams = { executor: this, params: { ...params, // for canvas we are passing this in, // canvas should be refactored to not pass any extra context in extraContext: this.context, - } as any, - }; + }, + } as ExecutionParams; if (typeof ast === 'string') executionParams.expression = ast; else executionParams.ast = ast; @@ -273,7 +273,7 @@ export class Executor = Record) { + public telemetry(ast: ExpressionAstExpression, telemetryData: Record) { this.walkAst(cloneDeep(ast), (fn, link) => { telemetryData = fn.telemetry(link.arguments, telemetryData); }); diff --git a/src/plugins/expressions/common/expression_functions/arguments.ts b/src/plugins/expressions/common/expression_functions/arguments.ts index 67f83cabc6450..7e39f019f00c2 100644 --- a/src/plugins/expressions/common/expression_functions/arguments.ts +++ b/src/plugins/expressions/common/expression_functions/arguments.ts @@ -24,9 +24,9 @@ export type ArgumentType = * representation of the type. */ // prettier-ignore -type ArrayTypeToArgumentString = - T extends Array ? TypeString : - T extends null ? 'null' : +type ArrayTypeToArgumentString = + T extends Array ? TypeString : + T extends null ? 'null' : never; /** @@ -34,9 +34,9 @@ type ArrayTypeToArgumentString = * string-based representation of the return type. */ // prettier-ignore -type UnresolvedTypeToArgumentString = - T extends (...args: any) => infer ElementType ? TypeString : - T extends null ? 'null' : +type UnresolvedTypeToArgumentString = + T extends (...args: any[]) => infer ElementType ? TypeString : + T extends null ? 'null' : never; /** @@ -44,10 +44,10 @@ type UnresolvedTypeToArgumentString = * string-based representation of the return type. */ // prettier-ignore -type UnresolvedArrayTypeToArgumentString = - T extends Array<(...args: any) => infer ElementType> ? TypeString : - T extends (...args: any) => infer ElementType ? ArrayTypeToArgumentString : - T extends null ? 'null' : +type UnresolvedArrayTypeToArgumentString = + T extends Array<(...args: any[]) => infer ElementType> ? TypeString : + T extends (...args: any[]) => infer ElementType ? ArrayTypeToArgumentString : + T extends null ? 'null' : never; /** A type containing properties common to all Function Arguments. */ diff --git a/src/plugins/expressions/common/expression_functions/expression_function.ts b/src/plugins/expressions/common/expression_functions/expression_function.ts index 05a5dbb638c01..8154534b32ab1 100644 --- a/src/plugins/expressions/common/expression_functions/expression_function.ts +++ b/src/plugins/expressions/common/expression_functions/expression_function.ts @@ -36,7 +36,11 @@ export class ExpressionFunction implements PersistableState, handlers: object) => ExpressionValue; + fn: ( + input: ExpressionValue, + params: Record, + handlers: object + ) => ExpressionValue; /** * A short help text. @@ -56,8 +60,8 @@ export class ExpressionFunction implements PersistableState - ) => Record; + telemetryData: Record + ) => Record; extract: (state: ExpressionAstFunction['arguments']) => { state: ExpressionAstFunction['arguments']; references: SavedObjectReference[]; @@ -100,13 +104,12 @@ export class ExpressionFunction implements PersistableState { // If you don't tell us input types, we'll assume you don't care what you get. - if (!this.inputTypes) return true; - return this.inputTypes.indexOf(type) > -1; + return this.inputTypes?.includes(type) ?? true; }; } diff --git a/src/plugins/expressions/common/expression_functions/expression_function_parameter.ts b/src/plugins/expressions/common/expression_functions/expression_function_parameter.ts index bfc45d65f1c93..9942c9af7ff71 100644 --- a/src/plugins/expressions/common/expression_functions/expression_function_parameter.ts +++ b/src/plugins/expressions/common/expression_functions/expression_function_parameter.ts @@ -6,20 +6,21 @@ * Side Public License, v 1. */ +import { KnownTypeToString } from '../types'; import { ArgumentType } from './arguments'; -export class ExpressionFunctionParameter { +export class ExpressionFunctionParameter { name: string; required: boolean; help: string; - types: string[]; - default: any; + types: ArgumentType['types']; + default?: ArgumentType['default']; aliases: string[]; multi: boolean; resolve: boolean; - options: any[]; + options: T[]; - constructor(name: string, arg: ArgumentType) { + constructor(name: string, arg: ArgumentType) { const { required, help, types, aliases, multi, resolve, options } = arg; if (name === '_') { @@ -38,7 +39,6 @@ export class ExpressionFunctionParameter { } accepts(type: string) { - if (!this.types.length) return true; - return this.types.indexOf(type) > -1; + return !this.types?.length || this.types.includes(type as KnownTypeToString); } } diff --git a/src/plugins/expressions/common/expression_functions/expression_function_parameters.test.ts b/src/plugins/expressions/common/expression_functions/expression_function_parameters.test.ts index 6e47634f5aac2..28ef5243e0fed 100644 --- a/src/plugins/expressions/common/expression_functions/expression_function_parameters.test.ts +++ b/src/plugins/expressions/common/expression_functions/expression_function_parameters.test.ts @@ -21,7 +21,7 @@ describe('ExpressionFunctionParameter', () => { const param = new ExpressionFunctionParameter('foo', { help: 'bar', types: ['baz', 'quux'], - }); + } as ConstructorParameters[1]); expect(param.accepts('baz')).toBe(true); expect(param.accepts('quux')).toBe(true); diff --git a/src/plugins/expressions/common/expression_functions/specs/create_table.ts b/src/plugins/expressions/common/expression_functions/specs/create_table.ts index 5174b258a4d9b..0ce427e817e24 100644 --- a/src/plugins/expressions/common/expression_functions/specs/create_table.ts +++ b/src/plugins/expressions/common/expression_functions/specs/create_table.ts @@ -11,9 +11,9 @@ import { ExpressionFunctionDefinition } from '../types'; import { Datatable, DatatableColumn } from '../../expression_types'; export interface CreateTableArguments { - ids: string[]; - names: string[] | null; - rowCount: number; + ids?: string[]; + names?: string[] | null; + rowCount?: number; } export const createTable: ExpressionFunctionDefinition< diff --git a/src/plugins/expressions/common/expression_functions/specs/font.ts b/src/plugins/expressions/common/expression_functions/specs/font.ts index fa8fc8d387af0..3d189a68119d5 100644 --- a/src/plugins/expressions/common/expression_functions/specs/font.ts +++ b/src/plugins/expressions/common/expression_functions/specs/font.ts @@ -30,7 +30,7 @@ const inlineStyle = (obj: Record) => { return styles.join(';'); }; -interface Arguments { +export interface FontArguments { align?: TextAlignment; color?: string; family?: FontFamily; @@ -41,7 +41,12 @@ interface Arguments { weight?: FontWeight; } -export type ExpressionFunctionFont = ExpressionFunctionDefinition<'font', null, Arguments, Style>; +export type ExpressionFunctionFont = ExpressionFunctionDefinition< + 'font', + null, + FontArguments, + Style +>; export const font: ExpressionFunctionFont = { name: 'font', diff --git a/src/plugins/expressions/common/expression_functions/specs/map_column.ts b/src/plugins/expressions/common/expression_functions/specs/map_column.ts index 23aeee6f9581b..7b2266637bfb5 100644 --- a/src/plugins/expressions/common/expression_functions/specs/map_column.ts +++ b/src/plugins/expressions/common/expression_functions/specs/map_column.ts @@ -110,7 +110,7 @@ export const mapColumn: ExpressionFunctionDefinition< map((rows) => { let type: DatatableColumnType = 'null'; for (const row of rows) { - const rowType = getType(row[id]); + const rowType = getType(row[id]) as DatatableColumnType; if (rowType !== 'null') { type = rowType; break; diff --git a/src/plugins/expressions/common/expression_functions/specs/math.ts b/src/plugins/expressions/common/expression_functions/specs/math.ts index 92a10976428a3..f843f53e4dd88 100644 --- a/src/plugins/expressions/common/expression_functions/specs/math.ts +++ b/src/plugins/expressions/common/expression_functions/specs/math.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { map, zipObject } from 'lodash'; +import { map, zipObject, isString } from 'lodash'; import { i18n } from '@kbn/i18n'; import { evaluate } from '@kbn/tinymath'; import { ExpressionFunctionDefinition } from '../types'; @@ -23,19 +23,18 @@ const TINYMATH = '`TinyMath`'; const TINYMATH_URL = 'https://www.elastic.co/guide/en/kibana/current/canvas-tinymath-functions.html'; -const isString = (val: any): boolean => typeof val === 'string'; - function pivotObjectArray< - RowType extends { [key: string]: any }, - ReturnColumns extends string | number | symbol = keyof RowType ->(rows: RowType[], columns?: string[]): Record { + RowType extends { [key: string]: unknown }, + ReturnColumns extends keyof RowType & string +>(rows: RowType[], columns?: ReturnColumns[]) { const columnNames = columns || Object.keys(rows[0]); if (!columnNames.every(isString)) { throw new Error('Columns should be an array of strings'); } const columnValues = map(columnNames, (name) => map(rows, name)); - return zipObject(columnNames, columnValues); + + return zipObject(columnNames, columnValues) as { [K in ReturnColumns]: Array }; } export const errors = { diff --git a/src/plugins/expressions/common/expression_functions/specs/math_column.ts b/src/plugins/expressions/common/expression_functions/specs/math_column.ts index c59016cd260ab..a2a79ef3f0286 100644 --- a/src/plugins/expressions/common/expression_functions/specs/math_column.ts +++ b/src/plugins/expressions/common/expression_functions/specs/math_column.ts @@ -107,7 +107,7 @@ export const mathColumn: ExpressionFunctionDefinition< let type: DatatableColumnType = 'null'; if (newRows.length) { for (const row of newRows) { - const rowType = getType(row[args.id]); + const rowType = getType(row[args.id]) as DatatableColumnType; if (rowType !== 'null') { type = rowType; break; diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/font.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/font.test.ts index 03b610126660f..e095f4e1bec69 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/font.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/font.test.ts @@ -7,7 +7,8 @@ */ import { openSans } from '../../../fonts'; -import { font } from '../font'; +import { FontWeight, TextAlignment } from '../../../types'; +import { font, FontArguments } from '../font'; import { functionWrapper } from './utils'; describe('font', () => { @@ -22,7 +23,7 @@ describe('font', () => { size: 14, underline: false, weight: 'normal', - }; + } as unknown as FontArguments; describe('default output', () => { const result = fn(null, args); @@ -63,7 +64,7 @@ describe('font', () => { describe('family', () => { it('sets font family', () => { - const result = fn(null, { ...args, family: 'Optima, serif' }); + const result = fn(null, { ...args, family: 'Optima, serif' } as unknown as FontArguments); expect(result.spec.fontFamily).toBe('Optima, serif'); expect(result.css).toContain('font-family:Optima, serif'); }); @@ -79,29 +80,29 @@ describe('font', () => { describe('weight', () => { it('sets font weight', () => { - let result = fn(null, { ...args, weight: 'normal' }); + let result = fn(null, { ...args, weight: FontWeight.NORMAL }); expect(result.spec.fontWeight).toBe('normal'); expect(result.css).toContain('font-weight:normal'); - result = fn(null, { ...args, weight: 'bold' }); + result = fn(null, { ...args, weight: FontWeight.BOLD }); expect(result.spec.fontWeight).toBe('bold'); expect(result.css).toContain('font-weight:bold'); - result = fn(null, { ...args, weight: 'bolder' }); + result = fn(null, { ...args, weight: FontWeight.BOLDER }); expect(result.spec.fontWeight).toBe('bolder'); expect(result.css).toContain('font-weight:bolder'); - result = fn(null, { ...args, weight: 'lighter' }); + result = fn(null, { ...args, weight: FontWeight.LIGHTER }); expect(result.spec.fontWeight).toBe('lighter'); expect(result.css).toContain('font-weight:lighter'); - result = fn(null, { ...args, weight: '400' }); + result = fn(null, { ...args, weight: FontWeight.FOUR }); expect(result.spec.fontWeight).toBe('400'); expect(result.css).toContain('font-weight:400'); }); it('throws when provided an invalid weight', () => { - expect(() => fn(null, { ...args, weight: 'foo' })).toThrow(); + expect(() => fn(null, { ...args, weight: 'foo' as FontWeight })).toThrow(); }); }); @@ -131,25 +132,25 @@ describe('font', () => { describe('align', () => { it('sets text alignment', () => { - let result = fn(null, { ...args, align: 'left' }); + let result = fn(null, { ...args, align: TextAlignment.LEFT }); expect(result.spec.textAlign).toBe('left'); expect(result.css).toContain('text-align:left'); - result = fn(null, { ...args, align: 'center' }); + result = fn(null, { ...args, align: TextAlignment.CENTER }); expect(result.spec.textAlign).toBe('center'); expect(result.css).toContain('text-align:center'); - result = fn(null, { ...args, align: 'right' }); + result = fn(null, { ...args, align: TextAlignment.RIGHT }); expect(result.spec.textAlign).toBe('right'); expect(result.css).toContain('text-align:right'); - result = fn(null, { ...args, align: 'justify' }); + result = fn(null, { ...args, align: TextAlignment.JUSTIFY }); expect(result.spec.textAlign).toBe('justify'); expect(result.css).toContain('text-align:justify'); }); it('throws when provided an invalid alignment', () => { - expect(() => fn(null, { ...args, align: 'foo' })).toThrow(); + expect(() => fn(null, { ...args, align: 'foo' as TextAlignment })).toThrow(); }); }); }); diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/math.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/math.test.ts index 6da00061244da..3761fe0a4f909 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/math.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/math.test.ts @@ -6,19 +6,19 @@ * Side Public License, v 1. */ -import { errors, math } from '../math'; +import { errors, math, MathArguments, MathInput } from '../math'; import { emptyTable, functionWrapper, testTable } from './utils'; describe('math', () => { - const fn = functionWrapper(math); + const fn = functionWrapper(math); it('evaluates math expressions without reference to context', () => { - expect(fn(null, { expression: '10.5345' })).toBe(10.5345); - expect(fn(null, { expression: '123 + 456' })).toBe(579); - expect(fn(null, { expression: '100 - 46' })).toBe(54); + expect(fn(null as unknown as MathInput, { expression: '10.5345' })).toBe(10.5345); + expect(fn(null as unknown as MathInput, { expression: '123 + 456' })).toBe(579); + expect(fn(null as unknown as MathInput, { expression: '100 - 46' })).toBe(54); expect(fn(1, { expression: '100 / 5' })).toBe(20); - expect(fn('foo', { expression: '100 / 5' })).toBe(20); - expect(fn(true, { expression: '100 / 5' })).toBe(20); + expect(fn('foo' as unknown as MathInput, { expression: '100 / 5' })).toBe(20); + expect(fn(true as unknown as MathInput, { expression: '100 / 5' })).toBe(20); expect(fn(testTable, { expression: '100 * 5' })).toBe(500); expect(fn(emptyTable, { expression: '100 * 5' })).toBe(500); }); @@ -54,7 +54,7 @@ describe('math', () => { describe('args', () => { describe('expression', () => { it('sets the math expression to be evaluted', () => { - expect(fn(null, { expression: '10' })).toBe(10); + expect(fn(null as unknown as MathInput, { expression: '10' })).toBe(10); expect(fn(23.23, { expression: 'floor(value)' })).toBe(23); expect(fn(testTable, { expression: 'count(price)' })).toBe(9); expect(fn(testTable, { expression: 'count(name)' })).toBe(9); @@ -99,11 +99,11 @@ describe('math', () => { it('throws when missing expression', () => { expect(() => fn(testTable)).toThrow(new RegExp(errors.emptyExpression().message)); - expect(() => fn(testTable, { expession: '' })).toThrow( + expect(() => fn(testTable, { expession: '' } as unknown as MathArguments)).toThrow( new RegExp(errors.emptyExpression().message) ); - expect(() => fn(testTable, { expession: ' ' })).toThrow( + expect(() => fn(testTable, { expession: ' ' } as unknown as MathArguments)).toThrow( new RegExp(errors.emptyExpression().message) ); }); diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts index 0733b1c77bf40..3f535b7fb7aca 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/theme.test.ts @@ -26,14 +26,14 @@ describe('expression_functions', () => { }; context = { - getSearchContext: () => ({} as any), + getSearchContext: () => ({}), getSearchSessionId: () => undefined, getExecutionContext: () => undefined, types: {}, variables: { theme: themeProps }, - abortSignal: {} as any, - inspectorAdapters: {} as any, - }; + abortSignal: {}, + inspectorAdapters: {}, + } as unknown as typeof context; }); it('returns the selected variable', () => { diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/ui_setting.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/ui_setting.test.ts index 6b3a458aa7e57..053f97ffc8fb0 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/ui_setting.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/ui_setting.test.ts @@ -10,13 +10,15 @@ jest.mock('../../../../common'); import { IUiSettingsClient } from 'src/core/public'; import { getUiSettingFn } from '../ui_setting'; +import { functionWrapper } from './utils'; describe('uiSetting', () => { describe('fn', () => { let getStartDependencies: jest.MockedFunction< Parameters[0]['getStartDependencies'] >; - let uiSetting: ReturnType; + const uiSettingWrapper = () => functionWrapper(getUiSettingFn({ getStartDependencies })); + let uiSetting: ReturnType; let uiSettings: jest.Mocked; beforeEach(() => { @@ -27,13 +29,13 @@ describe('uiSetting', () => { uiSettings, })) as unknown as typeof getStartDependencies; - uiSetting = getUiSettingFn({ getStartDependencies }); + uiSetting = uiSettingWrapper(); }); it('should return a value', () => { uiSettings.get.mockReturnValueOnce('value'); - expect(uiSetting.fn(null, { parameter: 'something' }, {} as any)).resolves.toEqual({ + expect(uiSetting(null, { parameter: 'something' })).resolves.toEqual({ type: 'ui_setting', key: 'something', value: 'value', @@ -41,7 +43,7 @@ describe('uiSetting', () => { }); it('should pass a default value', async () => { - await uiSetting.fn(null, { parameter: 'something', default: 'default' }, {} as any); + await uiSetting(null, { parameter: 'something', default: 'default' }); expect(uiSettings.get).toHaveBeenCalledWith('something', 'default'); }); @@ -51,16 +53,16 @@ describe('uiSetting', () => { throw new Error(); }); - expect(uiSetting.fn(null, { parameter: 'something' }, {} as any)).rejects.toEqual( + expect(uiSetting(null, { parameter: 'something' })).rejects.toEqual( new Error('Invalid parameter "something".') ); }); it('should get a request instance on the server-side', async () => { const request = {}; - await uiSetting.fn(null, { parameter: 'something' }, { + await uiSetting(null, { parameter: 'something' }, { getKibanaRequest: () => request, - } as any); + } as Parameters[2]); const [[getKibanaRequest]] = getStartDependencies.mock.calls; @@ -68,7 +70,7 @@ describe('uiSetting', () => { }); it('should throw an error if request is not provided on the server-side', async () => { - await uiSetting.fn(null, { parameter: 'something' }, {} as any); + await uiSetting(null, { parameter: 'something' }); const [[getKibanaRequest]] = getStartDependencies.mock.calls; diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/utils.ts b/src/plugins/expressions/common/expression_functions/specs/tests/utils.ts index ca41b427a28f7..e3f581d1ae35f 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/utils.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/utils.ts @@ -15,13 +15,15 @@ import { Datatable } from '../../../expression_types'; * Takes a function spec and passes in default args, * overriding with any provided args. */ -export const functionWrapper = ( - spec: AnyExpressionFunctionDefinition +export const functionWrapper = < + ExpressionFunctionDefinition extends AnyExpressionFunctionDefinition +>( + spec: ExpressionFunctionDefinition ) => { const defaultArgs = mapValues(spec.args, (argSpec) => argSpec.default); return ( - context: ContextType, - args: Record = {}, + context?: Parameters[0] | null, + args: Parameters[1] = {}, handlers: ExecutionContext = {} as ExecutionContext ) => spec.fn(context, { ...defaultArgs, ...args }, handlers); }; diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts index 0c5c6b1480201..ca9c9c257f706 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/var.test.ts @@ -24,9 +24,9 @@ describe('expression_functions', () => { getExecutionContext: () => undefined, types: {}, variables: { test: 1 }, - abortSignal: {} as any, - inspectorAdapters: {} as any, - }; + abortSignal: {}, + inspectorAdapters: {}, + } as unknown as typeof context; }); it('returns the selected variable', () => { diff --git a/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts b/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts index 95287f71907a4..b98e8285a1a84 100644 --- a/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts +++ b/src/plugins/expressions/common/expression_functions/specs/tests/var_set.test.ts @@ -17,7 +17,7 @@ describe('expression_functions', () => { const fn = functionWrapper(variableSet); let input: Partial>; let context: ExecutionContext; - let variables: Record; + let variables: Record; beforeEach(() => { input = { timeRange: { from: '0', to: '1' } }; @@ -27,9 +27,9 @@ describe('expression_functions', () => { getExecutionContext: () => undefined, types: {}, variables: { test: 1 }, - abortSignal: {} as any, - inspectorAdapters: {} as any, - }; + abortSignal: {}, + inspectorAdapters: {}, + } as unknown as typeof context; variables = context.variables; }); diff --git a/src/plugins/expressions/common/expression_functions/specs/theme.ts b/src/plugins/expressions/common/expression_functions/specs/theme.ts index 914e5d330bddb..76e97b12a967d 100644 --- a/src/plugins/expressions/common/expression_functions/specs/theme.ts +++ b/src/plugins/expressions/common/expression_functions/specs/theme.ts @@ -12,10 +12,10 @@ import { ExpressionFunctionDefinition } from '../types'; interface Arguments { variable: string; - default: string | number | boolean; + default?: string | number | boolean; } -type Output = any; +type Output = unknown; export type ExpressionFunctionTheme = ExpressionFunctionDefinition< 'theme', diff --git a/src/plugins/expressions/common/expression_functions/specs/var.ts b/src/plugins/expressions/common/expression_functions/specs/var.ts index d0e43a6871478..0ba4d5f439358 100644 --- a/src/plugins/expressions/common/expression_functions/specs/var.ts +++ b/src/plugins/expressions/common/expression_functions/specs/var.ts @@ -36,7 +36,8 @@ export const variable: ExpressionFunctionVar = { }, }, fn(input, args, context) { - const variables: Record = context.variables; + const { variables } = context; + return variables[args.name]; }, }; diff --git a/src/plugins/expressions/common/expression_functions/specs/var_set.ts b/src/plugins/expressions/common/expression_functions/specs/var_set.ts index f3ac6a2ab80d4..aa257940f9ad6 100644 --- a/src/plugins/expressions/common/expression_functions/specs/var_set.ts +++ b/src/plugins/expressions/common/expression_functions/specs/var_set.ts @@ -7,11 +7,12 @@ */ import { i18n } from '@kbn/i18n'; +import type { Serializable } from '@kbn/utility-types'; import { ExpressionFunctionDefinition } from '../types'; interface Arguments { name: string[]; - value: any[]; + value: Serializable[]; } export type ExpressionFunctionVarSet = ExpressionFunctionDefinition< @@ -46,10 +47,11 @@ export const variableSet: ExpressionFunctionVarSet = { }, }, fn(input, args, context) { - const variables: Record = context.variables; + const { variables } = context; args.name.forEach((name, i) => { variables[name] = args.value[i] === undefined ? input : args.value[i]; }); + return input; }, }; diff --git a/src/plugins/expressions/common/expression_functions/types.ts b/src/plugins/expressions/common/expression_functions/types.ts index 0ec61b39608a0..cb3677ed1668c 100644 --- a/src/plugins/expressions/common/expression_functions/types.ts +++ b/src/plugins/expressions/common/expression_functions/types.ts @@ -30,7 +30,7 @@ import { PersistableStateDefinition } from '../../../kibana_utils/common'; export interface ExpressionFunctionDefinition< Name extends string, Input, - Arguments extends Record, + Arguments extends Record, Output, Context extends ExecutionContext = ExecutionContext > extends PersistableStateDefinition { @@ -99,12 +99,14 @@ export interface ExpressionFunctionDefinition< /** * Type to capture every possible expression function definition. */ +/* eslint-disable @typescript-eslint/no-explicit-any */ export type AnyExpressionFunctionDefinition = ExpressionFunctionDefinition< string, any, Record, any >; +/* eslint-enable @typescript-eslint/no-explicit-any */ /** * A mapping of `ExpressionFunctionDefinition`s for functions which the diff --git a/src/plugins/expressions/common/expression_renderers/types.ts b/src/plugins/expressions/common/expression_renderers/types.ts index 8547c1a1bec92..6c889a81a1f80 100644 --- a/src/plugins/expressions/common/expression_renderers/types.ts +++ b/src/plugins/expressions/common/expression_renderers/types.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ +import { ExpressionAstExpression } from '../ast'; + export interface ExpressionRenderDefinition { /** * Technical name of the renderer, used as ID to identify renderer in @@ -46,6 +48,7 @@ export interface ExpressionRenderDefinition { ) => void | Promise; } +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type AnyExpressionRenderDefinition = ExpressionRenderDefinition; /** @@ -59,24 +62,34 @@ export type AnyExpressionRenderDefinition = ExpressionRenderDefinition; */ export type RenderMode = 'edit' | 'preview' | 'view'; +export interface IInterpreterRenderUpdateParams { + newExpression?: string | ExpressionAstExpression; + newParams: Params; +} + +export interface IInterpreterRenderEvent { + name: string; + data?: Context; +} + export interface IInterpreterRenderHandlers { /** * Done increments the number of rendering successes */ - done: () => void; - onDestroy: (fn: () => void) => void; - reload: () => void; - update: (params: any) => void; - event: (event: any) => void; - hasCompatibleActions?: (event: any) => Promise; - getRenderMode: () => RenderMode; + done(): void; + onDestroy(fn: () => void): void; + reload(): void; + update(params: IInterpreterRenderUpdateParams): void; + event(event: IInterpreterRenderEvent): void; + hasCompatibleActions?(event: IInterpreterRenderEvent): Promise; + getRenderMode(): RenderMode; /** * The chart is rendered in a non-interactive environment and should not provide any affordances for interaction like brushing. */ - isInteractive: () => boolean; + isInteractive(): boolean; - isSyncColorsEnabled: () => boolean; + isSyncColorsEnabled(): boolean; /** * This uiState interface is actually `PersistedState` from the visualizations plugin, * but expressions cannot know about vis or it creates a mess of circular dependencies. diff --git a/src/plugins/expressions/common/expression_types/expression_type.ts b/src/plugins/expressions/common/expression_types/expression_type.ts index 1c22b9f13b975..d179beeb76860 100644 --- a/src/plugins/expressions/common/expression_types/expression_type.ts +++ b/src/plugins/expressions/common/expression_types/expression_type.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import type { Serializable } from '@kbn/utility-types'; import { AnyExpressionTypeDefinition, ExpressionValue, ExpressionValueConverter } from './types'; import { getType } from './get_type'; @@ -20,15 +21,15 @@ export class ExpressionType { /** * Type validation, useful for checking function output. */ - validate: (type: any) => void | Error; + validate: (type: unknown) => void | Error; create: unknown; /** * Optional serialization (used when passing context around client/server). */ - serialize?: (value: ExpressionValue) => any; - deserialize?: (serialized: any) => ExpressionValue; + serialize?: (value: Serializable) => unknown; + deserialize?: (serialized: unknown[]) => Serializable; constructor(private readonly definition: AnyExpressionTypeDefinition) { const { name, help, deserialize, serialize, validate } = definition; @@ -38,7 +39,7 @@ export class ExpressionType { this.validate = validate || (() => {}); // Optional - this.create = (definition as any).create; + this.create = (definition as unknown as Record<'create', unknown>).create; this.serialize = serialize; this.deserialize = deserialize; diff --git a/src/plugins/expressions/common/expression_types/get_type.ts b/src/plugins/expressions/common/expression_types/get_type.ts index 052508df41329..17089c78816b6 100644 --- a/src/plugins/expressions/common/expression_types/get_type.ts +++ b/src/plugins/expressions/common/expression_types/get_type.ts @@ -6,14 +6,24 @@ * Side Public License, v 1. */ -export function getType(node: any) { - if (node == null) return 'null'; +export function getType(node: unknown): string { + if (node == null) { + return 'null'; + } + if (Array.isArray(node)) { throw new Error('Unexpected array value encountered.'); } - if (typeof node === 'object') { - if (!node.type) throw new Error('Objects must have a type property'); - return node.type; + + if (typeof node !== 'object') { + return typeof node; } - return typeof node; + + const { type } = node as Record; + + if (!type) { + throw new Error('Objects must have a type property'); + } + + return type as string; } diff --git a/src/plugins/expressions/common/expression_types/specs/datatable.ts b/src/plugins/expressions/common/expression_types/specs/datatable.ts index c268557936ac5..b45c36950f870 100644 --- a/src/plugins/expressions/common/expression_types/specs/datatable.ts +++ b/src/plugins/expressions/common/expression_types/specs/datatable.ts @@ -9,7 +9,7 @@ import type { SerializableRecord } from '@kbn/utility-types'; import { map, pick, zipObject } from 'lodash'; -import { ExpressionTypeDefinition } from '../types'; +import { ExpressionTypeDefinition, ExpressionValueBoxed } from '../types'; import { PointSeries, PointSeriesColumn } from './pointseries'; import { ExpressionValueRender } from './render'; import { SerializedFieldFormat } from '../../types'; @@ -21,7 +21,7 @@ const name = 'datatable'; * @param datatable */ export const isDatatable = (datatable: unknown): datatable is Datatable => - !!datatable && typeof datatable === 'object' && (datatable as any).type === 'datatable'; + (datatable as ExpressionValueBoxed | undefined)?.type === 'datatable'; /** * This type represents the `type` of any `DatatableColumn` in a `Datatable`. @@ -48,6 +48,7 @@ export type DatatableColumnType = /** * This type represents a row in a `Datatable`. */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type DatatableRow = Record; /** @@ -112,7 +113,7 @@ interface RenderedDatatable { export const datatable: ExpressionTypeDefinition = { name, - validate: (table) => { + validate: (table: Record) => { // TODO: Check columns types. Only string, boolean, number, date, allowed for now. if (!table.columns) { throw new Error('datatable must have a columns array, even if it is empty'); diff --git a/src/plugins/expressions/common/expression_types/specs/error.ts b/src/plugins/expressions/common/expression_types/specs/error.ts index 75e49633866f7..b170675b8f489 100644 --- a/src/plugins/expressions/common/expression_types/specs/error.ts +++ b/src/plugins/expressions/common/expression_types/specs/error.ts @@ -22,7 +22,7 @@ export type ExpressionValueError = ExpressionValueBoxed< } >; -export const isExpressionValueError = (value: any): value is ExpressionValueError => +export const isExpressionValueError = (value: unknown): value is ExpressionValueError => getType(value) === 'error'; /** diff --git a/src/plugins/expressions/common/expression_types/specs/pointseries.ts b/src/plugins/expressions/common/expression_types/specs/pointseries.ts index 1c8bddf14cffe..ef2079bd387a0 100644 --- a/src/plugins/expressions/common/expression_types/specs/pointseries.ts +++ b/src/plugins/expressions/common/expression_types/specs/pointseries.ts @@ -7,7 +7,7 @@ */ import { ExpressionTypeDefinition, ExpressionValueBoxed } from '../types'; -import { Datatable } from './datatable'; +import { Datatable, DatatableRow } from './datatable'; import { ExpressionValueRender } from './render'; const name = 'pointseries'; @@ -31,7 +31,7 @@ export interface PointSeriesColumn { */ export type PointSeriesColumns = Record | {}; -export type PointSeriesRow = Record; +export type PointSeriesRow = DatatableRow; /** * A `PointSeries` is a unique structure that represents dots on a chart. diff --git a/src/plugins/expressions/common/expression_types/specs/shape.ts b/src/plugins/expressions/common/expression_types/specs/shape.ts index 2b62dc6458c15..5ad86366a26cc 100644 --- a/src/plugins/expressions/common/expression_types/specs/shape.ts +++ b/src/plugins/expressions/common/expression_types/specs/shape.ts @@ -11,7 +11,7 @@ import { ExpressionValueRender } from './render'; const name = 'shape'; -export const shape: ExpressionTypeDefinition> = { +export const shape: ExpressionTypeDefinition> = { name: 'shape', to: { render: (input) => { diff --git a/src/plugins/expressions/common/expression_types/types.ts b/src/plugins/expressions/common/expression_types/types.ts index a829c2adc923c..15ec82e40314d 100644 --- a/src/plugins/expressions/common/expression_types/types.ts +++ b/src/plugins/expressions/common/expression_types/types.ts @@ -6,6 +6,9 @@ * Side Public License, v 1. */ +import type { ExpressionType } from './expression_type'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type ExpressionValueUnboxed = any; export type ExpressionValueBoxed = { @@ -16,7 +19,7 @@ export type ExpressionValue = ExpressionValueUnboxed | ExpressionValueBoxed; export type ExpressionValueConverter = ( input: I, - availableTypes: Record + availableTypes: Record ) => O; /** @@ -29,18 +32,19 @@ export interface ExpressionTypeDefinition< SerializedType = undefined > { name: Name; - validate?: (type: any) => void | Error; - serialize?: (type: Value) => SerializedType; - deserialize?: (type: SerializedType) => Value; + validate?(type: unknown): void | Error; + serialize?(type: Value): SerializedType; + deserialize?(type: SerializedType): Value; // TODO: Update typings for the `availableTypes` parameter once interfaces for this // have been added elsewhere in the interpreter. from?: { - [type: string]: ExpressionValueConverter; + [type: string]: ExpressionValueConverter; }; to?: { - [type: string]: ExpressionValueConverter; + [type: string]: ExpressionValueConverter; }; help?: string; } -export type AnyExpressionTypeDefinition = ExpressionTypeDefinition; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type AnyExpressionTypeDefinition = ExpressionTypeDefinition; diff --git a/src/plugins/expressions/common/mocks.ts b/src/plugins/expressions/common/mocks.ts index 681fa28268823..4141da06ec04e 100644 --- a/src/plugins/expressions/common/mocks.ts +++ b/src/plugins/expressions/common/mocks.ts @@ -11,7 +11,7 @@ import { ExecutionContext } from './execution/types'; export const createMockExecutionContext = ( extraContext: ExtraContext = {} as ExtraContext ): ExecutionContext & ExtraContext => { - const executionContext: ExecutionContext = { + const executionContext = { getSearchContext: jest.fn(), getSearchSessionId: jest.fn(), getExecutionContext: jest.fn(), @@ -25,10 +25,10 @@ export const createMockExecutionContext = removeEventListener: jest.fn(), }, inspectorAdapters: { - requests: {} as any, - data: {} as any, + requests: {}, + data: {}, }, - }; + } as unknown as ExecutionContext; return { ...executionContext, diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts index f21eaa34d7868..453ea656ec43b 100644 --- a/src/plugins/expressions/common/service/expressions_services.ts +++ b/src/plugins/expressions/common/service/expressions_services.ts @@ -125,7 +125,7 @@ export interface ExpressionsServiceSetup { export interface ExpressionExecutionParams { searchContext?: SerializableRecord; - variables?: Record; + variables?: Record; /** * Whether to execute expression in *debug mode*. In *debug mode* inputs and @@ -148,6 +148,8 @@ export interface ExpressionExecutionParams { inspectorAdapters?: Adapters; executionContext?: KibanaExecutionContext; + + extraContext?: object; } /** @@ -375,7 +377,7 @@ export class ExpressionsService */ public readonly telemetry = ( state: ExpressionAstExpression, - telemetryData: Record = {} + telemetryData: Record = {} ) => { return this.executor.telemetry(state, telemetryData); }; diff --git a/src/plugins/expressions/common/test_helpers/expression_functions/access.ts b/src/plugins/expressions/common/test_helpers/expression_functions/access.ts index 5498e6741bd99..6ddc99b13ee57 100644 --- a/src/plugins/expressions/common/test_helpers/expression_functions/access.ts +++ b/src/plugins/expressions/common/test_helpers/expression_functions/access.ts @@ -8,7 +8,7 @@ import { ExpressionFunctionDefinition } from '../../expression_functions'; -export const access: ExpressionFunctionDefinition<'access', any, { key: string }, any> = { +export const access: ExpressionFunctionDefinition<'access', unknown, { key: string }, unknown> = { name: 'access', help: 'Access key on input object or return the input, if it is not an object', args: { @@ -19,6 +19,10 @@ export const access: ExpressionFunctionDefinition<'access', any, { key: string } }, }, fn: (input, { key }, context) => { - return !input ? input : typeof input === 'object' ? input[key] : input; + return !input + ? input + : typeof input === 'object' + ? (input as Record)[key] + : input; }, }; diff --git a/src/plugins/expressions/common/test_helpers/expression_functions/add.ts b/src/plugins/expressions/common/test_helpers/expression_functions/add.ts index 03c72733166b8..5e646ead7b62f 100644 --- a/src/plugins/expressions/common/test_helpers/expression_functions/add.ts +++ b/src/plugins/expressions/common/test_helpers/expression_functions/add.ts @@ -26,11 +26,11 @@ export const add: ExpressionFunctionDefinition< types: ['null', 'number', 'string'], }, }, - fn: ({ value: value1 }, { val: input2 }, context) => { + fn: ({ value: value1 }, { val: input2 }) => { const value2 = !input2 ? 0 : typeof input2 === 'object' - ? (input2 as any).value + ? (input2 as ExpressionValueNum).value : Number(input2); return { diff --git a/src/plugins/expressions/common/test_helpers/expression_functions/introspect_context.ts b/src/plugins/expressions/common/test_helpers/expression_functions/introspect_context.ts index 9556872d57344..8b2c22df8e086 100644 --- a/src/plugins/expressions/common/test_helpers/expression_functions/introspect_context.ts +++ b/src/plugins/expressions/common/test_helpers/expression_functions/introspect_context.ts @@ -10,9 +10,9 @@ import { ExpressionFunctionDefinition } from '../../expression_functions'; export const introspectContext: ExpressionFunctionDefinition< 'introspectContext', - any, + unknown, { key: string }, - any + unknown > = { name: 'introspectContext', args: { @@ -25,7 +25,7 @@ export const introspectContext: ExpressionFunctionDefinition< fn: (input, args, context) => { return { type: 'any', - result: (context as any)[args.key], + result: context[args.key as keyof typeof context], }; }, }; diff --git a/src/plugins/expressions/common/test_helpers/expression_functions/sleep.ts b/src/plugins/expressions/common/test_helpers/expression_functions/sleep.ts index 04b1c9822a3bb..71a14b3dac10c 100644 --- a/src/plugins/expressions/common/test_helpers/expression_functions/sleep.ts +++ b/src/plugins/expressions/common/test_helpers/expression_functions/sleep.ts @@ -8,7 +8,7 @@ import { ExpressionFunctionDefinition } from '../../expression_functions'; -export const sleep: ExpressionFunctionDefinition<'sleep', any, { time: number }, any> = { +export const sleep: ExpressionFunctionDefinition<'sleep', unknown, { time: number }, unknown> = { name: 'sleep', args: { time: { diff --git a/src/plugins/expressions/common/types/common.ts b/src/plugins/expressions/common/types/common.ts index d8d1a9a4b256a..64b3d00895f56 100644 --- a/src/plugins/expressions/common/types/common.ts +++ b/src/plugins/expressions/common/types/common.ts @@ -37,7 +37,7 @@ export type KnownTypeToString = * `someArgument: Promise` results in `types: ['boolean', 'string']` */ export type TypeString = KnownTypeToString< - T extends ObservableLike ? UnwrapObservable : UnwrapPromiseOrReturn + T extends ObservableLike ? UnwrapObservable : UnwrapPromiseOrReturn >; /** @@ -52,6 +52,7 @@ export type UnmappedTypeStrings = 'date' | 'filter'; * Is used to carry information about how to format data in * a data table as part of the column definition. */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export interface SerializedFieldFormat> { id?: string; params?: TParams; diff --git a/src/plugins/expressions/common/util/expressions_inspector_adapter.ts b/src/plugins/expressions/common/util/expressions_inspector_adapter.ts index 34fa1c8713f5a..bf16635792c1f 100644 --- a/src/plugins/expressions/common/util/expressions_inspector_adapter.ts +++ b/src/plugins/expressions/common/util/expressions_inspector_adapter.ts @@ -7,16 +7,17 @@ */ import { EventEmitter } from 'events'; +import { ExpressionAstNode } from '..'; export class ExpressionsInspectorAdapter extends EventEmitter { - private _ast: any = {}; + private _ast = {} as ExpressionAstNode; - public logAST(ast: any): void { + logAST(ast: ExpressionAstNode): void { this._ast = ast; this.emit('change', this._ast); } - public get ast() { + public get ast(): ExpressionAstNode { return this._ast; } } diff --git a/src/plugins/expressions/common/util/test_utils.ts b/src/plugins/expressions/common/util/test_utils.ts index 59bd0a4235d9b..a6a4771bdf89d 100644 --- a/src/plugins/expressions/common/util/test_utils.ts +++ b/src/plugins/expressions/common/util/test_utils.ts @@ -14,7 +14,7 @@ export const createMockContext = () => { getSearchSessionId: () => undefined, types: {}, variables: {}, - abortSignal: {} as any, - inspectorAdapters: {} as any, + abortSignal: {}, + inspectorAdapters: {}, } as ExecutionContext; }; diff --git a/src/plugins/expressions/public/loader.test.ts b/src/plugins/expressions/public/loader.test.ts index ff960f4a3a80d..f22963cedf612 100644 --- a/src/plugins/expressions/public/loader.test.ts +++ b/src/plugins/expressions/public/loader.test.ts @@ -16,12 +16,14 @@ import { IInterpreterRenderHandlers, RenderMode, AnyExpressionFunctionDefinition, + ExpressionsService, + ExecutionContract, } from '../common'; // eslint-disable-next-line const { __getLastExecution, __getLastRenderMode } = require('./services'); -const element: HTMLElement = null as any; +const element = null as unknown as HTMLElement; let testScheduler: TestScheduler; @@ -36,8 +38,9 @@ jest.mock('./services', () => { }, }; - // eslint-disable-next-line - const service = new (require('../common/service/expressions_services').ExpressionsService as any)(); + const service: ExpressionsService = + // eslint-disable-next-line @typescript-eslint/no-var-requires + new (require('../common/service/expressions_services').ExpressionsService)(); const testFn: AnyExpressionFunctionDefinition = { fn: () => ({ type: 'render', as: 'test' }), @@ -54,9 +57,9 @@ jest.mock('./services', () => { service.start(); + let execution: ExecutionContract; const moduleMock = { - __execution: undefined, - __getLastExecution: () => moduleMock.__execution, + __getLastExecution: () => execution, __getLastRenderMode: () => renderMode, getRenderersRegistry: () => ({ get: (id: string) => renderers[id], @@ -72,13 +75,14 @@ jest.mock('./services', () => { }; const execute = service.execute; - service.execute = (...args: any) => { - const execution = execute(...args); + + jest.spyOn(service, 'execute').mockImplementation((...args) => { + execution = execute(...args); jest.spyOn(execution, 'getData'); jest.spyOn(execution, 'cancel'); - moduleMock.__execution = execution; + return execution; - }; + }); return moduleMock; }); diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts index 3ab7473d8d735..b0a54e3dec35d 100644 --- a/src/plugins/expressions/public/loader.ts +++ b/src/plugins/expressions/public/loader.ts @@ -9,7 +9,7 @@ import { BehaviorSubject, Observable, Subject, Subscription, asyncScheduler, identity } from 'rxjs'; import { filter, map, delay, throttleTime } from 'rxjs/operators'; import { defaults } from 'lodash'; -import { UnwrapObservable } from '@kbn/utility-types'; +import { SerializableRecord, UnwrapObservable } from '@kbn/utility-types'; import { Adapters } from '../../inspector/public'; import { IExpressionLoaderParams } from './types'; import { ExpressionAstExpression } from '../common'; @@ -18,7 +18,7 @@ import { ExecutionContract } from '../common/execution/execution_contract'; import { ExpressionRenderHandler } from './render'; import { getExpressionsService } from './services'; -type Data = any; +type Data = unknown; export class ExpressionLoader { data$: ReturnType; @@ -156,7 +156,7 @@ export class ExpressionLoader { }; private render(data: Data): void { - this.renderHandler.render(data, this.params.uiState); + this.renderHandler.render(data as SerializableRecord, this.params.uiState); } private setParams(params?: IExpressionLoaderParams) { @@ -169,7 +169,7 @@ export class ExpressionLoader { {}, params.searchContext, this.params.searchContext || {} - ) as any; + ); } if (params.uiState && this.params) { this.params.uiState = params.uiState; diff --git a/src/plugins/expressions/public/react_expression_renderer.test.tsx b/src/plugins/expressions/public/react_expression_renderer.test.tsx index d31a4c947b09d..f1932ce7dd6ba 100644 --- a/src/plugins/expressions/public/react_expression_renderer.test.tsx +++ b/src/plugins/expressions/public/react_expression_renderer.test.tsx @@ -14,6 +14,7 @@ import { ReactExpressionRenderer } from './react_expression_renderer'; import { ExpressionLoader } from './loader'; import { mount } from 'enzyme'; import { EuiProgress } from '@elastic/eui'; +import { IInterpreterRenderHandlers } from '../common'; import { RenderErrorHandlerFnType } from './types'; import { ExpressionRendererEvent } from './render'; @@ -234,7 +235,7 @@ describe('ExpressionRenderer', () => { done: () => { renderSubject.next(1); }, - } as any); + } as IInterpreterRenderHandlers); }); instance.update(); diff --git a/src/plugins/expressions/public/render.test.ts b/src/plugins/expressions/public/render.test.ts index 61dc0a25439b4..8d4298785572a 100644 --- a/src/plugins/expressions/public/render.test.ts +++ b/src/plugins/expressions/public/render.test.ts @@ -8,6 +8,7 @@ import { ExpressionRenderHandler, render } from './render'; import { Observable } from 'rxjs'; +import { SerializableRecord } from '@kbn/utility-types'; import { ExpressionRenderError } from './types'; import { getRenderersRegistry } from './services'; import { first, take, toArray } from 'rxjs/operators'; @@ -79,11 +80,11 @@ describe('ExpressionRenderHandler', () => { it('in case of error render$ should emit when error renderer is finished', async () => { const expressionRenderHandler = new ExpressionRenderHandler(element); - expressionRenderHandler.render(false); + expressionRenderHandler.render(false as unknown as SerializableRecord); const promise1 = expressionRenderHandler.render$.pipe(first()).toPromise(); await expect(promise1).resolves.toEqual(1); - expressionRenderHandler.render(false); + expressionRenderHandler.render(false as unknown as SerializableRecord); const promise2 = expressionRenderHandler.render$.pipe(first()).toPromise(); await expect(promise2).resolves.toEqual(2); }); @@ -92,7 +93,7 @@ describe('ExpressionRenderHandler', () => { const expressionRenderHandler = new ExpressionRenderHandler(element, { onRenderError: mockMockErrorRenderFunction, }); - await expressionRenderHandler.render(false); + await expressionRenderHandler.render(false as unknown as SerializableRecord); expect(getHandledError()!.message).toEqual( `invalid data provided to the expression renderer` ); @@ -122,7 +123,8 @@ describe('ExpressionRenderHandler', () => { get: () => ({ render: (domNode: HTMLElement, config: unknown, handlers: IInterpreterRenderHandlers) => { handlers.hasCompatibleActions!({ - foo: 'bar', + name: 'something', + data: 'bar', }); }, }), @@ -136,7 +138,8 @@ describe('ExpressionRenderHandler', () => { await expressionRenderHandler.render({ type: 'render', as: 'something' }); expect(hasCompatibleActions).toHaveBeenCalledTimes(1); expect(hasCompatibleActions.mock.calls[0][0]).toEqual({ - foo: 'bar', + name: 'something', + data: 'bar', }); }); @@ -156,7 +159,7 @@ describe('ExpressionRenderHandler', () => { it('default renderer should use notification service', async () => { const expressionRenderHandler = new ExpressionRenderHandler(element); const promise1 = expressionRenderHandler.render$.pipe(first()).toPromise(); - expressionRenderHandler.render(false); + expressionRenderHandler.render(false as unknown as SerializableRecord); await expect(promise1).resolves.toEqual(1); expect(mockNotificationService.toasts.addError).toBeCalledWith( expect.objectContaining({ @@ -175,7 +178,7 @@ describe('ExpressionRenderHandler', () => { const expressionRenderHandler1 = new ExpressionRenderHandler(element, { onRenderError: mockMockErrorRenderFunction, }); - expressionRenderHandler1.render(false); + expressionRenderHandler1.render(false as unknown as SerializableRecord); const renderPromiseAfterRender = expressionRenderHandler1.render$.pipe(first()).toPromise(); await expect(renderPromiseAfterRender).resolves.toEqual(1); expect(getHandledError()!.message).toEqual( @@ -188,7 +191,7 @@ describe('ExpressionRenderHandler', () => { onRenderError: mockMockErrorRenderFunction, }); const renderPromiseBeforeRender = expressionRenderHandler2.render$.pipe(first()).toPromise(); - expressionRenderHandler2.render(false); + expressionRenderHandler2.render(false as unknown as SerializableRecord); await expect(renderPromiseBeforeRender).resolves.toEqual(1); expect(getHandledError()!.message).toEqual( 'invalid data provided to the expression renderer' @@ -199,9 +202,9 @@ describe('ExpressionRenderHandler', () => { // that observables will emit previous result if subscription happens after render it('should emit previous render and error results', async () => { const expressionRenderHandler = new ExpressionRenderHandler(element); - expressionRenderHandler.render(false); + expressionRenderHandler.render(false as unknown as SerializableRecord); const renderPromise = expressionRenderHandler.render$.pipe(take(2), toArray()).toPromise(); - expressionRenderHandler.render(false); + expressionRenderHandler.render(false as unknown as SerializableRecord); await expect(renderPromise).resolves.toEqual([1, 2]); }); }); diff --git a/src/plugins/expressions/public/render.ts b/src/plugins/expressions/public/render.ts index e9a65d1e8f12e..8635a4033bde5 100644 --- a/src/plugins/expressions/public/render.ts +++ b/src/plugins/expressions/public/render.ts @@ -9,13 +9,20 @@ import * as Rx from 'rxjs'; import { Observable } from 'rxjs'; import { filter } from 'rxjs/operators'; +import { isNumber } from 'lodash'; +import { SerializableRecord } from '@kbn/utility-types'; import { ExpressionRenderError, RenderErrorHandlerFnType, IExpressionLoaderParams } from './types'; import { renderErrorHandler as defaultRenderErrorHandler } from './render_error_handler'; -import { IInterpreterRenderHandlers, ExpressionAstExpression, RenderMode } from '../common'; +import { + IInterpreterRenderHandlers, + IInterpreterRenderEvent, + IInterpreterRenderUpdateParams, + RenderMode, +} from '../common'; import { getRenderersRegistry } from './services'; -export type IExpressionRendererExtraHandlers = Record; +export type IExpressionRendererExtraHandlers = Record; export interface ExpressionRenderHandlerParams { onRenderError?: RenderErrorHandlerFnType; @@ -25,15 +32,10 @@ export interface ExpressionRenderHandlerParams { hasCompatibleActions?: (event: ExpressionRendererEvent) => Promise; } -export interface ExpressionRendererEvent { - name: string; - data: any; -} +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type ExpressionRendererEvent = IInterpreterRenderEvent; -interface UpdateValue { - newExpression?: string | ExpressionAstExpression; - newParams: IExpressionLoaderParams; -} +type UpdateValue = IInterpreterRenderUpdateParams; export class ExpressionRenderHandler { render$: Observable; @@ -41,7 +43,7 @@ export class ExpressionRenderHandler { events$: Observable; private element: HTMLElement; - private destroyFn?: any; + private destroyFn?: Function; private renderCount: number = 0; private renderSubject: Rx.BehaviorSubject; private eventsSubject: Rx.Subject; @@ -66,16 +68,14 @@ export class ExpressionRenderHandler { this.onRenderError = onRenderError || defaultRenderErrorHandler; - this.renderSubject = new Rx.BehaviorSubject(null as any | null); - this.render$ = this.renderSubject - .asObservable() - .pipe(filter((_) => _ !== null)) as Observable; + this.renderSubject = new Rx.BehaviorSubject(null); + this.render$ = this.renderSubject.asObservable().pipe(filter(isNumber)); this.updateSubject = new Rx.Subject(); this.update$ = this.updateSubject.asObservable(); this.handlers = { - onDestroy: (fn: any) => { + onDestroy: (fn: Function) => { this.destroyFn = fn; }, done: () => { @@ -104,14 +104,14 @@ export class ExpressionRenderHandler { }; } - render = async (value: any, uiState?: any) => { + render = async (value: SerializableRecord, uiState?: unknown) => { if (!value || typeof value !== 'object') { return this.handleRenderError(new Error('invalid data provided to the expression renderer')); } if (value.type !== 'render' || !value.as) { if (value.type === 'error') { - return this.handleRenderError(value.error); + return this.handleRenderError(value.error as unknown as ExpressionRenderError); } else { return this.handleRenderError( new Error('invalid data provided to the expression renderer') @@ -119,20 +119,20 @@ export class ExpressionRenderHandler { } } - if (!getRenderersRegistry().get(value.as)) { + if (!getRenderersRegistry().get(value.as as string)) { return this.handleRenderError(new Error(`invalid renderer id '${value.as}'`)); } try { // Rendering is asynchronous, completed by handlers.done() await getRenderersRegistry() - .get(value.as)! + .get(value.as as string)! .render(this.element, value.value, { ...this.handlers, uiState, - } as any); + }); } catch (e) { - return this.handleRenderError(e); + return this.handleRenderError(e as ExpressionRenderError); } }; @@ -156,10 +156,10 @@ export class ExpressionRenderHandler { export function render( element: HTMLElement, - data: any, + data: unknown, options?: ExpressionRenderHandlerParams ): ExpressionRenderHandler { const handler = new ExpressionRenderHandler(element, options); - handler.render(data); + handler.render(data as SerializableRecord); return handler; } diff --git a/src/plugins/expressions/public/types/index.ts b/src/plugins/expressions/public/types/index.ts index 172f322f8892a..ea47403332c74 100644 --- a/src/plugins/expressions/public/types/index.ts +++ b/src/plugins/expressions/public/types/index.ts @@ -36,7 +36,7 @@ export interface ExpressionInterpreter { export interface IExpressionLoaderParams { searchContext?: SerializableRecord; context?: ExpressionValue; - variables?: Record; + variables?: Record; // Enables debug tracking on each expression in the AST debug?: boolean; disableCaching?: boolean; diff --git a/src/plugins/vis_type_markdown/public/markdown_fn.test.ts b/src/plugins/vis_type_markdown/public/markdown_fn.test.ts index bef0b32e392f0..148a15fb9fc8a 100644 --- a/src/plugins/vis_type_markdown/public/markdown_fn.test.ts +++ b/src/plugins/vis_type_markdown/public/markdown_fn.test.ts @@ -8,6 +8,7 @@ import { functionWrapper } from '../../expressions/common/expression_functions/specs/tests/utils'; import { createMarkdownVisFn } from './markdown_fn'; +import { Arguments } from './types'; describe('interpreter/functions#markdown', () => { const fn = functionWrapper(createMarkdownVisFn()); @@ -15,7 +16,7 @@ describe('interpreter/functions#markdown', () => { font: { spec: { fontSize: 12 } }, openLinksInNewTab: true, markdown: '## hello _markdown_', - }; + } as unknown as Arguments; it('returns an object with the correct structure', async () => { const actual = await fn(null, args, undefined); diff --git a/src/plugins/vis_types/metric/public/metric_vis_fn.test.ts b/src/plugins/vis_types/metric/public/metric_vis_fn.test.ts index 3844c0f21ed05..28124a653629c 100644 --- a/src/plugins/vis_types/metric/public/metric_vis_fn.test.ts +++ b/src/plugins/vis_types/metric/public/metric_vis_fn.test.ts @@ -10,13 +10,15 @@ import { createMetricVisFn } from './metric_vis_fn'; import { functionWrapper } from '../../../expressions/common/expression_functions/specs/tests/utils'; import { Datatable } from '../../../expressions/common/expression_types/specs'; +type Arguments = Parameters['fn']>[1]; + describe('interpreter/functions#metric', () => { const fn = functionWrapper(createMetricVisFn()); const context = { type: 'datatable', rows: [{ 'col-0-1': 0 }], columns: [{ id: 'col-0-1', name: 'Count' }], - }; + } as unknown as Datatable; const args = { percentageMode: false, useRanges: false, @@ -50,7 +52,7 @@ describe('interpreter/functions#metric', () => { aggType: 'count', }, ], - }; + } as unknown as Arguments; it('returns an object with the correct structure', () => { const actual = fn(context, args, undefined); diff --git a/src/plugins/vis_types/pie/public/pie_fn.test.ts b/src/plugins/vis_types/pie/public/pie_fn.test.ts index d0e0af9807f34..9ba21cdc847e5 100644 --- a/src/plugins/vis_types/pie/public/pie_fn.test.ts +++ b/src/plugins/vis_types/pie/public/pie_fn.test.ts @@ -8,6 +8,7 @@ import { functionWrapper } from '../../../expressions/common/expression_functions/specs/tests/utils'; import { createPieVisFn } from './pie_fn'; +import { PieVisConfig } from './types'; import { Datatable } from '../../../expressions/common/expression_types/specs'; describe('interpreter/functions#pie', () => { @@ -16,7 +17,7 @@ describe('interpreter/functions#pie', () => { type: 'datatable', rows: [{ 'col-0-1': 0 }], columns: [{ id: 'col-0-1', name: 'Count' }], - }; + } as unknown as Datatable; const visConfig = { addTooltip: true, addLegend: true, @@ -43,7 +44,7 @@ describe('interpreter/functions#pie', () => { params: {}, aggType: 'count', }, - }; + } as unknown as PieVisConfig; beforeEach(() => { jest.clearAllMocks(); diff --git a/src/plugins/vis_types/table/public/table_vis_fn.test.ts b/src/plugins/vis_types/table/public/table_vis_fn.test.ts index 8b08bca160478..d0d9a414bbcce 100644 --- a/src/plugins/vis_types/table/public/table_vis_fn.test.ts +++ b/src/plugins/vis_types/table/public/table_vis_fn.test.ts @@ -8,6 +8,7 @@ import { createTableVisFn } from './table_vis_fn'; import { tableVisResponseHandler } from './utils'; +import { TableVisConfig } from './types'; import { functionWrapper } from '../../../expressions/common/expression_functions/specs/tests/utils'; import { Datatable } from '../../../expressions/common/expression_types/specs'; @@ -24,7 +25,7 @@ describe('interpreter/functions#table', () => { type: 'datatable', rows: [{ 'col-0-1': 0 }], columns: [{ id: 'col-0-1', name: 'Count' }], - }; + } as unknown as Datatable; const visConfig = { title: 'My Chart title', perPage: 10, @@ -52,7 +53,7 @@ describe('interpreter/functions#table', () => { }, ], buckets: [], - }; + } as unknown as TableVisConfig; beforeEach(() => { jest.clearAllMocks(); diff --git a/src/plugins/vis_types/vislib/public/pie_fn.test.ts b/src/plugins/vis_types/vislib/public/pie_fn.test.ts index 0df7bf1365bea..9c317f9e72dc1 100644 --- a/src/plugins/vis_types/vislib/public/pie_fn.test.ts +++ b/src/plugins/vis_types/vislib/public/pie_fn.test.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import type { Datatable } from 'src/plugins/expressions'; import { functionWrapper } from '../../../expressions/common/expression_functions/specs/tests/utils'; import { createPieVisFn } from './pie_fn'; // @ts-ignore @@ -34,7 +35,7 @@ describe('interpreter/functions#pie', () => { type: 'datatable', rows: [{ 'col-0-1': 0 }], columns: [{ id: 'col-0-1', name: 'Count' }], - }; + } as unknown as Datatable; const visConfig = { type: 'pie', addTooltip: true, diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts index 4c37d9acc4868..63c3f1dcabcaf 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { Datatable, ExpressionFunctionDefinition, getType } from '../../../types'; +import { + Datatable, + DatatableColumnType, + ExpressionFunctionDefinition, + getType, +} from '../../../types'; import { getFunctionHelp } from '../../../i18n'; interface Arguments { @@ -30,14 +35,14 @@ export function asFn(): ExpressionFunctionDefinition<'as', Input, Arguments, Dat default: 'value', }, }, - fn: (input, args) => { + fn: (input, args): Datatable => { return { type: 'datatable', columns: [ { id: args.name, name: args.name, - meta: { type: getType(input) }, + meta: { type: getType(input) as DatatableColumnType }, }, ], rows: [ diff --git a/x-pack/plugins/canvas/public/components/function_reference_generator/generate_function_reference.ts b/x-pack/plugins/canvas/public/components/function_reference_generator/generate_function_reference.ts index 075e65bc24dab..289704ae79539 100644 --- a/x-pack/plugins/canvas/public/components/function_reference_generator/generate_function_reference.ts +++ b/x-pack/plugins/canvas/public/components/function_reference_generator/generate_function_reference.ts @@ -156,7 +156,7 @@ ${examplesBlock} *Returns:* ${output ? wrapInBackTicks(output) : 'Depends on your input and arguments'}\n\n`; }; -const getArgsTable = (args: { [key: string]: ExpressionFunctionParameter }) => { +const getArgsTable = (args: { [key: string]: ExpressionFunctionParameter }) => { if (!args || Object.keys(args).length === 0) { return 'None'; } diff --git a/x-pack/plugins/lens/common/expressions/format_column/format_column.test.ts b/x-pack/plugins/lens/common/expressions/format_column/format_column.test.ts index 28f9b08eff1cb..4d53f96c71fd8 100644 --- a/x-pack/plugins/lens/common/expressions/format_column/format_column.test.ts +++ b/x-pack/plugins/lens/common/expressions/format_column/format_column.test.ts @@ -7,11 +7,10 @@ import { Datatable, DatatableColumn } from 'src/plugins/expressions/public'; import { functionWrapper } from 'src/plugins/expressions/common/expression_functions/specs/tests/utils'; -import { FormatColumnArgs, formatColumn } from './index'; +import { formatColumn } from './index'; describe('format_column', () => { - const fn: (input: Datatable, args: FormatColumnArgs) => Promise = - functionWrapper(formatColumn); + const fn = functionWrapper(formatColumn); let datatable: Datatable; From ba7bea456ab1e86f769eaf9f30373eafc80539cd Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Mon, 4 Oct 2021 10:31:47 -0600 Subject: [PATCH 51/98] [Security Solution] Migrates siem.notifications ruleAlertId to saved object references array (#113205) ## Summary Fixes https://github.com/elastic/kibana/issues/113276 * Migrates the legacy `siem.notifications` "ruleAlertId" to be within the references array * Adds code to serialize and de-serialize "ruleAlertId" from the saved object references array * Adds migration code to `kibana-alerting` to migrate on startup * Adds `legacy_saved_object_references/README.md` which describes how to test and what those files are for. * Updates earlier similar `signals/saved_object_references/README.md` after reviewing it during my work * Names these files the format of `legacy_foo` since this is all considered legacy work and will be removed once the legacy notification system is removed after customers have migrated. * Adds unit tests * Adds 2e2 tests We only migrate if we find these conditions and cases: * "ruleAlertId" is not `null`, `undefined` or malformed data * The"ruleAlertId" references do not already have an exceptionItem reference already found within it. We migrate on the common use case: * "ruleAlertId" exists and is a string We do these additional (mis-use) cases and steps as well. These should NOT be common things that happen but we safe guard for them here: * If the migration is run twice we are idempotent and do NOT add duplicates or remove items. * If the migration was partially successful but re-run a second time, we only add what is missing. Again no duplicates or removed items should occur. * If the saved object references already exists and contains a different or foreign value, we will retain the foreign reference(s) and still migrate. Before migration you should see data structures like this if you query: ```json # Get the alert type of "siem-notifications" which is part of the legacy system. GET .kibana/_search { "query": { "term": { "alert.alertTypeId": "siem.notifications" } } } ``` ```json "data..omitted": "data..omitted", "params" : { "ruleAlertId" : "933ca720-1be1-11ec-a722-83da1c22a481" <-- Pre-migration we had this Saved Object ID which is not part of references array below }, "actions" : [ { "group" : "default", "params" : { "message" : "Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts" }, "actionTypeId" : ".slack", "actionRef" : "action_0" <-- Pre-migration this is correct as this work is already done within the alerting plugin }, "references" : [ { "id" : "879e8ff0-1be1-11ec-a722-83da1c22a481", "name" : "action_0", <-- Pre-migration this is correct as this work is already done within the alerting plugin "type" : "action" } ] ], "data..omitted": "data..omitted", ``` After migration you should see data structures like this: ```json "data..omitted": "data..omitted", "params" : { "ruleAlertId" : "933ca720-1be1-11ec-a722-83da1c22a481" <-- Post-migration this is not used but rather the serialized version references is used instead. }, "actions" : [ { "group" : "default", "params" : { "message" : "Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts" }, "actionTypeId" : ".slack", "actionRef" : "action_0" }, "references" : [ { "id" : "879e8ff0-1be1-11ec-a722-83da1c22a481", "name" : "action_0", "type" : "action" }, { "id" : "933ca720-1be1-11ec-a722-83da1c22a481", <-- Our id here is preferred and used during serialization. "name" : "param:alert_0", <-- We add the name of our reference which is param:alert_0 similar to action_0 but with "param" "type" : "alert" <-- We add the type which is type of alert to the references } ] ], "data..omitted": "data..omitted", ``` ## Manual testing There are e2e and unit tests but for any manual testing or verification you can do the following: If you have a 7.14.0 system and can migrate it forward that is the most straight forward way to ensure this does migrate correctly and forward. You should see that the legacy notification system still operates as expected. If you are a developer off of master and want to test different scenarios then this section is for below as it is more involved and harder to do but goes into more depth: * Create a rule and activate it normally within security_solution * Do not add actions to the rule at this point as we are exercising the older legacy system. However, you want at least one action configured such as a slack notification. * Within dev tools do a query for all your actions and grab one of the `_id` of them without their prefix: ```json # See all your actions GET .kibana/_search { "query": { "term": { "type": "action" } } } ``` Mine was `"_id" : "action:879e8ff0-1be1-11ec-a722-83da1c22a481"`, so I will be copying the ID of `879e8ff0-1be1-11ec-a722-83da1c22a481` Go to the file `detection_engine/scripts/legacy_notifications/one_action.json` and add this id to the file. Something like this: ```json { "name": "Legacy notification with one action", "interval": "1m", <--- You can use whatever you want. Real values are "1h", "1d", "1w". I use "1m" for testing purposes. "actions": [ { "id": "879e8ff0-1be1-11ec-a722-83da1c22a481", <--- My action id "group": "default", "params": { "message": "Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts" }, "actionTypeId": ".slack" <--- I am a slack action id type. } ] } ``` Query for an alert you want to add manually add back a legacy notification to it. Such as: ```json # See all your siem.signals alert types and choose one GET .kibana/_search { "query": { "term": { "alert.alertTypeId": "siem.signals" } } } ``` Grab the `_id` without the alert prefix. For mine this was `933ca720-1be1-11ec-a722-83da1c22a481` Within the directory of detection_engine/scripts execute the script: ```json ./post_legacy_notification.sh 933ca720-1be1-11ec-a722-83da1c22a481 { "ok": "acknowledged" } ``` which is going to do a few things. See the file `detection_engine/routes/rules/legacy_create_legacy_notification.ts` for the definition of the route and what it does in full, but we should notice that we have now: Created a legacy side car action object of type `siem-detection-engine-rule-actions` you can see in dev tools: ```json # See the actions "side car" which are part of the legacy notification system. GET .kibana/_search { "query": { "term": { "type": { "value": "siem-detection-engine-rule-actions" } } } } ``` But more importantly what the saved object references are which should be this: ```json # Get the alert type of "siem-notifications" which is part of the legacy system. GET .kibana/_search { "query": { "term": { "alert.alertTypeId": "siem.notifications" } } } ``` If you need to ad-hoc test what happens when the migration runs you can get the id of an alert and downgrade it, then restart Kibana. The `ctx._source.references.remove(1)` removes the last element of the references array which is assumed to have a rule. But it might not, so ensure you check your data structure and adjust accordingly. ```json POST .kibana/_update/alert:933ca720-1be1-11ec-a722-83da1c22a481 { "script" : { "source": """ ctx._source.migrationVersion.alert = "7.15.0"; ctx._source.references.remove(1); """, "lang": "painless" } } ``` If you just want to remove your your "param:alert_0" and it is the second array element to test the errors within the console then you would use ```json POST .kibana/_update/alert:933ca720-1be1-11ec-a722-83da1c22a481 { "script" : { "source": """ ctx._source.references.remove(1); """, "lang": "painless" } } ``` Check your log files and should see errors about the saved object references missing until you restart Kibana. Once you restart then it will migrate forward and you will no longer see errors. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../server/saved_objects/migrations.test.ts | 217 ++++++++++++++++++ .../server/saved_objects/migrations.ts | 60 ++++- .../legacy_rules_notification_alert_type.ts | 19 +- .../legacy_saved_object_references/README.md | 217 ++++++++++++++++++ .../legacy_extract_references.test.ts | 55 +++++ .../legacy_extract_references.ts | 62 +++++ .../legacy_extract_rule_id.test.ts | 58 +++++ .../legacy_extract_rule_id.ts | 46 ++++ .../legacy_inject_references.test.ts | 74 ++++++ .../legacy_inject_references.ts | 53 +++++ .../legacy_inject_rule_id_references.test.ts | 101 ++++++++ .../legacy_inject_rule_id_references.ts | 60 +++++ .../notifications/legacy_types.ts | 26 ++- .../legacy_notifications/one_action.json | 2 +- .../signals/saved_object_references/README.md | 22 +- .../spaces_only/tests/alerting/migrations.ts | 16 ++ .../functional/es_archives/alerts/data.json | 42 +++- 17 files changed, 1117 insertions(+), 13 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/README.md create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_references.test.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_references.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_rule_id.test.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_rule_id.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_references.test.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_references.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.test.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.ts diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts index 729286b594089..3f7cdecf4affd 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts @@ -1696,6 +1696,223 @@ describe('successful migrations', () => { }, }); }); + + test('security solution is migrated to saved object references if it has a "ruleAlertId"', () => { + const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0']; + const alert = getMockData({ + alertTypeId: 'siem.notifications', + params: { + ruleAlertId: '123', + }, + }); + + expect(migration7160(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + legacyId: alert.id, + }, + references: [ + { + name: 'param:alert_0', + id: '123', + type: 'alert', + }, + ], + }); + }); + + test('security solution does not migrate anything if its type is not siem.notifications', () => { + const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0']; + const alert = getMockData({ + alertTypeId: 'other-type', + params: { + ruleAlertId: '123', + }, + }); + + expect(migration7160(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + legacyId: alert.id, + }, + }); + }); + test('security solution does not change anything if "ruleAlertId" is missing', () => { + const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0']; + const alert = getMockData({ + alertTypeId: 'siem.notifications', + params: {}, + }); + + expect(migration7160(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + legacyId: alert.id, + }, + }); + }); + + test('security solution will keep existing references if we do not have a "ruleAlertId" but we do already have references', () => { + const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0']; + const alert = { + ...getMockData({ + alertTypeId: 'siem.notifications', + params: {}, + }), + references: [ + { + name: 'param:alert_0', + id: '123', + type: 'alert', + }, + ], + }; + + expect(migration7160(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + legacyId: alert.id, + }, + references: [ + { + name: 'param:alert_0', + id: '123', + type: 'alert', + }, + ], + }); + }); + + test('security solution will keep any foreign references if they exist but still migrate other "ruleAlertId" references', () => { + const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0']; + const alert = { + ...getMockData({ + alertTypeId: 'siem.notifications', + params: { + ruleAlertId: '123', + }, + }), + references: [ + { + name: 'foreign-name', + id: '999', + type: 'foreign-name', + }, + ], + }; + + expect(migration7160(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + legacyId: alert.id, + }, + references: [ + { + name: 'foreign-name', + id: '999', + type: 'foreign-name', + }, + { + name: 'param:alert_0', + id: '123', + type: 'alert', + }, + ], + }); + }); + + test('security solution is idempotent and if re-run on the same migrated data will keep the same items "ruleAlertId" references', () => { + const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0']; + const alert = { + ...getMockData({ + alertTypeId: 'siem.notifications', + params: { + ruleAlertId: '123', + }, + }), + references: [ + { + name: 'param:alert_0', + id: '123', + type: 'alert', + }, + ], + }; + + expect(migration7160(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + legacyId: alert.id, + }, + references: [ + { + name: 'param:alert_0', + id: '123', + type: 'alert', + }, + ], + }); + }); + + test('security solution will not migrate "ruleAlertId" if it is invalid data', () => { + const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0']; + const alert = { + ...getMockData({ + alertTypeId: 'siem.notifications', + params: { + ruleAlertId: 55, // This is invalid if it is a number and not a string + }, + }), + }; + + expect(migration7160(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + legacyId: alert.id, + }, + }); + }); + + test('security solution will not migrate "ruleAlertId" if it is invalid data but will keep existing references', () => { + const migration7160 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['7.16.0']; + const alert = { + ...getMockData({ + alertTypeId: 'siem.notifications', + params: { + ruleAlertId: 456, // This is invalid if it is a number and not a string + }, + }), + references: [ + { + name: 'param:alert_0', + id: '123', + type: 'alert', + }, + ], + }; + + expect(migration7160(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + legacyId: alert.id, + }, + references: [ + { + name: 'param:alert_0', + id: '123', + type: 'alert', + }, + ], + }); + }); }); describe('8.0.0', () => { diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.ts index bd795b9efc61f..9dcca54285279 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations.ts @@ -54,6 +54,17 @@ export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc): boolean => doc.attributes.alertTypeId === 'siem.signals'; +/** + * Returns true if the alert type is that of "siem.notifications" which is a legacy notification system that was deprecated in 7.16.0 + * in favor of using the newer alerting notifications system. + * @param doc The saved object alert type document + * @returns true if this is a legacy "siem.notifications" rule, otherwise false + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const isSecuritySolutionLegacyNotification = ( + doc: SavedObjectUnsanitizedDoc +): boolean => doc.attributes.alertTypeId === 'siem.notifications'; + export function getMigrations( encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, isPreconfigured: (connectorId: string) => boolean @@ -103,7 +114,11 @@ export function getMigrations( const migrateRules716 = createEsoMigration( encryptedSavedObjects, (doc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations(setLegacyId, getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured)) + pipeMigrations( + setLegacyId, + getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured), + addRuleIdsToLegacyNotificationReferences + ) ); const migrationRules800 = createEsoMigration( @@ -574,6 +589,49 @@ function removeMalformedExceptionsList( } } +/** + * This migrates rule_id's within the legacy siem.notification to saved object references on an upgrade. + * We only migrate if we find these conditions: + * - ruleAlertId is a string and not null, undefined, or malformed data. + * - The existing references do not already have a ruleAlertId found within it. + * Some of these issues could crop up during either user manual errors of modifying things, earlier migration + * issues, etc... so we are safer to check them as possibilities + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + * @param doc The document that might have "ruleAlertId" to migrate into the references + * @returns The document migrated with saved object references + */ +function addRuleIdsToLegacyNotificationReferences( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { + params: { ruleAlertId }, + }, + references, + } = doc; + if (!isSecuritySolutionLegacyNotification(doc) || !isString(ruleAlertId)) { + // early return if we are not a string or if we are not a security solution notification saved object. + return doc; + } else { + const existingReferences = references ?? []; + const existingReferenceFound = existingReferences.find((reference) => { + return reference.id === ruleAlertId && reference.type === 'alert'; + }); + if (existingReferenceFound) { + // skip this if the references already exists for some uncommon reason so we do not add an additional one. + return doc; + } else { + const savedObjectReference: SavedObjectReference = { + id: ruleAlertId, + name: 'param:alert_0', + type: 'alert', + }; + const newReferences = [...existingReferences, savedObjectReference]; + return { ...doc, references: newReferences }; + } + } +} + function setLegacyId( doc: SavedObjectUnsanitizedDoc ): SavedObjectUnsanitizedDoc { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.ts index 07f571bc7be1b..fa05b1fb5b07a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.ts @@ -6,7 +6,6 @@ */ import { Logger } from 'src/core/server'; -import { schema } from '@kbn/config-schema'; import { parseScheduleDates } from '@kbn/securitysolution-io-ts-utils'; import { DEFAULT_RULE_NOTIFICATION_QUERY_SIZE, @@ -15,12 +14,19 @@ import { } from '../../../../common/constants'; // eslint-disable-next-line no-restricted-imports -import { LegacyNotificationAlertTypeDefinition } from './legacy_types'; +import { + LegacyNotificationAlertTypeDefinition, + legacyRulesNotificationParams, +} from './legacy_types'; import { AlertAttributes } from '../signals/types'; import { siemRuleActionGroups } from '../signals/siem_rule_action_groups'; import { scheduleNotificationActions } from './schedule_notification_actions'; import { getNotificationResultsLink } from './utils'; import { getSignals } from './get_signals'; +// eslint-disable-next-line no-restricted-imports +import { legacyExtractReferences } from './legacy_saved_object_references/legacy_extract_references'; +// eslint-disable-next-line no-restricted-imports +import { legacyInjectReferences } from './legacy_saved_object_references/legacy_inject_references'; /** * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function @@ -36,9 +42,12 @@ export const legacyRulesNotificationAlertType = ({ defaultActionGroupId: 'default', producer: SERVER_APP_ID, validate: { - params: schema.object({ - ruleAlertId: schema.string(), - }), + params: legacyRulesNotificationParams, + }, + useSavedObjectReferences: { + extractReferences: (params) => legacyExtractReferences({ logger, params }), + injectReferences: (params, savedObjectReferences) => + legacyInjectReferences({ logger, params, savedObjectReferences }), }, minimumLicenseRequired: 'basic', isExportable: false, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/README.md b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/README.md new file mode 100644 index 0000000000000..da9ccd30cfdac --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/README.md @@ -0,0 +1,217 @@ +This is where you add code when you have rules which contain saved object references. Saved object references are for +when you have "joins" in the saved objects between one saved object and another one. This can be a 1 to M (1 to many) +relationship for example where you have a rule which contains the "id" of another saved object. + +NOTE: This is the "legacy saved object references" and should only be for the "legacy_rules_notification_alert_type". +The legacy notification system is being phased out and deprecated in favor of using the newer alerting notification system. +It would be considered wrong to see additional code being added here at this point. However, maintenance should be expected +until we have all users moved away from the legacy system. + + +## How to create a legacy notification + +* Create a rule and activate it normally within security_solution +* Do not add actions to the rule at this point as we are exercising the older legacy system. However, you want at least one action configured such as a slack notification. +* Within dev tools do a query for all your actions and grab one of the `_id` of them without their prefix: + +```json +# See all your actions +GET .kibana/_search +{ + "query": { + "term": { + "type": "action" + } + } +} +``` + +Mine was `"_id" : "action:879e8ff0-1be1-11ec-a722-83da1c22a481"`, so I will be copying the ID of `879e8ff0-1be1-11ec-a722-83da1c22a481` + +Go to the file `detection_engine/scripts/legacy_notifications/one_action.json` and add this id to the file. Something like this: + +```json +{ + "name": "Legacy notification with one action", + "interval": "1m", <--- You can use whatever you want. Real values are "1h", "1d", "1w". I use "1m" for testing purposes. + "actions": [ + { + "id": "879e8ff0-1be1-11ec-a722-83da1c22a481", <--- My action id + "group": "default", + "params": { + "message": "Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts" + }, + "actionTypeId": ".slack" <--- I am a slack action id type. + } + ] +} +``` + +Query for an alert you want to add manually add back a legacy notification to it. Such as: + +```json +# See all your siem.signals alert types and choose one +GET .kibana/_search +{ + "query": { + "term": { + "alert.alertTypeId": "siem.signals" + } + } +} +``` + +Grab the `_id` without the alert prefix. For mine this was `933ca720-1be1-11ec-a722-83da1c22a481` + +Within the directory of detection_engine/scripts execute the script: + +```json +./post_legacy_notification.sh 933ca720-1be1-11ec-a722-83da1c22a481 +{ + "ok": "acknowledged" +} +``` + +which is going to do a few things. See the file `detection_engine/routes/rules/legacy_create_legacy_notification.ts` for the definition of the route and what it does in full, but we should notice that we have now: + +Created a legacy side car action object of type `siem-detection-engine-rule-actions` you can see in dev tools: + +```json +# See the actions "side car" which are part of the legacy notification system. +GET .kibana/_search +{ + "query": { + "term": { + "type": { + "value": "siem-detection-engine-rule-actions" + } + } + } +} +``` + +But more importantly what the saved object references are which should be this: + +```json +# Get the alert type of "siem-notifications" which is part of the legacy system. +GET .kibana/_search +{ + "query": { + "term": { + "alert.alertTypeId": "siem.notifications" + } + } +} +``` + +I omit parts but leave the important parts pre-migration and post-migration of the Saved Object. + +```json +"data..omitted": "data..omitted", +"params" : { + "ruleAlertId" : "933ca720-1be1-11ec-a722-83da1c22a481" <-- Pre-migration we had this Saved Object ID which is not part of references array below +}, +"actions" : [ + { + "group" : "default", + "params" : { + "message" : "Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts" + }, + "actionTypeId" : ".slack", + "actionRef" : "action_0" <-- Pre-migration this is correct as this work is already done within the alerting plugin + }, + "references" : [ + { + "id" : "879e8ff0-1be1-11ec-a722-83da1c22a481", + "name" : "action_0", <-- Pre-migration this is correct as this work is already done within the alerting plugin + "type" : "action" + } + ] +], +"data..omitted": "data..omitted", +``` + +Post migration this structure should look like this after Kibana has started and finished the migration. + +```json +"data..omitted": "data..omitted", +"params" : { + "ruleAlertId" : "933ca720-1be1-11ec-a722-83da1c22a481" <-- Post-migration this is not used but rather the serialized version references is used instead. +}, +"actions" : [ + { + "group" : "default", + "params" : { + "message" : "Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts" + }, + "actionTypeId" : ".slack", + "actionRef" : "action_0" + }, + "references" : [ + { + "id" : "879e8ff0-1be1-11ec-a722-83da1c22a481", + "name" : "action_0", + "type" : "action" + }, + { + "id" : "933ca720-1be1-11ec-a722-83da1c22a481", <-- Our id here is preferred and used during serialization. + "name" : "param:alert_0", <-- We add the name of our reference which is param:alert_0 similar to action_0 but with "param" + "type" : "alert" <-- We add the type which is type of rule to the references + } + ] +], +"data..omitted": "data..omitted", +``` + +Only if for some reason a migration has failed due to a bug would we fallback and try to use `"ruleAlertId" : "933ca720-1be1-11ec-a722-83da1c22a481"`, as it was last stored within SavedObjects. Otherwise all access will come from the +references array's version. If the migration fails or the fallback to the last known saved object id `"ruleAlertId" : "933ca720-1be1-11ec-a722-83da1c22a481"` does happen, then the code emits several error messages to the +user which should further encourage the user to help migrate the legacy notification system to the newer notification system. + +## Useful queries + +This gives you back the legacy notifications. + +```json +# Get the alert type of "siem-notifications" which is part of the legacy system. +GET .kibana/_search +{ + "query": { + "term": { + "alert.alertTypeId": "siem.notifications" + } + } +} +``` + +If you need to ad-hoc test what happens when the migration runs you can get the id of an alert and downgrade it, then +restart Kibana. The `ctx._source.references.remove(1)` removes the last element of the references array which is assumed +to have a rule. But it might not, so ensure you check your data structure and adjust accordingly. +```json +POST .kibana/_update/alert:933ca720-1be1-11ec-a722-83da1c22a481 +{ + "script" : { + "source": """ + ctx._source.migrationVersion.alert = "7.15.0"; + ctx._source.references.remove(1); + """, + "lang": "painless" + } +} +``` + +If you just want to remove your "param:alert_0" and it is the second array element to test the errors within the console +then you would use +```json +POST .kibana/_update/alert:933ca720-1be1-11ec-a722-83da1c22a481 +{ + "script" : { + "source": """ + ctx._source.references.remove(1); + """, + "lang": "painless" + } +} +``` + +## End to end tests +See `test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts` for tests around migrations diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_references.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_references.test.ts new file mode 100644 index 0000000000000..231451947a1dd --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_references.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { loggingSystemMock } from 'src/core/server/mocks'; +// eslint-disable-next-line no-restricted-imports +import { LegacyRulesNotificationParams } from '../legacy_types'; +// eslint-disable-next-line no-restricted-imports +import { legacyExtractReferences } from './legacy_extract_references'; + +describe('legacy_extract_references', () => { + type FuncReturn = ReturnType; + let logger = loggingSystemMock.create().get('security_solution'); + + beforeEach(() => { + logger = loggingSystemMock.create().get('security_solution'); + }); + + test('It returns the references extracted as saved object references', () => { + const params: LegacyRulesNotificationParams = { + ruleAlertId: '123', + }; + expect( + legacyExtractReferences({ + logger, + params, + }) + ).toEqual({ + params, + references: [ + { + id: '123', + name: 'alert_0', + type: 'alert', + }, + ], + }); + }); + + test('It returns the empty references array if the ruleAlertId is missing for any particular unusual reason', () => { + const params = {}; + expect( + legacyExtractReferences({ + logger, + params: params as LegacyRulesNotificationParams, + }) + ).toEqual({ + params: params as LegacyRulesNotificationParams, + references: [], + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_references.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_references.ts new file mode 100644 index 0000000000000..1461b78ba73a6 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_references.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Logger } from 'src/core/server'; +import { RuleParamsAndRefs } from '../../../../../../alerting/server'; +// eslint-disable-next-line no-restricted-imports +import { LegacyRulesNotificationParams } from '../legacy_types'; +// eslint-disable-next-line no-restricted-imports +import { legacyExtractRuleId } from './legacy_extract_rule_id'; + +/** + * Extracts references and returns the saved object references. + * NOTE: You should not have to add any new ones here at all, but this keeps consistency with the other + * version(s) used for security_solution rules. + * + * How to add a new extracted references here (This should be rare or non-existent): + * --- + * Add a new file for extraction named: extract_.ts, example: extract_foo.ts + * Add a function into that file named: extract, example: extractFoo(logger, params.foo) + * Add a new line below and concat together the new extract with existing ones like so: + * + * const legacyRuleIdReferences = legacyExtractRuleId(logger, params.ruleAlertId); + * const fooReferences = extractFoo(logger, params.foo); + * const returnReferences = [...legacyRuleIdReferences, ...fooReferences]; + * + * Optionally you can remove any parameters you do not want to store within the Saved Object here: + * const paramsWithoutSavedObjectReferences = { removeParam, ...otherParams }; + * + * If you do remove params, then update the types in: security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.ts + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + * @param logger Kibana injected logger + * @param params The params of the base rule(s). + * @returns The rule parameters and the saved object references to store. + */ +export const legacyExtractReferences = ({ + logger, + params, +}: { + logger: Logger; + params: LegacyRulesNotificationParams; +}): RuleParamsAndRefs => { + const legacyRuleIdReferences = legacyExtractRuleId({ + logger, + ruleAlertId: params.ruleAlertId, + }); + const returnReferences = [...legacyRuleIdReferences]; + + // Modify params if you want to remove any elements separately here. For legacy ruleAlertId, we do not remove the id and instead + // keep it to both fail safe guard against manually removed saved object references or if there are migration issues and the saved object + // references are removed. Also keeping it we can detect and log out a warning if the reference between it and the saved_object reference + // array have changed between each other indicating the saved_object array is being mutated outside of this functionality + const paramsWithoutSavedObjectReferences = { ...params }; + + return { + references: returnReferences, + params: paramsWithoutSavedObjectReferences, + }; +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_rule_id.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_rule_id.test.ts new file mode 100644 index 0000000000000..476a72461e8a0 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_rule_id.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { loggingSystemMock } from 'src/core/server/mocks'; +// eslint-disable-next-line no-restricted-imports +import { LegacyRulesNotificationParams } from '../legacy_types'; +// eslint-disable-next-line no-restricted-imports +import { legacyExtractRuleId } from './legacy_extract_rule_id'; + +describe('legacy_extract_rule_id', () => { + type FuncReturn = ReturnType; + let logger = loggingSystemMock.create().get('security_solution'); + + beforeEach(() => { + logger = loggingSystemMock.create().get('security_solution'); + }); + + test('it returns an empty array given a "undefined" ruleAlertId.', () => { + expect( + legacyExtractRuleId({ + logger, + ruleAlertId: undefined as unknown as LegacyRulesNotificationParams['ruleAlertId'], + }) + ).toEqual([]); + }); + + test('logs expect error message if given a "undefined" ruleAlertId.', () => { + expect( + legacyExtractRuleId({ + logger, + ruleAlertId: null as unknown as LegacyRulesNotificationParams['ruleAlertId'], + }) + ).toEqual([]); + + expect(logger.error).toBeCalledWith( + 'Security Solution notification (Legacy) system "ruleAlertId" is null or undefined when it never should be. ,This indicates potentially that saved object migrations did not run correctly. Returning empty reference' + ); + }); + + test('it returns the "ruleAlertId" transformed into a saved object references array.', () => { + expect( + legacyExtractRuleId({ + logger, + ruleAlertId: '123', + }) + ).toEqual([ + { + id: '123', + name: 'alert_0', + type: 'alert', + }, + ]); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_rule_id.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_rule_id.ts new file mode 100644 index 0000000000000..bc43fd59e68ee --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_extract_rule_id.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Logger, SavedObjectReference } from 'src/core/server'; +// eslint-disable-next-line no-restricted-imports +import { LegacyRulesNotificationParams } from '../legacy_types'; + +/** + * This extracts the "ruleAlertId" "id" and returns it as a saved object reference. + * NOTE: Due to rolling upgrades with migrations and a few bugs with migrations, I do an additional check for if "ruleAlertId" exists or not. Once + * those bugs are fixed, we can remove the "if (ruleAlertId == null) {" check, but for the time being it is there to keep things running even + * if ruleAlertId has not been migrated. + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + * @param logger The kibana injected logger + * @param ruleAlertId The rule alert id to get the id from and return it as a saved object reference. + * @returns The saved object references from the rule alert id + */ +export const legacyExtractRuleId = ({ + logger, + ruleAlertId, +}: { + logger: Logger; + ruleAlertId: LegacyRulesNotificationParams['ruleAlertId']; +}): SavedObjectReference[] => { + if (ruleAlertId == null) { + logger.error( + [ + 'Security Solution notification (Legacy) system "ruleAlertId" is null or undefined when it never should be. ', + 'This indicates potentially that saved object migrations did not run correctly. Returning empty reference', + ].join() + ); + return []; + } else { + return [ + { + id: ruleAlertId, + name: 'alert_0', + type: 'alert', + }, + ]; + } +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_references.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_references.test.ts new file mode 100644 index 0000000000000..ae34479e73534 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_references.test.ts @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { loggingSystemMock } from 'src/core/server/mocks'; +import { SavedObjectReference } from 'src/core/server'; + +// eslint-disable-next-line no-restricted-imports +import { LegacyRulesNotificationParams } from '../legacy_types'; +// eslint-disable-next-line no-restricted-imports +import { legacyInjectReferences } from './legacy_inject_references'; + +describe('legacy_inject_references', () => { + type FuncReturn = ReturnType; + let logger = loggingSystemMock.create().get('security_solution'); + const mockSavedObjectReferences = (): SavedObjectReference[] => [ + { + id: '123', + name: 'alert_0', + type: 'alert', + }, + ]; + + beforeEach(() => { + logger = loggingSystemMock.create().get('security_solution'); + }); + + test('returns parameters from a saved object if found', () => { + const params: LegacyRulesNotificationParams = { + ruleAlertId: '123', + }; + + expect( + legacyInjectReferences({ + logger, + params, + savedObjectReferences: mockSavedObjectReferences(), + }) + ).toEqual(params); + }); + + test('returns parameters from the saved object if found with a different saved object reference id', () => { + const params: LegacyRulesNotificationParams = { + ruleAlertId: '123', + }; + + expect( + legacyInjectReferences({ + logger, + params, + savedObjectReferences: [{ ...mockSavedObjectReferences()[0], id: '456' }], + }) + ).toEqual({ + ruleAlertId: '456', + }); + }); + + test('It returns params with an added ruleAlertId if the ruleAlertId is missing due to migration bugs', () => { + const params = {} as LegacyRulesNotificationParams; + + expect( + legacyInjectReferences({ + logger, + params, + savedObjectReferences: [{ ...mockSavedObjectReferences()[0], id: '456' }], + }) + ).toEqual({ + ruleAlertId: '456', + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_references.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_references.ts new file mode 100644 index 0000000000000..5a7118d64ba3a --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_references.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Logger, SavedObjectReference } from 'src/core/server'; +// eslint-disable-next-line no-restricted-imports +import { LegacyRulesNotificationParams } from '../legacy_types'; +// eslint-disable-next-line no-restricted-imports +import { legacyInjectRuleIdReferences } from './legacy_inject_rule_id_references'; + +/** + * Injects references and returns the saved object references. + * How to add a new injected references here (NOTE: We do not expect to add more here but we leave this as the same pattern we have in other reference sections): + * --- + * Add a new file for injection named: legacy_inject_.ts, example: legacy_inject_foo.ts + * Add a new function into that file named: legacy_inject, example: legacyInjectFooReferences(logger, params.foo) + * Add a new line below and spread the new parameter together like so: + * + * const foo = legacyInjectFooReferences(logger, params.foo, savedObjectReferences); + * const ruleParamsWithSavedObjectReferences: RuleParams = { + * ...params, + * foo, + * ruleAlertId, + * }; + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + * @param logger Kibana injected logger + * @param params The params of the base rule(s). + * @param savedObjectReferences The saved object references to merge with the rule params + * @returns The rule parameters with the saved object references. + */ +export const legacyInjectReferences = ({ + logger, + params, + savedObjectReferences, +}: { + logger: Logger; + params: LegacyRulesNotificationParams; + savedObjectReferences: SavedObjectReference[]; +}): LegacyRulesNotificationParams => { + const ruleAlertId = legacyInjectRuleIdReferences({ + logger, + ruleAlertId: params.ruleAlertId, + savedObjectReferences, + }); + const ruleParamsWithSavedObjectReferences: LegacyRulesNotificationParams = { + ...params, + ruleAlertId, + }; + return ruleParamsWithSavedObjectReferences; +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.test.ts new file mode 100644 index 0000000000000..2f63a184875f1 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.test.ts @@ -0,0 +1,101 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { loggingSystemMock } from 'src/core/server/mocks'; +import { SavedObjectReference } from 'src/core/server'; + +// eslint-disable-next-line no-restricted-imports +import { legacyInjectRuleIdReferences } from './legacy_inject_rule_id_references'; +// eslint-disable-next-line no-restricted-imports +import { LegacyRulesNotificationParams } from '../legacy_types'; + +describe('legacy_inject_rule_id_references', () => { + type FuncReturn = ReturnType; + let logger = loggingSystemMock.create().get('security_solution'); + const mockSavedObjectReferences = (): SavedObjectReference[] => [ + { + id: '123', + name: 'alert_0', + type: 'alert', + }, + ]; + + beforeEach(() => { + logger = loggingSystemMock.create().get('security_solution'); + }); + + test('returns parameters from the saved object if found', () => { + expect( + legacyInjectRuleIdReferences({ + logger, + ruleAlertId: '123', + savedObjectReferences: mockSavedObjectReferences(), + }) + ).toEqual('123'); + }); + + test('returns parameters from the saved object if "ruleAlertId" is undefined', () => { + expect( + legacyInjectRuleIdReferences({ + logger, + ruleAlertId: undefined as unknown as LegacyRulesNotificationParams['ruleAlertId'], + savedObjectReferences: mockSavedObjectReferences(), + }) + ).toEqual('123'); + }); + + test('prefers to use saved object references if the two are different from each other', () => { + expect( + legacyInjectRuleIdReferences({ + logger, + ruleAlertId: '456', + savedObjectReferences: mockSavedObjectReferences(), + }) + ).toEqual('123'); + }); + + test('returns sent in "ruleAlertId" if the saved object references is empty', () => { + expect( + legacyInjectRuleIdReferences({ + logger, + ruleAlertId: '456', + savedObjectReferences: [], + }) + ).toEqual('456'); + }); + + test('does not log an error if it returns parameters from the saved object when found', () => { + legacyInjectRuleIdReferences({ + logger, + ruleAlertId: '123', + savedObjectReferences: mockSavedObjectReferences(), + }); + expect(logger.error).not.toHaveBeenCalled(); + }); + + test('logs an error if found with a different saved object reference id', () => { + legacyInjectRuleIdReferences({ + logger, + ruleAlertId: '456', + savedObjectReferences: mockSavedObjectReferences(), + }); + expect(logger.error).toBeCalledWith( + 'The id of the "saved object reference id": 123 is not the same as the "saved object id": 456. Preferring and using the "saved object reference id" instead of the "saved object id"' + ); + }); + + test('logs an error if the saved object references is empty', () => { + legacyInjectRuleIdReferences({ + logger, + ruleAlertId: '123', + savedObjectReferences: [], + }); + expect(logger.error).toBeCalledWith( + 'The saved object reference was not found for the "ruleAlertId" when we were expecting to find it. Kibana migrations might not have run correctly or someone might have removed the saved object references manually. Returning the last known good "ruleAlertId" which might not work. "ruleAlertId" with its id being returned is: 123' + ); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.ts new file mode 100644 index 0000000000000..5cb32c6563157 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Logger, SavedObjectReference } from 'src/core/server'; +// eslint-disable-next-line no-restricted-imports +import { LegacyRulesNotificationParams } from '../legacy_types'; + +/** + * This injects any legacy "id"'s from saved object reference and returns the "ruleAlertId" using the saved object reference. If for + * some reason it is missing on saved object reference, we log an error about it and then take the last known good value from the "ruleId" + * + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + * @param logger The kibana injected logger + * @param ruleAlertId The alert id to merge the saved object reference from. + * @param savedObjectReferences The saved object references which should contain a "ruleAlertId" + * @returns The "ruleAlertId" with the saved object reference replacing any value in the saved object's id. + */ +export const legacyInjectRuleIdReferences = ({ + logger, + ruleAlertId, + savedObjectReferences, +}: { + logger: Logger; + ruleAlertId: LegacyRulesNotificationParams['ruleAlertId']; + savedObjectReferences: SavedObjectReference[]; +}): LegacyRulesNotificationParams['ruleAlertId'] => { + const referenceFound = savedObjectReferences.find((reference) => { + return reference.name === 'alert_0'; + }); + if (referenceFound) { + if (referenceFound.id !== ruleAlertId) { + // This condition should not be reached but we log an error if we encounter it to help if we migrations + // did not run correctly or we create a regression in the future. + logger.error( + [ + 'The id of the "saved object reference id": ', + referenceFound.id, + ' is not the same as the "saved object id": ', + ruleAlertId, + '. Preferring and using the "saved object reference id" instead of the "saved object id"', + ].join('') + ); + } + return referenceFound.id; + } else { + logger.error( + [ + 'The saved object reference was not found for the "ruleAlertId" when we were expecting to find it. ', + 'Kibana migrations might not have run correctly or someone might have removed the saved object references manually. ', + 'Returning the last known good "ruleAlertId" which might not work. "ruleAlertId" with its id being returned is: ', + ruleAlertId, + ].join('') + ); + return ruleAlertId; + } +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_types.ts index 2a52f14379845..28fa62f28ed2e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_types.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { schema, TypeOf } from '@kbn/config-schema'; + import { RulesClient, PartialAlert, @@ -102,8 +104,8 @@ export type LegacyNotificationExecutorOptions = AlertExecutorOptions< export const legacyIsNotificationAlertExecutor = ( obj: LegacyNotificationAlertTypeDefinition ): obj is AlertType< - AlertTypeParams, - AlertTypeParams, + LegacyRuleNotificationAlertTypeParams, + LegacyRuleNotificationAlertTypeParams, AlertTypeState, AlertInstanceState, AlertInstanceContext @@ -116,8 +118,8 @@ export const legacyIsNotificationAlertExecutor = ( */ export type LegacyNotificationAlertTypeDefinition = Omit< AlertType< - AlertTypeParams, - AlertTypeParams, + LegacyRuleNotificationAlertTypeParams, + LegacyRuleNotificationAlertTypeParams, AlertTypeState, AlertInstanceState, AlertInstanceContext, @@ -131,3 +133,19 @@ export type LegacyNotificationAlertTypeDefinition = Omit< state, }: LegacyNotificationExecutorOptions) => Promise; }; + +/** + * This is the notification type used within legacy_rules_notification_alert_type for the alert params. + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + * @see legacy_rules_notification_alert_type + */ +export const legacyRulesNotificationParams = schema.object({ + ruleAlertId: schema.string(), +}); + +/** + * This legacy rules notification type used within legacy_rules_notification_alert_type for the alert params. + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + * @see legacy_rules_notification_alert_type + */ +export type LegacyRulesNotificationParams = TypeOf; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/scripts/legacy_notifications/one_action.json b/x-pack/plugins/security_solution/server/lib/detection_engine/scripts/legacy_notifications/one_action.json index b1500ac6fa6b7..1966dcf5ff53c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/scripts/legacy_notifications/one_action.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/scripts/legacy_notifications/one_action.json @@ -3,7 +3,7 @@ "interval": "1m", "actions": [ { - "id": "879e8ff0-1be1-11ec-a722-83da1c22a481", + "id": "42534430-2092-11ec-99a6-05d79563c01a", "group": "default", "params": { "message": "Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/README.md b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/README.md index 893797afa44d7..c76a69db084ca 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/README.md +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/README.md @@ -21,6 +21,26 @@ GET .kibana/_search } ``` +If you want to manually test the downgrade of an alert then you can use this script. +```json +# Set saved object array references as empty arrays and set our migration version to be 7.14.0 +POST .kibana/_update/alert:38482620-ef1b-11eb-ad71-7de7959be71c +{ + "script" : { + "source": """ + ctx._source.migrationVersion.alert = "7.14.0"; + ctx._source.references = [] + """, + "lang": "painless" + } +} +``` + +Reload the alert in the security_solution and notice you get these errors until you restart Kibana to cause a migration moving forward. Although you get errors, +everything should still operate normally as we try to work even if migrations did not run correctly for any unforeseen reasons. + +For testing idempotentence, just re-run the same script above for a downgrade after you restarted Kibana. + ## Structure on disk Run a query in dev tools and you should see this code that adds the following savedObject references to any newly saved rule: @@ -141,4 +161,4 @@ Good examples and utilities can be found in the folder of `utils` such as: You can follow those patterns but if it doesn't fit your use case it's fine to just create a new file and wire up your new saved object references ## End to end tests -At this moment there are none. \ No newline at end of file +See `test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts` for tests around migrations diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts index c98fe9c7d67f2..e3a062a08ffb9 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts @@ -257,5 +257,21 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, ]); }); + + it('7.16.0 migrates security_solution (Legacy) siem.notifications with "ruleAlertId" to be saved object references', async () => { + // NOTE: We hae to use elastic search directly against the ".kibana" index because alerts do not expose the references which we want to test exists + const response = await es.get<{ references: [{}] }>({ + index: '.kibana', + id: 'alert:d7a8c6a1-9394-48df-a634-d5457c35d747', + }); + expect(response.statusCode).to.eql(200); + expect(response.body._source?.references).to.eql([ + { + name: 'param:alert_0', + id: '1a4ed6ae-3c89-44b2-999d-db554144504c', + type: 'alert', + }, + ]); + }); }); } diff --git a/x-pack/test/functional/es_archives/alerts/data.json b/x-pack/test/functional/es_archives/alerts/data.json index 1685d909eee81..880a81a8fc209 100644 --- a/x-pack/test/functional/es_archives/alerts/data.json +++ b/x-pack/test/functional/es_archives/alerts/data.json @@ -451,4 +451,44 @@ "updated_at": "2020-06-17T15:35:39.839Z" } } -} \ No newline at end of file +} + +{ + "type": "doc", + "value": { + "id": "alert:d7a8c6a1-9394-48df-a634-d5457c35d747", + "index": ".kibana_1", + "source": { + "alert" : { + "name" : "test upgrade of ruleAlertId", + "alertTypeId" : "siem.notifications", + "consumer" : "alertsFixture", + "params" : { + "ruleAlertId" : "1a4ed6ae-3c89-44b2-999d-db554144504c" + }, + "schedule" : { + "interval" : "1m" + }, + "enabled" : true, + "actions" : [ ], + "throttle" : null, + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "elastic", + "updatedBy" : "elastic", + "createdAt" : "2021-07-27T20:42:55.896Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "scheduledTaskId" : null, + "tags": [] + }, + "type" : "alert", + "migrationVersion" : { + "alert" : "7.8.0" + }, + "updated_at" : "2021-08-13T23:00:11.985Z", + "references": [ + ] + } + } +} From 28702ff1c6a0c1c61b6395cab9c188de7a61d9fb Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Mon, 4 Oct 2021 19:00:41 +0200 Subject: [PATCH 52/98] [test/page_objects] validate selected dates for timepicker (#113597) * [test/page_objects] validate selected dates for timepicker * unskip flaky test * fix types check failure * update tests * update message * unskip more tests --- .../apps/discover/_discover_histogram.ts | 12 +++--- test/functional/page_objects/time_picker.ts | 41 +++++++++++++------ .../feature_controls/discover_spaces.ts | 3 +- .../apps/discover/saved_searches.ts | 3 +- .../apps/lens/persistent_context.ts | 4 +- 5 files changed, 38 insertions(+), 25 deletions(-) diff --git a/test/functional/apps/discover/_discover_histogram.ts b/test/functional/apps/discover/_discover_histogram.ts index de12cde84edc5..36abcd81d53a0 100644 --- a/test/functional/apps/discover/_discover_histogram.ts +++ b/test/functional/apps/discover/_discover_histogram.ts @@ -52,21 +52,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { } it('should visualize monthly data with different day intervals', async () => { - const fromTime = 'Nov 01, 2017 @ 00:00:00.000'; + const fromTime = 'Nov 1, 2017 @ 00:00:00.000'; const toTime = 'Mar 21, 2018 @ 00:00:00.000'; await prepareTest(fromTime, toTime, 'Month'); const chartCanvasExist = await elasticChart.canvasExists(); expect(chartCanvasExist).to.be(true); }); it('should visualize weekly data with within DST changes', async () => { - const fromTime = 'Mar 01, 2018 @ 00:00:00.000'; - const toTime = 'May 01, 2018 @ 00:00:00.000'; + const fromTime = 'Mar 1, 2018 @ 00:00:00.000'; + const toTime = 'May 1, 2018 @ 00:00:00.000'; await prepareTest(fromTime, toTime, 'Week'); const chartCanvasExist = await elasticChart.canvasExists(); expect(chartCanvasExist).to.be(true); }); it('should visualize monthly data with different years scaled to 30 days', async () => { - const fromTime = 'Jan 01, 2010 @ 00:00:00.000'; + const fromTime = 'Jan 1, 2010 @ 00:00:00.000'; const toTime = 'Mar 21, 2019 @ 00:00:00.000'; await prepareTest(fromTime, toTime, 'Day'); const chartCanvasExist = await elasticChart.canvasExists(); @@ -75,7 +75,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(chartIntervalIconTip).to.be(true); }); it('should allow hide/show histogram, persisted in url state', async () => { - const fromTime = 'Jan 01, 2010 @ 00:00:00.000'; + const fromTime = 'Jan 1, 2010 @ 00:00:00.000'; const toTime = 'Mar 21, 2019 @ 00:00:00.000'; await prepareTest(fromTime, toTime); let canvasExists = await elasticChart.canvasExists(); @@ -95,7 +95,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(canvasExists).to.be(true); }); it('should allow hiding the histogram, persisted in saved search', async () => { - const fromTime = 'Jan 01, 2010 @ 00:00:00.000'; + const fromTime = 'Jan 1, 2010 @ 00:00:00.000'; const toTime = 'Mar 21, 2019 @ 00:00:00.000'; const savedSearch = 'persisted hidden histogram'; await prepareTest(fromTime, toTime); diff --git a/test/functional/page_objects/time_picker.ts b/test/functional/page_objects/time_picker.ts index 00133d720d884..6cc4fda513ea6 100644 --- a/test/functional/page_objects/time_picker.ts +++ b/test/functional/page_objects/time_picker.ts @@ -116,23 +116,38 @@ export class TimePickerPageObject extends FtrService { public async setAbsoluteRange(fromTime: string, toTime: string) { this.log.debug(`Setting absolute range to ${fromTime} to ${toTime}`); await this.showStartEndTimes(); + let panel!: WebElementWrapper; // set to time - await this.testSubjects.click('superDatePickerendDatePopoverButton'); - let panel = await this.getTimePickerPanel(); - await this.testSubjects.click('superDatePickerAbsoluteTab'); - await this.testSubjects.click('superDatePickerAbsoluteDateInput'); - await this.inputValue('superDatePickerAbsoluteDateInput', toTime); - await this.browser.pressKeys(this.browser.keys.ESCAPE); // close popover because sometimes browser can't find start input + await this.retry.waitFor(`endDate is set to ${toTime}`, async () => { + await this.testSubjects.click('superDatePickerendDatePopoverButton'); + panel = await this.getTimePickerPanel(); + await this.testSubjects.click('superDatePickerAbsoluteTab'); + await this.testSubjects.click('superDatePickerAbsoluteDateInput'); + await this.inputValue('superDatePickerAbsoluteDateInput', toTime); + await this.browser.pressKeys(this.browser.keys.ESCAPE); // close popover because sometimes browser can't find start input + const actualToTime = await this.testSubjects.getVisibleText( + 'superDatePickerendDatePopoverButton' + ); + this.log.debug(`Validating 'endDate' - expected: '${toTime}, actual: ${actualToTime}'`); + return toTime === actualToTime; + }); // set from time - await this.testSubjects.click('superDatePickerstartDatePopoverButton'); - await this.waitPanelIsGone(panel); - panel = await this.getTimePickerPanel(); - await this.testSubjects.click('superDatePickerAbsoluteTab'); - await this.testSubjects.click('superDatePickerAbsoluteDateInput'); - await this.inputValue('superDatePickerAbsoluteDateInput', fromTime); - await this.browser.pressKeys(this.browser.keys.ESCAPE); + await this.retry.waitFor(`endDate is set to ${fromTime}`, async () => { + await this.testSubjects.click('superDatePickerstartDatePopoverButton'); + await this.waitPanelIsGone(panel); + panel = await this.getTimePickerPanel(); + await this.testSubjects.click('superDatePickerAbsoluteTab'); + await this.testSubjects.click('superDatePickerAbsoluteDateInput'); + await this.inputValue('superDatePickerAbsoluteDateInput', fromTime); + await this.browser.pressKeys(this.browser.keys.ESCAPE); + const actualFromTime = await this.testSubjects.getVisibleText( + 'superDatePickerstartDatePopoverButton' + ); + this.log.debug(`Validating 'startDate' - expected: '${fromTime}, actual: ${actualFromTime}'`); + return fromTime === actualFromTime; + }); await this.retry.waitFor('Timepicker popover to close', async () => { return !(await this.testSubjects.exists('superDatePickerAbsoluteDateInput')); diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts index 0cf4ecefe8dbd..c245b45917497 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts @@ -28,8 +28,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.timePicker.setDefaultAbsoluteRange(); } - // FLAKY https://github.com/elastic/kibana/issues/113067 - describe.skip('spaces', () => { + describe('spaces', () => { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); }); diff --git a/x-pack/test/functional/apps/discover/saved_searches.ts b/x-pack/test/functional/apps/discover/saved_searches.ts index ec649935adec2..1d8de9fe9fb6d 100644 --- a/x-pack/test/functional/apps/discover/saved_searches.ts +++ b/x-pack/test/functional/apps/discover/saved_searches.ts @@ -18,8 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const panelActionsTimeRange = getService('dashboardPanelTimeRange'); const ecommerceSOPath = 'x-pack/test/functional/fixtures/kbn_archiver/reporting/ecommerce.json'; - // FLAKY https://github.com/elastic/kibana/issues/104578 - describe.skip('Discover Saved Searches', () => { + describe('Discover Saved Searches', () => { before('initialize tests', async () => { await esArchiver.load('x-pack/test/functional/es_archives/reporting/ecommerce'); await kibanaServer.importExport.load(ecommerceSOPath); diff --git a/x-pack/test/functional/apps/lens/persistent_context.ts b/x-pack/test/functional/apps/lens/persistent_context.ts index 90a7b9fe83c12..e7b99ad804cd0 100644 --- a/x-pack/test/functional/apps/lens/persistent_context.ts +++ b/x-pack/test/functional/apps/lens/persistent_context.ts @@ -31,7 +31,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickVisType('lens'); await PageObjects.lens.goToTimeRange( - 'Sep 06, 2015 @ 06:31:44.000', + 'Sep 6, 2015 @ 06:31:44.000', 'Sep 18, 2025 @ 06:31:44.000' ); await filterBar.addFilter('ip', 'is', '97.220.3.248'); @@ -45,7 +45,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should remember time range and pinned filters from discover', async () => { await PageObjects.lens.goToTimeRange( - 'Sep 07, 2015 @ 06:31:44.000', + 'Sep 7, 2015 @ 06:31:44.000', 'Sep 19, 2025 @ 06:31:44.000' ); await filterBar.toggleFilterEnabled('ip'); From bbb2e96dd5d0683628be7c4ad3fede2fa462acd8 Mon Sep 17 00:00:00 2001 From: Matthew Kime Date: Mon, 4 Oct 2021 12:05:22 -0500 Subject: [PATCH 53/98] [data views] Move data views api from data plugin and into its own (#113497) * initial pass at moving data views into own plugin * require expressions plugin, fix META_FIELDS reference * bundle limits and localization * fix integration test * update plugin list and jest config * type fixes * search fixes * fix localization * fix mocks * fix mocks * fix stub * type fixes * fix import on test file * path fixes * remove shorted dotted from data plugin * more todo removal * eslint fixes * eslint fix * simplify data views server plugin * simplify data views server plugin * simplify data views server plugin * fix imports on api routes * fix imports on api routes * update plugin list * ts fixes * ts fixes * add deprecation notice * fix circular dependency and api integration test * fix circular dependency and api integration test * rename types for better clarity * path fixes * jest.config and tsconfig cleanup Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + .i18nrc.json | 1 + docs/developer/plugin-list.asciidoc | 6 + packages/kbn-optimizer/limits.yml | 1 + src/plugins/data/README.mdx | 9 -- src/plugins/data/common/constants.ts | 9 -- src/plugins/data/common/data_views/index.ts | 21 ---- src/plugins/data/common/index.ts | 70 ++++++++++-- src/plugins/data/common/mocks.ts | 2 +- .../common/search/aggs/param_types/field.ts | 2 +- .../search/expressions/esaggs/esaggs_fn.ts | 2 +- .../search_source/extract_references.ts | 6 +- src/plugins/data/common/stubs.ts | 4 +- src/plugins/data/common/types.ts | 1 - src/plugins/data/kibana.json | 4 +- src/plugins/data/public/data_views/index.ts | 23 +--- src/plugins/data/public/index.ts | 4 +- src/plugins/data/public/plugin.ts | 40 ++----- src/plugins/data/public/stubs.ts | 3 +- src/plugins/data/public/types.ts | 2 + src/plugins/data/server/data_views/index.ts | 10 +- .../data_views/index_patterns_service.ts | 108 ------------------ src/plugins/data/server/data_views/mocks.ts | 6 +- src/plugins/data/server/index.ts | 2 +- src/plugins/data/server/plugin.ts | 22 +--- .../data/server/saved_objects/index.ts | 1 - src/plugins/data/tsconfig.json | 3 +- src/plugins/data_views/README.mdx | 19 +++ .../common}/constants.ts | 11 ++ .../common}/data_view.stub.ts | 4 +- .../__snapshots__/data_view.test.ts.snap | 0 .../__snapshots__/data_views.test.ts.snap | 0 .../common}/data_views/_pattern_cache.ts | 0 .../common}/data_views/data_view.stub.ts | 4 +- .../common}/data_views/data_view.test.ts | 6 +- .../common}/data_views/data_view.ts | 12 +- .../common}/data_views/data_views.test.ts | 2 +- .../common}/data_views/data_views.ts | 22 ++-- .../data_views/ensure_default_data_view.ts | 0 .../common}/data_views/flatten_hit.test.ts | 2 +- .../common}/data_views/flatten_hit.ts | 0 .../common}/data_views/format_hit.ts | 2 +- .../common}/data_views/index.ts | 0 .../errors/data_view_saved_object_conflict.ts | 0 .../common}/errors/duplicate_index_pattern.ts | 0 .../common}/errors/index.ts | 0 .../common}/expressions/index.ts | 0 .../common}/expressions/load_index_pattern.ts | 6 +- .../common}/field.stub.ts | 0 .../data_view_field.test.ts.snap | 0 .../common}/fields/data_view_field.test.ts | 4 +- .../common}/fields/data_view_field.ts | 6 +- .../common}/fields/field_list.ts | 0 .../common}/fields/fields.mocks.ts | 0 .../common}/fields/index.ts | 0 .../common}/fields/types.ts | 2 +- .../common/fields/utils.test.ts} | 2 +- .../common}/fields/utils.ts | 12 ++ src/plugins/data_views/common/index.ts | 62 ++++++++++ .../common}/lib/errors.ts | 2 +- .../common}/lib/get_title.ts | 4 +- .../common}/lib/index.ts | 0 .../common}/lib/types.ts | 0 .../common}/lib/validate_data_view.test.ts | 0 .../common}/lib/validate_data_view.ts | 0 .../data_views => data_views/common}/mocks.ts | 0 src/plugins/data_views/common/stubs.ts | 10 ++ .../data_views => data_views/common}/types.ts | 7 +- .../common}/utils.test.ts | 0 .../data_views => data_views/common}/utils.ts | 4 +- src/plugins/data_views/jest.config.js | 16 +++ src/plugins/data_views/kibana.json | 15 +++ .../public}/data_views/data_view.stub.ts | 10 +- .../data_views_api_client.test.mock.ts | 2 +- .../data_views/data_views_api_client.test.ts | 0 .../data_views/data_views_api_client.ts | 8 +- .../public}/data_views/index.ts | 2 +- .../data_views/redirect_no_index_pattern.tsx | 13 +-- .../public}/expressions/index.ts | 0 .../expressions/load_index_pattern.test.ts | 2 +- .../public}/expressions/load_index_pattern.ts | 11 +- src/plugins/data_views/public/index.ts | 45 ++++++++ src/plugins/data_views/public/plugin.ts | 68 +++++++++++ .../saved_objects_client_wrapper.test.ts | 2 +- .../public}/saved_objects_client_wrapper.ts | 2 +- src/plugins/data_views/public/types.ts | 32 ++++++ .../public}/ui_settings_wrapper.ts | 2 +- .../server}/capabilities_provider.ts | 0 .../server/data_views_service_factory.ts | 50 ++++++++ .../server}/deprecations/index.ts | 0 .../deprecations/scripted_fields.test.ts | 0 .../server}/deprecations/scripted_fields.ts | 10 +- .../data_views => data_views/server}/error.ts | 0 .../server}/expressions/index.ts | 0 .../expressions/load_index_pattern.test.ts | 2 +- .../server}/expressions/load_index_pattern.ts | 16 ++- .../server}/fetcher/index.ts | 0 .../fetcher/index_not_found_exception.json | 21 ++++ .../fetcher/index_patterns_fetcher.test.ts | 2 +- .../server}/fetcher/index_patterns_fetcher.ts | 0 .../server}/fetcher/lib/errors.ts | 0 .../server}/fetcher/lib/es_api.test.js | 0 .../server}/fetcher/lib/es_api.ts | 0 .../__fixtures__/es_field_caps_response.json | 0 .../field_capabilities.test.js | 0 .../field_capabilities/field_capabilities.ts | 0 .../field_caps_response.test.js | 2 +- .../field_capabilities/field_caps_response.ts | 2 +- .../fetcher/lib/field_capabilities/index.ts | 0 .../lib/field_capabilities/overrides.ts | 0 .../should_read_field_from_doc_values.test.ts | 0 .../should_read_field_from_doc_values.ts | 0 .../server}/fetcher/lib/index.ts | 0 .../fetcher/lib/jobs_compatibility.test.js | 0 .../server}/fetcher/lib/jobs_compatibility.ts | 0 .../server}/fetcher/lib/map_capabilities.ts | 0 .../lib/merge_capabilities_with_fields.ts | 0 .../fetcher/lib/resolve_time_pattern.test.js | 0 .../fetcher/lib/resolve_time_pattern.ts | 0 .../lib/time_pattern_to_wildcard.test.ts | 0 .../fetcher/lib/time_pattern_to_wildcard.ts | 0 .../server}/has_user_index_pattern.test.ts | 2 +- .../server}/has_user_index_pattern.ts | 6 +- src/plugins/data_views/server/index.ts | 37 ++++++ .../server}/index_patterns_api_client.ts | 4 +- src/plugins/data_views/server/mocks.ts | 15 +++ src/plugins/data_views/server/plugin.ts | 74 ++++++++++++ ...ter_index_pattern_usage_collection.test.ts | 4 +- ...register_index_pattern_usage_collection.ts | 18 +-- .../server}/routes.ts | 7 +- .../server}/routes/create_index_pattern.ts | 15 ++- .../server}/routes/default_index_pattern.ts | 17 +-- .../server}/routes/delete_index_pattern.ts | 13 ++- .../server}/routes/fields/update_fields.ts | 16 ++- .../server}/routes/get_index_pattern.ts | 13 ++- .../server}/routes/has_user_index_pattern.ts | 13 ++- .../runtime_fields/create_runtime_field.ts | 16 ++- .../runtime_fields/delete_runtime_field.ts | 16 ++- .../runtime_fields/get_runtime_field.ts | 16 ++- .../runtime_fields/put_runtime_field.ts | 16 ++- .../runtime_fields/update_runtime_field.ts | 18 ++- .../scripted_fields/create_scripted_field.ts | 16 ++- .../scripted_fields/delete_scripted_field.ts | 16 ++- .../scripted_fields/get_scripted_field.ts | 16 ++- .../scripted_fields/put_scripted_field.ts | 16 ++- .../scripted_fields/update_scripted_field.ts | 18 ++- .../server}/routes/update_index_pattern.ts | 13 ++- .../server}/routes/util/handle_errors.ts | 0 .../server}/routes/util/schemas.ts | 2 +- .../server/saved_objects/data_views.ts} | 6 +- .../server/saved_objects}/index.ts | 3 +- .../index_pattern_migrations.test.ts | 0 .../saved_objects/index_pattern_migrations.ts | 0 .../saved_objects/migrations/to_v7_12_0.ts} | 14 +-- .../saved_objects_client_wrapper.test.ts | 2 +- .../server}/saved_objects_client_wrapper.ts | 2 +- src/plugins/data_views/server/types.ts | 51 +++++++++ .../server}/ui_settings_wrapper.ts | 2 +- .../data_views => data_views/server}/utils.ts | 6 +- src/plugins/data_views/tsconfig.json | 26 +++++ .../server/services/new_instance_status.ts | 3 +- .../controls_references.ts | 2 +- .../timeseries_references.ts | 2 +- .../deprecations/scripted_fields.ts | 8 +- .../apis/index_patterns/es_errors/errors.js | 2 +- .../components/top_values/top_values.tsx | 2 +- .../utils/saved_search_utils.test.ts | 2 +- .../translations/translations/ja-JP.json | 12 +- .../translations/translations/zh-CN.json | 12 +- 169 files changed, 996 insertions(+), 497 deletions(-) delete mode 100644 src/plugins/data/common/data_views/index.ts delete mode 100644 src/plugins/data/server/data_views/index_patterns_service.ts create mode 100644 src/plugins/data_views/README.mdx rename src/plugins/{data/common/data_views => data_views/common}/constants.ts (81%) rename src/plugins/{data/common/data_views => data_views/common}/data_view.stub.ts (94%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/__snapshots__/data_view.test.ts.snap (100%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/__snapshots__/data_views.test.ts.snap (100%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/_pattern_cache.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/data_view.stub.ts (91%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/data_view.test.ts (98%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/data_view.ts (97%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/data_views.test.ts (99%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/data_views.ts (96%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/ensure_default_data_view.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/flatten_hit.test.ts (96%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/flatten_hit.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/format_hit.ts (97%) rename src/plugins/{data/common/data_views => data_views/common}/data_views/index.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/errors/data_view_saved_object_conflict.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/errors/duplicate_index_pattern.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/errors/index.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/expressions/index.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/expressions/load_index_pattern.ts (90%) rename src/plugins/{data/common/data_views => data_views/common}/field.stub.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/fields/__snapshots__/data_view_field.test.ts.snap (100%) rename src/plugins/{data/common/data_views => data_views/common}/fields/data_view_field.test.ts (97%) rename src/plugins/{data/common/data_views => data_views/common}/fields/data_view_field.ts (97%) rename src/plugins/{data/common/data_views => data_views/common}/fields/field_list.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/fields/fields.mocks.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/fields/index.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/fields/types.ts (95%) rename src/plugins/{data/common/utils/shorten_dotted_string.test.ts => data_views/common/fields/utils.test.ts} (92%) rename src/plugins/{data/common/data_views => data_views/common}/fields/utils.ts (75%) create mode 100644 src/plugins/data_views/common/index.ts rename src/plugins/{data/common/data_views => data_views/common}/lib/errors.ts (93%) rename src/plugins/{data/common/data_views => data_views/common}/lib/get_title.ts (85%) rename src/plugins/{data/common/data_views => data_views/common}/lib/index.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/lib/types.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/lib/validate_data_view.test.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/lib/validate_data_view.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/mocks.ts (100%) create mode 100644 src/plugins/data_views/common/stubs.ts rename src/plugins/{data/common/data_views => data_views/common}/types.ts (96%) rename src/plugins/{data/common/data_views => data_views/common}/utils.test.ts (100%) rename src/plugins/{data/common/data_views => data_views/common}/utils.ts (89%) create mode 100644 src/plugins/data_views/jest.config.js create mode 100644 src/plugins/data_views/kibana.json rename src/plugins/{data/public/data_views => data_views/public}/data_views/data_view.stub.ts (84%) rename src/plugins/{data/public/data_views => data_views/public}/data_views/data_views_api_client.test.mock.ts (86%) rename src/plugins/{data/public/data_views => data_views/public}/data_views/data_views_api_client.test.ts (100%) rename src/plugins/{data/public/data_views => data_views/public}/data_views/data_views_api_client.ts (90%) rename src/plugins/{data/public/data_views => data_views/public}/data_views/index.ts (88%) rename src/plugins/{data/public/data_views => data_views/public}/data_views/redirect_no_index_pattern.tsx (84%) rename src/plugins/{data/public/data_views => data_views/public}/expressions/index.ts (100%) rename src/plugins/{data/public/data_views => data_views/public}/expressions/load_index_pattern.test.ts (92%) rename src/plugins/{data/public/data_views => data_views/public}/expressions/load_index_pattern.ts (88%) create mode 100644 src/plugins/data_views/public/index.ts create mode 100644 src/plugins/data_views/public/plugin.ts rename src/plugins/{data/public/data_views => data_views/public}/saved_objects_client_wrapper.test.ts (96%) rename src/plugins/{data/public/data_views => data_views/public}/saved_objects_client_wrapper.ts (98%) create mode 100644 src/plugins/data_views/public/types.ts rename src/plugins/{data/public/data_views => data_views/public}/ui_settings_wrapper.ts (95%) rename src/plugins/{data/server/data_views => data_views/server}/capabilities_provider.ts (100%) create mode 100644 src/plugins/data_views/server/data_views_service_factory.ts rename src/plugins/{data/server/data_views => data_views/server}/deprecations/index.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/deprecations/scripted_fields.test.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/deprecations/scripted_fields.ts (89%) rename src/plugins/{data/server/data_views => data_views/server}/error.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/expressions/index.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/expressions/load_index_pattern.test.ts (94%) rename src/plugins/{data/server/data_views => data_views/server}/expressions/load_index_pattern.ts (85%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/index.ts (100%) create mode 100644 src/plugins/data_views/server/fetcher/index_not_found_exception.json rename src/plugins/{data/server/data_views => data_views/server}/fetcher/index_patterns_fetcher.test.ts (95%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/index_patterns_fetcher.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/errors.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/es_api.test.js (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/es_api.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/field_capabilities.test.js (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/field_capabilities.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/field_caps_response.test.js (99%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/field_caps_response.ts (98%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/index.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/overrides.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/should_read_field_from_doc_values.test.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/index.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/jobs_compatibility.test.js (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/jobs_compatibility.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/map_capabilities.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/merge_capabilities_with_fields.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/resolve_time_pattern.test.js (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/resolve_time_pattern.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/time_pattern_to_wildcard.test.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/fetcher/lib/time_pattern_to_wildcard.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/has_user_index_pattern.test.ts (99%) rename src/plugins/{data/server/data_views => data_views/server}/has_user_index_pattern.ts (91%) create mode 100644 src/plugins/data_views/server/index.ts rename src/plugins/{data/server/data_views => data_views/server}/index_patterns_api_client.ts (94%) create mode 100644 src/plugins/data_views/server/mocks.ts create mode 100644 src/plugins/data_views/server/plugin.ts rename src/plugins/{data/server/data_views => data_views/server}/register_index_pattern_usage_collection.test.ts (98%) rename src/plugins/{data/server/data_views => data_views/server}/register_index_pattern_usage_collection.ts (90%) rename src/plugins/{data/server/data_views => data_views/server}/routes.ts (96%) rename src/plugins/{data/server/data_views => data_views/server}/routes/create_index_pattern.ts (84%) rename src/plugins/{data/server/data_views => data_views/server}/routes/default_index_pattern.ts (76%) rename src/plugins/{data/server/data_views => data_views/server}/routes/delete_index_pattern.ts (75%) rename src/plugins/{data/server/data_views => data_views/server}/routes/fields/update_fields.ts (87%) rename src/plugins/{data/server/data_views => data_views/server}/routes/get_index_pattern.ts (76%) rename src/plugins/{data/server/data_views => data_views/server}/routes/has_user_index_pattern.ts (69%) rename src/plugins/{data/server/data_views => data_views/server}/routes/runtime_fields/create_runtime_field.ts (82%) rename src/plugins/{data/server/data_views => data_views/server}/routes/runtime_fields/delete_runtime_field.ts (79%) rename src/plugins/{data/server/data_views => data_views/server}/routes/runtime_fields/get_runtime_field.ts (79%) rename src/plugins/{data/server/data_views => data_views/server}/routes/runtime_fields/put_runtime_field.ts (82%) rename src/plugins/{data/server/data_views => data_views/server}/routes/runtime_fields/update_runtime_field.ts (83%) rename src/plugins/{data/server/data_views => data_views/server}/routes/scripted_fields/create_scripted_field.ts (83%) rename src/plugins/{data/server/data_views => data_views/server}/routes/scripted_fields/delete_scripted_field.ts (81%) rename src/plugins/{data/server/data_views => data_views/server}/routes/scripted_fields/get_scripted_field.ts (81%) rename src/plugins/{data/server/data_views => data_views/server}/routes/scripted_fields/put_scripted_field.ts (83%) rename src/plugins/{data/server/data_views => data_views/server}/routes/scripted_fields/update_scripted_field.ts (86%) rename src/plugins/{data/server/data_views => data_views/server}/routes/update_index_pattern.ts (91%) rename src/plugins/{data/server/data_views => data_views/server}/routes/util/handle_errors.ts (100%) rename src/plugins/{data/server/data_views => data_views/server}/routes/util/schemas.ts (96%) rename src/plugins/{data/server/saved_objects/index_patterns.ts => data_views/server/saved_objects/data_views.ts} (88%) rename src/plugins/{data/common/utils => data_views/server/saved_objects}/index.ts (81%) rename src/plugins/{data => data_views}/server/saved_objects/index_pattern_migrations.test.ts (100%) rename src/plugins/{data => data_views}/server/saved_objects/index_pattern_migrations.ts (100%) rename src/plugins/{data/common/utils/shorten_dotted_string.ts => data_views/server/saved_objects/migrations/to_v7_12_0.ts} (57%) rename src/plugins/{data/server/data_views => data_views/server}/saved_objects_client_wrapper.test.ts (96%) rename src/plugins/{data/server/data_views => data_views/server}/saved_objects_client_wrapper.ts (98%) create mode 100644 src/plugins/data_views/server/types.ts rename src/plugins/{data/server/data_views => data_views/server}/ui_settings_wrapper.ts (95%) rename src/plugins/{data/server/data_views => data_views/server}/utils.ts (92%) create mode 100644 src/plugins/data_views/tsconfig.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 90f88de7d1104..9aa308c0dc58d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -62,6 +62,7 @@ /packages/kbn-interpreter/ @elastic/kibana-app-services /src/plugins/bfetch/ @elastic/kibana-app-services /src/plugins/data/ @elastic/kibana-app-services +/src/plugins/data-views/ @elastic/kibana-app-services /src/plugins/embeddable/ @elastic/kibana-app-services /src/plugins/expressions/ @elastic/kibana-app-services /src/plugins/field_formats/ @elastic/kibana-app-services diff --git a/.i18nrc.json b/.i18nrc.json index 4107772e421ca..45016edc38dcd 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -9,6 +9,7 @@ "bfetch": "src/plugins/bfetch", "dashboard": "src/plugins/dashboard", "data": "src/plugins/data", + "dataViews": "src/plugins/data_views", "embeddableApi": "src/plugins/embeddable", "embeddableExamples": "examples/embeddable_examples", "fieldFormats": "src/plugins/field_formats", diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index edc1821f3b223..7f7041f7815cd 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -57,6 +57,12 @@ as uiSettings within the code. |The data plugin provides common data access services, such as search and query, for solutions and application developers. +|{kib-repo}blob/{branch}/src/plugins/data_views/README.mdx[dataViews] +|The data views API provides a consistent method of structuring and formatting documents +and field lists across the various Kibana apps. Its typically used in conjunction with + for composing queries. + + |{kib-repo}blob/{branch}/src/plugins/dev_tools/README.md[devTools] |The ui/registry/dev_tools is removed in favor of the devTools plugin which exposes a register method in the setup contract. Registering app works mostly the same as registering apps in core.application.register. diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 8fb31b36f39d5..a0ca88e4e04bd 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -116,3 +116,4 @@ pageLoadAssetSize: expressions: 239290 securitySolution: 231753 customIntegrations: 28810 + dataViews: 42000 diff --git a/src/plugins/data/README.mdx b/src/plugins/data/README.mdx index 40e82d3034ee2..18b755275b4aa 100644 --- a/src/plugins/data/README.mdx +++ b/src/plugins/data/README.mdx @@ -49,15 +49,6 @@ This is helpful when you want to provide a user with options, for example when c ``` -## Data Views - -The data views API provides a consistent method of structuring and formatting documents -and field lists across the various Kibana apps. Its typically used in conjunction with - for composing queries. - -*Note: Kibana index patterns are currently being renamed to data views. There will be some naming inconsistencies until the transition is complete.* - - ## Query The query service is responsible for managing the configuration of a search query (`QueryState`): filters, time range, query string, and settings such as the auto refresh behavior and saved queries. diff --git a/src/plugins/data/common/constants.ts b/src/plugins/data/common/constants.ts index 2c339d1408237..c236be18a8e41 100644 --- a/src/plugins/data/common/constants.ts +++ b/src/plugins/data/common/constants.ts @@ -9,15 +9,6 @@ export const DEFAULT_QUERY_LANGUAGE = 'kuery'; export const KIBANA_USER_QUERY_LANGUAGE_KEY = 'kibana.userQueryLanguage'; -/** @public **/ -export const DATA_VIEW_SAVED_OBJECT_TYPE = 'index-pattern'; - -/** - * @deprecated Use DATA_VIEW_SAVED_OBJECT_TYPE. All index pattern interfaces were renamed. - */ - -export const INDEX_PATTERN_SAVED_OBJECT_TYPE = DATA_VIEW_SAVED_OBJECT_TYPE; - export type ValueSuggestionsMethod = 'terms_enum' | 'terms_agg'; export const UI_SETTINGS = { diff --git a/src/plugins/data/common/data_views/index.ts b/src/plugins/data/common/data_views/index.ts deleted file mode 100644 index fd1df0336815a..0000000000000 --- a/src/plugins/data/common/data_views/index.ts +++ /dev/null @@ -1,21 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export * from './constants'; -export * from './fields'; -export * from './types'; -export { - IndexPatternsService, - IndexPatternsContract, - DataViewsService, - DataViewsContract, -} from './data_views'; -// todo was trying to export this as type but wasn't working -export { IndexPattern, IndexPatternListItem, DataView, DataViewListItem } from './data_views'; -export * from './errors'; -export * from './expressions'; diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts index 8a9a93f96b68b..195cb9d475314 100644 --- a/src/plugins/data/common/index.ts +++ b/src/plugins/data/common/index.ts @@ -11,18 +11,68 @@ export * from './constants'; export * from './es_query'; -export * from './data_views'; export * from './kbn_field_types'; export * from './query'; export * from './search'; export * from './types'; -export * from './utils'; export * from './exports'; - -/** - * - * @deprecated Use data plugin interface instead - * @removeBy 8.1 - */ - -export { IndexPatternAttributes } from './types'; +export type { + IFieldType, + IIndexPatternFieldList, + FieldFormatMap, + RuntimeType, + RuntimeField, + IIndexPattern, + DataViewAttributes, + IndexPatternAttributes, + FieldAttrs, + FieldAttrSet, + OnNotification, + OnError, + UiSettingsCommon, + SavedObjectsClientCommonFindArgs, + SavedObjectsClientCommon, + GetFieldsOptions, + GetFieldsOptionsTimePattern, + IDataViewsApiClient, + IIndexPatternsApiClient, + SavedObject, + AggregationRestrictions, + TypeMeta, + FieldSpecConflictDescriptions, + FieldSpecExportFmt, + FieldSpec, + DataViewFieldMap, + IndexPatternFieldMap, + DataViewSpec, + IndexPatternSpec, + SourceFilter, + IndexPatternExpressionType, + IndexPatternLoadStartDependencies, + IndexPatternLoadExpressionFunctionDefinition, +} from '../../data_views/common'; +export { + RUNTIME_FIELD_TYPES, + FLEET_ASSETS_TO_IGNORE, + META_FIELDS, + DATA_VIEW_SAVED_OBJECT_TYPE, + INDEX_PATTERN_SAVED_OBJECT_TYPE, + isFilterable, + isNestedField, + fieldList, + DataViewField, + IndexPatternField, + DataViewType, + IndexPatternType, + IndexPatternsService, + IndexPatternsContract, + DataViewsService, + DataViewsContract, + IndexPattern, + IndexPatternListItem, + DataView, + DataViewListItem, + DuplicateDataViewError, + DataViewSavedObjectConflictError, + getIndexPatternLoadMeta, +} from '../../data_views/common'; diff --git a/src/plugins/data/common/mocks.ts b/src/plugins/data/common/mocks.ts index 66ad3b695d24c..c656d9d21346e 100644 --- a/src/plugins/data/common/mocks.ts +++ b/src/plugins/data/common/mocks.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export * from './data_views/fields/fields.mocks'; +export * from '../../data_views/common/fields/fields.mocks'; diff --git a/src/plugins/data/common/search/aggs/param_types/field.ts b/src/plugins/data/common/search/aggs/param_types/field.ts index e1c872ac16701..05e1302475d04 100644 --- a/src/plugins/data/common/search/aggs/param_types/field.ts +++ b/src/plugins/data/common/search/aggs/param_types/field.ts @@ -15,7 +15,7 @@ import { import { BaseParamType } from './base'; import { propFilter } from '../utils'; import { KBN_FIELD_TYPES } from '../../../kbn_field_types/types'; -import { isNestedField, IndexPatternField } from '../../../data_views/fields'; +import { isNestedField, IndexPatternField } from '../../../../../data_views/common'; const filterByType = propFilter('type'); diff --git a/src/plugins/data/common/search/expressions/esaggs/esaggs_fn.ts b/src/plugins/data/common/search/expressions/esaggs/esaggs_fn.ts index a9078d6042db8..09d68177c3ec3 100644 --- a/src/plugins/data/common/search/expressions/esaggs/esaggs_fn.ts +++ b/src/plugins/data/common/search/expressions/esaggs/esaggs_fn.ts @@ -12,7 +12,7 @@ import { Observable } from 'rxjs'; import type { Datatable, ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { buildExpressionFunction } from '../../../../../../plugins/expressions/common'; -import { IndexPatternExpressionType } from '../../../data_views/expressions'; +import { IndexPatternExpressionType } from '../../../../../data_views/common/expressions'; import { IndexPatternsContract } from '../../..'; import { AggsStart, AggExpressionType, aggCountFnName } from '../../aggs'; diff --git a/src/plugins/data/common/search/search_source/extract_references.ts b/src/plugins/data/common/search/search_source/extract_references.ts index c7f6c53d0f5f7..dfcd1b12cb62f 100644 --- a/src/plugins/data/common/search/search_source/extract_references.ts +++ b/src/plugins/data/common/search/search_source/extract_references.ts @@ -10,7 +10,7 @@ import { SavedObjectReference } from 'src/core/types'; import { Filter } from '@kbn/es-query'; import { SearchSourceFields } from './types'; -import { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../../constants'; +import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../../../../data/common'; export const extractReferences = ( state: SearchSourceFields @@ -22,7 +22,7 @@ export const extractReferences = ( const refName = 'kibanaSavedObjectMeta.searchSourceJSON.index'; references.push({ name: refName, - type: INDEX_PATTERN_SAVED_OBJECT_TYPE, + type: DATA_VIEW_SAVED_OBJECT_TYPE, id: indexId, }); searchSourceFields = { @@ -42,7 +42,7 @@ export const extractReferences = ( const refName = `kibanaSavedObjectMeta.searchSourceJSON.filter[${i}].meta.index`; references.push({ name: refName, - type: INDEX_PATTERN_SAVED_OBJECT_TYPE, + type: DATA_VIEW_SAVED_OBJECT_TYPE, id: filterRow.meta.index, }); return { diff --git a/src/plugins/data/common/stubs.ts b/src/plugins/data/common/stubs.ts index 5cddcf397f442..ec53b20f6ff3d 100644 --- a/src/plugins/data/common/stubs.ts +++ b/src/plugins/data/common/stubs.ts @@ -6,6 +6,6 @@ * Side Public License, v 1. */ -export * from './data_views/field.stub'; -export * from './data_views/data_view.stub'; +export * from '../../data_views/common/field.stub'; +export * from '../../data_views/common/data_view.stub'; export * from './es_query/stubs'; diff --git a/src/plugins/data/common/types.ts b/src/plugins/data/common/types.ts index c574d4854cfd6..81b47735d8fe2 100644 --- a/src/plugins/data/common/types.ts +++ b/src/plugins/data/common/types.ts @@ -8,7 +8,6 @@ export * from './query/types'; export * from './kbn_field_types/types'; -export * from './data_views/types'; /** * If a service is being shared on both the client and the server, and diff --git a/src/plugins/data/kibana.json b/src/plugins/data/kibana.json index c21955501787d..3d70d138d80ed 100644 --- a/src/plugins/data/kibana.json +++ b/src/plugins/data/kibana.json @@ -3,8 +3,8 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["bfetch", "expressions", "uiActions", "share", "inspector", "fieldFormats"], - "serviceFolders": ["search", "data_views", "query", "autocomplete", "ui"], + "requiredPlugins": ["bfetch", "expressions", "uiActions", "share", "inspector", "fieldFormats", "dataViews"], + "serviceFolders": ["search", "query", "autocomplete", "ui"], "optionalPlugins": ["usageCollection"], "extraPublicDirs": ["common"], "requiredBundles": ["kibanaUtils", "kibanaReact", "inspector"], diff --git a/src/plugins/data/public/data_views/index.ts b/src/plugins/data/public/data_views/index.ts index 0125b173989fb..4fb2bbaf08503 100644 --- a/src/plugins/data/public/data_views/index.ts +++ b/src/plugins/data/public/data_views/index.ts @@ -6,25 +6,4 @@ * Side Public License, v 1. */ -export { - ILLEGAL_CHARACTERS_KEY, - CONTAINS_SPACES_KEY, - ILLEGAL_CHARACTERS_VISIBLE, - ILLEGAL_CHARACTERS, - validateDataView, -} from '../../common/data_views/lib'; -export { flattenHitWrapper, formatHitProvider, onRedirectNoIndexPattern } from './data_views'; - -export { IndexPatternField, IIndexPatternFieldList, TypeMeta } from '../../common/data_views'; - -export { - IndexPatternsService, - IndexPatternsContract, - IndexPattern, - DataViewsApiClient, - DataViewsService, - DataViewsContract, - DataView, -} from './data_views'; -export { UiSettingsPublicToCommon } from './ui_settings_wrapper'; -export { SavedObjectsClientPublicToCommon } from './saved_objects_client_wrapper'; +export * from '../../../data_views/public'; diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index e1f5b98baca9c..4b6d184f807a4 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -83,14 +83,12 @@ export { IndexPatternLoadExpressionFunctionDefinition, fieldList, GetFieldsOptions, - INDEX_PATTERN_SAVED_OBJECT_TYPE, AggregationRestrictions, IndexPatternType, IndexPatternListItem, + DuplicateDataViewError, } from '../common'; -export { DuplicateDataViewError } from '../common/data_views/errors'; - /* * Autocomplete query suggestions: */ diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index aa766f78a5ecb..4a55cc2a0d511 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -21,12 +21,6 @@ import { AutocompleteService } from './autocomplete'; import { SearchService } from './search/search_service'; import { QueryService } from './query'; import { createIndexPatternSelect } from './ui/index_pattern_select'; -import { - DataViewsService, - onRedirectNoIndexPattern, - DataViewsApiClient, - UiSettingsPublicToCommon, -} from './data_views'; import { setIndexPatterns, setNotifications, @@ -44,8 +38,6 @@ import { createSelectRangeAction, } from './actions'; import { APPLY_FILTER_TRIGGER, applyFilterTrigger } from './triggers'; -import { SavedObjectsClientPublicToCommon } from './data_views'; -import { getIndexPatternLoad } from './data_views/expressions'; import { UsageCollectionSetup } from '../../usage_collection/public'; import { getTableViewDescription } from './utils/table_inspector_view'; import { NowProvider, NowProviderInternalContract } from './now_provider'; @@ -89,8 +81,6 @@ export class DataPublicPlugin ): DataPublicPluginSetup { const startServices = createStartServicesGetter(core.getStartServices); - expressions.registerFunction(getIndexPatternLoad({ getStartServices: core.getStartServices })); - this.usageCollection = usageCollection; const searchService = this.searchService.setup(core, { @@ -138,29 +128,13 @@ export class DataPublicPlugin public start( core: CoreStart, - { uiActions, fieldFormats }: DataStartDependencies + { uiActions, fieldFormats, dataViews }: DataStartDependencies ): DataPublicPluginStart { - const { uiSettings, http, notifications, savedObjects, overlays, application } = core; + const { uiSettings, notifications, savedObjects, overlays } = core; setNotifications(notifications); setOverlays(overlays); setUiSettings(uiSettings); - - const indexPatterns = new DataViewsService({ - uiSettings: new UiSettingsPublicToCommon(uiSettings), - savedObjectsClient: new SavedObjectsClientPublicToCommon(savedObjects.client), - apiClient: new DataViewsApiClient(http), - fieldFormats, - onNotification: (toastInputFields) => { - notifications.toasts.add(toastInputFields); - }, - onError: notifications.toasts.addError.bind(notifications.toasts), - onRedirectNoIndexPattern: onRedirectNoIndexPattern( - application.capabilities, - application.navigateToApp, - overlays - ), - }); - setIndexPatterns(indexPatterns); + setIndexPatterns(dataViews); const query = this.queryService.start({ storage: this.storage, @@ -168,7 +142,7 @@ export class DataPublicPlugin uiSettings, }); - const search = this.searchService.start(core, { fieldFormats, indexPatterns }); + const search = this.searchService.start(core, { fieldFormats, indexPatterns: dataViews }); setSearchService(search); uiActions.addTriggerAction( @@ -197,8 +171,8 @@ export class DataPublicPlugin }, autocomplete: this.autocomplete.start(), fieldFormats, - indexPatterns, - dataViews: indexPatterns, + indexPatterns: dataViews, + dataViews, query, search, nowProvider: this.nowProvider, @@ -214,7 +188,7 @@ export class DataPublicPlugin return { ...dataServices, ui: { - IndexPatternSelect: createIndexPatternSelect(indexPatterns), + IndexPatternSelect: createIndexPatternSelect(dataViews), SearchBar, }, }; diff --git a/src/plugins/data/public/stubs.ts b/src/plugins/data/public/stubs.ts index 3d160a56bd8cf..b81d9c4cc78e4 100644 --- a/src/plugins/data/public/stubs.ts +++ b/src/plugins/data/public/stubs.ts @@ -7,4 +7,5 @@ */ export * from '../common/stubs'; -export { createStubDataView } from './data_views/data_views/data_view.stub'; +// eslint-disable-next-line +export { createStubDataView } from '../../data_views/public/data_views/data_view.stub'; diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index 7ed13c2096515..9b16ee39f5c80 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -11,6 +11,7 @@ import { CoreStart } from 'src/core/public'; import { BfetchPublicSetup } from 'src/plugins/bfetch/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { ExpressionsSetup } from 'src/plugins/expressions/public'; +import { DataViewsPublicPluginStart } from 'src/plugins/data_views/public'; import { UiActionsSetup, UiActionsStart } from 'src/plugins/ui_actions/public'; import { FieldFormatsSetup, FieldFormatsStart } from 'src/plugins/field_formats/public'; import { AutocompleteSetup, AutocompleteStart } from './autocomplete'; @@ -35,6 +36,7 @@ export interface DataSetupDependencies { export interface DataStartDependencies { uiActions: UiActionsStart; fieldFormats: FieldFormatsStart; + dataViews: DataViewsPublicPluginStart; } /** diff --git a/src/plugins/data/server/data_views/index.ts b/src/plugins/data/server/data_views/index.ts index 7226d6f015cf8..91a61f4bcb7db 100644 --- a/src/plugins/data/server/data_views/index.ts +++ b/src/plugins/data/server/data_views/index.ts @@ -6,12 +6,4 @@ * Side Public License, v 1. */ -export * from './utils'; -export { - IndexPatternsFetcher, - FieldDescriptor, - shouldReadFieldFromDocValues, - mergeCapabilitiesWithFields, - getCapabilitiesForRollupIndices, -} from './fetcher'; -export { IndexPatternsServiceProvider, IndexPatternsServiceStart } from './index_patterns_service'; +export * from '../../../data_views/server'; diff --git a/src/plugins/data/server/data_views/index_patterns_service.ts b/src/plugins/data/server/data_views/index_patterns_service.ts deleted file mode 100644 index 5286d1d64794b..0000000000000 --- a/src/plugins/data/server/data_views/index_patterns_service.ts +++ /dev/null @@ -1,108 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - CoreSetup, - CoreStart, - Plugin, - Logger, - SavedObjectsClientContract, - ElasticsearchClient, - UiSettingsServiceStart, -} from 'kibana/server'; -import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; -import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { DataPluginStart } from '../plugin'; -import { registerRoutes } from './routes'; -import { indexPatternSavedObjectType } from '../saved_objects'; -import { capabilitiesProvider } from './capabilities_provider'; -import { IndexPatternsCommonService } from '../'; -import { FieldFormatsStart } from '../../../field_formats/server'; -import { getIndexPatternLoad } from './expressions'; -import { UiSettingsServerToCommon } from './ui_settings_wrapper'; -import { IndexPatternsApiServer } from './index_patterns_api_client'; -import { SavedObjectsClientServerToCommon } from './saved_objects_client_wrapper'; -import { registerIndexPatternsUsageCollector } from './register_index_pattern_usage_collection'; -import { createScriptedFieldsDeprecationsConfig } from './deprecations'; - -export interface IndexPatternsServiceStart { - indexPatternsServiceFactory: ( - savedObjectsClient: SavedObjectsClientContract, - elasticsearchClient: ElasticsearchClient - ) => Promise; -} - -export interface IndexPatternsServiceSetupDeps { - expressions: ExpressionsServerSetup; - logger: Logger; - usageCollection?: UsageCollectionSetup; -} - -export interface IndexPatternsServiceStartDeps { - fieldFormats: FieldFormatsStart; - logger: Logger; -} - -export const indexPatternsServiceFactory = - ({ - logger, - uiSettings, - fieldFormats, - }: { - logger: Logger; - uiSettings: UiSettingsServiceStart; - fieldFormats: FieldFormatsStart; - }) => - async ( - savedObjectsClient: SavedObjectsClientContract, - elasticsearchClient: ElasticsearchClient - ) => { - const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); - const formats = await fieldFormats.fieldFormatServiceFactory(uiSettingsClient); - - return new IndexPatternsCommonService({ - uiSettings: new UiSettingsServerToCommon(uiSettingsClient), - savedObjectsClient: new SavedObjectsClientServerToCommon(savedObjectsClient), - apiClient: new IndexPatternsApiServer(elasticsearchClient, savedObjectsClient), - fieldFormats: formats, - onError: (error) => { - logger.error(error); - }, - onNotification: ({ title, text }) => { - logger.warn(`${title}${text ? ` : ${text}` : ''}`); - }, - }); - }; - -export class IndexPatternsServiceProvider implements Plugin { - public setup( - core: CoreSetup, - { expressions, usageCollection }: IndexPatternsServiceSetupDeps - ) { - core.savedObjects.registerType(indexPatternSavedObjectType); - core.capabilities.registerProvider(capabilitiesProvider); - - registerRoutes(core.http, core.getStartServices); - - expressions.registerFunction(getIndexPatternLoad({ getStartServices: core.getStartServices })); - registerIndexPatternsUsageCollector(core.getStartServices, usageCollection); - core.deprecations.registerDeprecations(createScriptedFieldsDeprecationsConfig(core)); - } - - public start(core: CoreStart, { fieldFormats, logger }: IndexPatternsServiceStartDeps) { - const { uiSettings } = core; - - return { - indexPatternsServiceFactory: indexPatternsServiceFactory({ - logger, - uiSettings, - fieldFormats, - }), - }; - } -} diff --git a/src/plugins/data/server/data_views/mocks.ts b/src/plugins/data/server/data_views/mocks.ts index 6435c09cb7ec9..69b57ed079127 100644 --- a/src/plugins/data/server/data_views/mocks.ts +++ b/src/plugins/data/server/data_views/mocks.ts @@ -6,8 +6,4 @@ * Side Public License, v 1. */ -export function createIndexPatternsStartMock() { - return { - indexPatternsServiceFactory: jest.fn().mockResolvedValue({ get: jest.fn() }), - }; -} +export * from '../../../data_views/server/mocks'; diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index a17c66c694b2d..fce73e65dc699 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -30,7 +30,7 @@ export const exporters = { * Field Formats: */ -export { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../common'; +export { DATA_VIEW_SAVED_OBJECT_TYPE } from '../common'; /* * Index patterns: diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts index 3342519782d7a..cb52500e78f94 100644 --- a/src/plugins/data/server/plugin.ts +++ b/src/plugins/data/server/plugin.ts @@ -9,8 +9,8 @@ import { CoreSetup, CoreStart, Logger, Plugin, PluginInitializerContext } from 'src/core/server'; import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; import { BfetchServerSetup } from 'src/plugins/bfetch/server'; +import { PluginStart as DataViewsServerPluginStart } from 'src/plugins/data_views/server'; import { ConfigSchema } from '../config'; -import { IndexPatternsServiceProvider, IndexPatternsServiceStart } from './data_views'; import { ISearchSetup, ISearchStart, SearchEnhancements } from './search'; import { SearchService } from './search/search_service'; import { QueryService } from './query/query_service'; @@ -43,7 +43,7 @@ export interface DataPluginStart { * @deprecated - use "fieldFormats" plugin directly instead */ fieldFormats: FieldFormatsStart; - indexPatterns: IndexPatternsServiceStart; + indexPatterns: DataViewsServerPluginStart; } export interface DataPluginSetupDependencies { @@ -56,6 +56,7 @@ export interface DataPluginSetupDependencies { export interface DataPluginStartDependencies { fieldFormats: FieldFormatsStart; logger: Logger; + dataViews: DataViewsServerPluginStart; } export class DataServerPlugin @@ -71,7 +72,6 @@ export class DataServerPlugin private readonly scriptsService: ScriptsService; private readonly kqlTelemetryService: KqlTelemetryService; private readonly autocompleteService: AutocompleteService; - private readonly indexPatterns = new IndexPatternsServiceProvider(); private readonly queryService = new QueryService(); private readonly logger: Logger; @@ -91,11 +91,6 @@ export class DataServerPlugin this.queryService.setup(core); this.autocompleteService.setup(core); this.kqlTelemetryService.setup(core, { usageCollection }); - this.indexPatterns.setup(core, { - expressions, - logger: this.logger.get('indexPatterns'), - usageCollection, - }); core.uiSettings.register(getUiSettings()); @@ -114,16 +109,11 @@ export class DataServerPlugin }; } - public start(core: CoreStart, { fieldFormats }: DataPluginStartDependencies) { - const indexPatterns = this.indexPatterns.start(core, { - fieldFormats, - logger: this.logger.get('indexPatterns'), - }); - + public start(core: CoreStart, { fieldFormats, dataViews }: DataPluginStartDependencies) { return { fieldFormats, - indexPatterns, - search: this.searchService.start(core, { fieldFormats, indexPatterns }), + indexPatterns: dataViews, + search: this.searchService.start(core, { fieldFormats, indexPatterns: dataViews }), }; } diff --git a/src/plugins/data/server/saved_objects/index.ts b/src/plugins/data/server/saved_objects/index.ts index 53d4360782b5b..8bfce1a4d3696 100644 --- a/src/plugins/data/server/saved_objects/index.ts +++ b/src/plugins/data/server/saved_objects/index.ts @@ -7,6 +7,5 @@ */ export { querySavedObjectType } from './query'; -export { indexPatternSavedObjectType } from './index_patterns'; export { kqlTelemetry } from './kql_telemetry'; export { searchTelemetry } from './search_telemetry'; diff --git a/src/plugins/data/tsconfig.json b/src/plugins/data/tsconfig.json index 3687604e05e2b..92f80f47eca64 100644 --- a/src/plugins/data/tsconfig.json +++ b/src/plugins/data/tsconfig.json @@ -23,6 +23,7 @@ { "path": "../usage_collection/tsconfig.json" }, { "path": "../kibana_utils/tsconfig.json" }, { "path": "../kibana_react/tsconfig.json" }, - { "path": "../field_formats/tsconfig.json" } + { "path": "../field_formats/tsconfig.json" }, + { "path": "../data_views/tsconfig.json" } ] } diff --git a/src/plugins/data_views/README.mdx b/src/plugins/data_views/README.mdx new file mode 100644 index 0000000000000..90efdc18d8fdb --- /dev/null +++ b/src/plugins/data_views/README.mdx @@ -0,0 +1,19 @@ +--- +id: kibDataPlugin +slug: /kibana-dev-docs/services/data-plugin +title: Data services +image: https://source.unsplash.com/400x175/?Search +summary: The data plugin contains services for searching, querying and filtering. +date: 2020-12-02 +tags: ['kibana', 'dev', 'contributor', 'api docs'] +--- + +# Data Views + +The data views API provides a consistent method of structuring and formatting documents +and field lists across the various Kibana apps. Its typically used in conjunction with + for composing queries. + +*Note: Kibana index patterns are currently being renamed to data views. There will be some naming inconsistencies until the transition is complete.* + + diff --git a/src/plugins/data/common/data_views/constants.ts b/src/plugins/data_views/common/constants.ts similarity index 81% rename from src/plugins/data/common/data_views/constants.ts rename to src/plugins/data_views/common/constants.ts index 67e266dbd84a2..ca42221806b2e 100644 --- a/src/plugins/data/common/data_views/constants.ts +++ b/src/plugins/data_views/common/constants.ts @@ -29,3 +29,14 @@ export const FLEET_ASSETS_TO_IGNORE = { METRICS_DATA_STREAM_TO_IGNORE: 'metrics-elastic_agent', // ignore ds created by Fleet server itself METRICS_ENDPOINT_INDEX_TO_IGNORE: 'metrics-endpoint.metadata_current_default', // ignore index created by Fleet endpoint package installed by default in Cloud }; + +export const META_FIELDS = 'metaFields'; + +/** @public **/ +export const DATA_VIEW_SAVED_OBJECT_TYPE = 'index-pattern'; + +/** + * @deprecated Use DATA_VIEW_SAVED_OBJECT_TYPE. All index pattern interfaces were renamed. + */ + +export const INDEX_PATTERN_SAVED_OBJECT_TYPE = DATA_VIEW_SAVED_OBJECT_TYPE; diff --git a/src/plugins/data/common/data_views/data_view.stub.ts b/src/plugins/data_views/common/data_view.stub.ts similarity index 94% rename from src/plugins/data/common/data_views/data_view.stub.ts rename to src/plugins/data_views/common/data_view.stub.ts index a3279434c7a0b..2eb6d4f5d7813 100644 --- a/src/plugins/data/common/data_views/data_view.stub.ts +++ b/src/plugins/data_views/common/data_view.stub.ts @@ -12,8 +12,8 @@ export { createStubDataView, createStubDataView as createStubIndexPattern, } from './data_views/data_view.stub'; -import { SavedObject } from '../../../../core/types'; -import { DataViewAttributes } from '../types'; +import { SavedObject } from '../../../core/types'; +import { DataViewAttributes } from './types'; export const stubDataView = createStubDataView({ spec: { diff --git a/src/plugins/data/common/data_views/data_views/__snapshots__/data_view.test.ts.snap b/src/plugins/data_views/common/data_views/__snapshots__/data_view.test.ts.snap similarity index 100% rename from src/plugins/data/common/data_views/data_views/__snapshots__/data_view.test.ts.snap rename to src/plugins/data_views/common/data_views/__snapshots__/data_view.test.ts.snap diff --git a/src/plugins/data/common/data_views/data_views/__snapshots__/data_views.test.ts.snap b/src/plugins/data_views/common/data_views/__snapshots__/data_views.test.ts.snap similarity index 100% rename from src/plugins/data/common/data_views/data_views/__snapshots__/data_views.test.ts.snap rename to src/plugins/data_views/common/data_views/__snapshots__/data_views.test.ts.snap diff --git a/src/plugins/data/common/data_views/data_views/_pattern_cache.ts b/src/plugins/data_views/common/data_views/_pattern_cache.ts similarity index 100% rename from src/plugins/data/common/data_views/data_views/_pattern_cache.ts rename to src/plugins/data_views/common/data_views/_pattern_cache.ts diff --git a/src/plugins/data/common/data_views/data_views/data_view.stub.ts b/src/plugins/data_views/common/data_views/data_view.stub.ts similarity index 91% rename from src/plugins/data/common/data_views/data_views/data_view.stub.ts rename to src/plugins/data_views/common/data_views/data_view.stub.ts index 5ff2d077812a8..bb7696b0e1262 100644 --- a/src/plugins/data/common/data_views/data_views/data_view.stub.ts +++ b/src/plugins/data_views/common/data_views/data_view.stub.ts @@ -8,8 +8,8 @@ import { DataView } from './data_view'; import { DataViewSpec } from '../types'; -import { FieldFormatsStartCommon } from '../../../../field_formats/common'; -import { fieldFormatsMock } from '../../../../field_formats/common/mocks'; +import { FieldFormatsStartCommon } from '../../../field_formats/common'; +import { fieldFormatsMock } from '../../../field_formats/common/mocks'; /** * Create a custom stub index pattern. Use it in your unit tests where an {@link DataView} expected. diff --git a/src/plugins/data/common/data_views/data_views/data_view.test.ts b/src/plugins/data_views/common/data_views/data_view.test.ts similarity index 98% rename from src/plugins/data/common/data_views/data_views/data_view.test.ts rename to src/plugins/data_views/common/data_views/data_view.test.ts index 6aea86a7adae7..990b8fa4d5f35 100644 --- a/src/plugins/data/common/data_views/data_views/data_view.test.ts +++ b/src/plugins/data_views/common/data_views/data_view.test.ts @@ -10,12 +10,12 @@ import { map, last } from 'lodash'; import { IndexPattern } from './data_view'; -import { DuplicateField } from '../../../../kibana_utils/common'; +import { DuplicateField } from '../../../kibana_utils/common'; import { IndexPatternField } from '../fields'; -import { fieldFormatsMock } from '../../../../field_formats/common/mocks'; -import { FieldFormat } from '../../../../field_formats/common'; +import { fieldFormatsMock } from '../../../field_formats/common/mocks'; +import { FieldFormat } from '../../../field_formats/common'; import { RuntimeField } from '../types'; import { stubLogstashFields } from '../field.stub'; import { stubbedSavedObjectIndexPattern } from '../data_view.stub'; diff --git a/src/plugins/data/common/data_views/data_views/data_view.ts b/src/plugins/data_views/common/data_views/data_view.ts similarity index 97% rename from src/plugins/data/common/data_views/data_views/data_view.ts rename to src/plugins/data_views/common/data_views/data_view.ts index 18d301d2f9ea7..00b96cda32ad7 100644 --- a/src/plugins/data/common/data_views/data_views/data_view.ts +++ b/src/plugins/data_views/common/data_views/data_view.ts @@ -9,19 +9,19 @@ /* eslint-disable max-classes-per-file */ import _, { each, reject } from 'lodash'; -import { castEsToKbnFieldTypeName } from '@kbn/field-types'; +import { castEsToKbnFieldTypeName, ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; import type { estypes } from '@elastic/elasticsearch'; -import { FieldAttrs, FieldAttrSet, DataViewAttributes } from '../..'; +import { FieldAttrs, FieldAttrSet, DataViewAttributes } from '..'; import type { RuntimeField } from '../types'; -import { DuplicateField } from '../../../../kibana_utils/common'; +import { DuplicateField } from '../../../kibana_utils/common'; -import { ES_FIELD_TYPES, KBN_FIELD_TYPES, IIndexPattern, IFieldType } from '../../../common'; +import { IIndexPattern, IFieldType } from '../../common'; import { DataViewField, IIndexPatternFieldList, fieldList } from '../fields'; import { formatHitProvider } from './format_hit'; import { flattenHitWrapper } from './flatten_hit'; -import { FieldFormatsStartCommon, FieldFormat } from '../../../../field_formats/common'; +import { FieldFormatsStartCommon, FieldFormat } from '../../../field_formats/common'; import { DataViewSpec, TypeMeta, SourceFilter, DataViewFieldMap } from '../types'; -import { SerializedFieldFormat } from '../../../../expressions/common'; +import { SerializedFieldFormat } from '../../../expressions/common'; interface DataViewDeps { spec?: DataViewSpec; diff --git a/src/plugins/data/common/data_views/data_views/data_views.test.ts b/src/plugins/data_views/common/data_views/data_views.test.ts similarity index 99% rename from src/plugins/data/common/data_views/data_views/data_views.test.ts rename to src/plugins/data_views/common/data_views/data_views.test.ts index ef9381f16d934..9a01e52ce48e2 100644 --- a/src/plugins/data/common/data_views/data_views/data_views.test.ts +++ b/src/plugins/data_views/common/data_views/data_views.test.ts @@ -8,7 +8,7 @@ import { defaults } from 'lodash'; import { DataViewsService, DataView } from '.'; -import { fieldFormatsMock } from '../../../../field_formats/common/mocks'; +import { fieldFormatsMock } from '../../../field_formats/common/mocks'; import { UiSettingsCommon, SavedObjectsClientCommon, SavedObject } from '../types'; import { stubbedSavedObjectIndexPattern } from '../data_view.stub'; diff --git a/src/plugins/data/common/data_views/data_views/data_views.ts b/src/plugins/data_views/common/data_views/data_views.ts similarity index 96% rename from src/plugins/data/common/data_views/data_views/data_views.ts rename to src/plugins/data_views/common/data_views/data_views.ts index f9b193d154770..77ce1caaaad84 100644 --- a/src/plugins/data/common/data_views/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { PublicMethodsOf } from '@kbn/utility-types'; import { castEsToKbnFieldTypeName } from '@kbn/field-types'; -import { DATA_VIEW_SAVED_OBJECT_TYPE, SavedObjectsClientCommon } from '../..'; +import { DATA_VIEW_SAVED_OBJECT_TYPE, SavedObjectsClientCommon } from '..'; import { createDataViewCache } from '.'; import type { RuntimeField } from '../types'; @@ -30,9 +30,9 @@ import { DataViewFieldMap, TypeMeta, } from '../types'; -import { FieldFormatsStartCommon, FORMATS_UI_SETTINGS } from '../../../../field_formats/common/'; -import { UI_SETTINGS, SavedObject } from '../../../common'; -import { SavedObjectNotFound } from '../../../../kibana_utils/common'; +import { FieldFormatsStartCommon, FORMATS_UI_SETTINGS } from '../../../field_formats/common/'; +import { META_FIELDS, SavedObject } from '../../common'; +import { SavedObjectNotFound } from '../../../kibana_utils/common'; import { DataViewMissingIndices } from '../lib'; import { findByTitle } from '../utils'; import { DuplicateDataViewError } from '../errors'; @@ -244,7 +244,7 @@ export class DataViewsService { * @returns FieldSpec[] */ getFieldsForWildcard = async (options: GetFieldsOptions) => { - const metaFields = await this.config.get(UI_SETTINGS.META_FIELDS); + const metaFields = await this.config.get(META_FIELDS); return this.apiClient.getFieldsForWildcard({ pattern: options.pattern, metaFields, @@ -290,7 +290,7 @@ export class DataViewsService { } this.onError(err, { - title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { + title: i18n.translate('dataViews.fetchFieldErrorTitle', { defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})', values: { id: indexPattern.id, title: indexPattern.title }, }), @@ -336,7 +336,7 @@ export class DataViewsService { } this.onError(err, { - title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { + title: i18n.translate('dataViews.fetchFieldErrorTitle', { defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})', values: { id, title }, }), @@ -445,7 +445,7 @@ export class DataViewsService { spec.title as string, { pattern: title as string, - metaFields: await this.config.get(UI_SETTINGS.META_FIELDS), + metaFields: await this.config.get(META_FIELDS), type, rollupIndex: typeMeta?.params?.rollup_index, allowNoIndex: spec.allowNoIndex, @@ -478,7 +478,7 @@ export class DataViewsService { }); } else { this.onError(err, { - title: i18n.translate('data.indexPatterns.fetchFieldErrorTitle', { + title: i18n.translate('dataViews.fetchFieldErrorTitle', { defaultMessage: 'Error fetching fields for index pattern {title} (ID: {id})', values: { id: savedObject.id, title }, }), @@ -520,7 +520,7 @@ export class DataViewsService { */ async create(spec: DataViewSpec, skipFetchFields = false): Promise { const shortDotsEnable = await this.config.get(FORMATS_UI_SETTINGS.SHORT_DOTS_ENABLE); - const metaFields = await this.config.get(UI_SETTINGS.META_FIELDS); + const metaFields = await this.config.get(META_FIELDS); const indexPattern = new DataView({ spec, @@ -648,7 +648,7 @@ export class DataViewsService { if (ignoreErrors) { return; } - const title = i18n.translate('data.indexPatterns.unableWriteLabel', { + const title = i18n.translate('dataViews.unableWriteLabel', { defaultMessage: 'Unable to write index pattern! Refresh the page to get the most up to date changes for this index pattern.', }); diff --git a/src/plugins/data/common/data_views/data_views/ensure_default_data_view.ts b/src/plugins/data_views/common/data_views/ensure_default_data_view.ts similarity index 100% rename from src/plugins/data/common/data_views/data_views/ensure_default_data_view.ts rename to src/plugins/data_views/common/data_views/ensure_default_data_view.ts diff --git a/src/plugins/data/common/data_views/data_views/flatten_hit.test.ts b/src/plugins/data_views/common/data_views/flatten_hit.test.ts similarity index 96% rename from src/plugins/data/common/data_views/data_views/flatten_hit.test.ts rename to src/plugins/data_views/common/data_views/flatten_hit.test.ts index 73232a65b6b72..0946f30b85e39 100644 --- a/src/plugins/data/common/data_views/data_views/flatten_hit.test.ts +++ b/src/plugins/data_views/common/data_views/flatten_hit.test.ts @@ -8,7 +8,7 @@ import { DataView } from './data_view'; -import { fieldFormatsMock } from '../../../../field_formats/common/mocks'; +import { fieldFormatsMock } from '../../../field_formats/common/mocks'; import { flattenHitWrapper } from './flatten_hit'; import { stubbedSavedObjectIndexPattern } from '../data_view.stub'; diff --git a/src/plugins/data/common/data_views/data_views/flatten_hit.ts b/src/plugins/data_views/common/data_views/flatten_hit.ts similarity index 100% rename from src/plugins/data/common/data_views/data_views/flatten_hit.ts rename to src/plugins/data_views/common/data_views/flatten_hit.ts diff --git a/src/plugins/data/common/data_views/data_views/format_hit.ts b/src/plugins/data_views/common/data_views/format_hit.ts similarity index 97% rename from src/plugins/data/common/data_views/data_views/format_hit.ts rename to src/plugins/data_views/common/data_views/format_hit.ts index 39f7fef564eb0..30daf7768c4dc 100644 --- a/src/plugins/data/common/data_views/data_views/format_hit.ts +++ b/src/plugins/data_views/common/data_views/format_hit.ts @@ -8,7 +8,7 @@ import _ from 'lodash'; import { DataView } from './data_view'; -import { FieldFormatsContentType } from '../../../../field_formats/common'; +import { FieldFormatsContentType } from '../../../field_formats/common'; const formattedCache = new WeakMap(); const partialFormattedCache = new WeakMap(); diff --git a/src/plugins/data/common/data_views/data_views/index.ts b/src/plugins/data_views/common/data_views/index.ts similarity index 100% rename from src/plugins/data/common/data_views/data_views/index.ts rename to src/plugins/data_views/common/data_views/index.ts diff --git a/src/plugins/data/common/data_views/errors/data_view_saved_object_conflict.ts b/src/plugins/data_views/common/errors/data_view_saved_object_conflict.ts similarity index 100% rename from src/plugins/data/common/data_views/errors/data_view_saved_object_conflict.ts rename to src/plugins/data_views/common/errors/data_view_saved_object_conflict.ts diff --git a/src/plugins/data/common/data_views/errors/duplicate_index_pattern.ts b/src/plugins/data_views/common/errors/duplicate_index_pattern.ts similarity index 100% rename from src/plugins/data/common/data_views/errors/duplicate_index_pattern.ts rename to src/plugins/data_views/common/errors/duplicate_index_pattern.ts diff --git a/src/plugins/data/common/data_views/errors/index.ts b/src/plugins/data_views/common/errors/index.ts similarity index 100% rename from src/plugins/data/common/data_views/errors/index.ts rename to src/plugins/data_views/common/errors/index.ts diff --git a/src/plugins/data/common/data_views/expressions/index.ts b/src/plugins/data_views/common/expressions/index.ts similarity index 100% rename from src/plugins/data/common/data_views/expressions/index.ts rename to src/plugins/data_views/common/expressions/index.ts diff --git a/src/plugins/data/common/data_views/expressions/load_index_pattern.ts b/src/plugins/data_views/common/expressions/load_index_pattern.ts similarity index 90% rename from src/plugins/data/common/data_views/expressions/load_index_pattern.ts rename to src/plugins/data_views/common/expressions/load_index_pattern.ts index dd47a9fc0dfb4..ca0c1090ceea8 100644 --- a/src/plugins/data/common/data_views/expressions/load_index_pattern.ts +++ b/src/plugins/data_views/common/expressions/load_index_pattern.ts @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { DataViewsContract } from '../data_views'; import { DataViewSpec } from '..'; -import { SavedObjectReference } from '../../../../../core/types'; +import { SavedObjectReference } from '../../../../core/types'; const name = 'indexPatternLoad'; const type = 'index_pattern'; @@ -46,14 +46,14 @@ export const getIndexPatternLoadMeta = (): Omit< name, type, inputTypes: ['null'], - help: i18n.translate('data.functions.indexPatternLoad.help', { + help: i18n.translate('dataViews.indexPatternLoad.help', { defaultMessage: 'Loads an index pattern', }), args: { id: { types: ['string'], required: true, - help: i18n.translate('data.functions.indexPatternLoad.id.help', { + help: i18n.translate('dataViews.functions.indexPatternLoad.id.help', { defaultMessage: 'index pattern id to load', }), }, diff --git a/src/plugins/data/common/data_views/field.stub.ts b/src/plugins/data_views/common/field.stub.ts similarity index 100% rename from src/plugins/data/common/data_views/field.stub.ts rename to src/plugins/data_views/common/field.stub.ts diff --git a/src/plugins/data/common/data_views/fields/__snapshots__/data_view_field.test.ts.snap b/src/plugins/data_views/common/fields/__snapshots__/data_view_field.test.ts.snap similarity index 100% rename from src/plugins/data/common/data_views/fields/__snapshots__/data_view_field.test.ts.snap rename to src/plugins/data_views/common/fields/__snapshots__/data_view_field.test.ts.snap diff --git a/src/plugins/data/common/data_views/fields/data_view_field.test.ts b/src/plugins/data_views/common/fields/data_view_field.test.ts similarity index 97% rename from src/plugins/data/common/data_views/fields/data_view_field.test.ts rename to src/plugins/data_views/common/fields/data_view_field.test.ts index 9107036c15c1a..9c611354683c2 100644 --- a/src/plugins/data/common/data_views/fields/data_view_field.test.ts +++ b/src/plugins/data_views/common/fields/data_view_field.test.ts @@ -8,9 +8,9 @@ import { IndexPatternField } from './data_view_field'; import { IndexPattern } from '..'; -import { KBN_FIELD_TYPES } from '../../../common'; +import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { FieldSpec, RuntimeField } from '../types'; -import { FieldFormat } from '../../../../field_formats/common'; +import { FieldFormat } from '../../../field_formats/common'; describe('Field', function () { function flatten(obj: Record) { diff --git a/src/plugins/data/common/data_views/fields/data_view_field.ts b/src/plugins/data_views/common/fields/data_view_field.ts similarity index 97% rename from src/plugins/data/common/data_views/fields/data_view_field.ts rename to src/plugins/data_views/common/fields/data_view_field.ts index fae0e14b95c05..3ad92a3a7e53d 100644 --- a/src/plugins/data/common/data_views/fields/data_view_field.ts +++ b/src/plugins/data_views/common/fields/data_view_field.ts @@ -9,11 +9,11 @@ /* eslint-disable max-classes-per-file */ import { KbnFieldType, getKbnFieldType, castEsToKbnFieldTypeName } from '@kbn/field-types'; +import { KBN_FIELD_TYPES } from '@kbn/field-types'; import type { RuntimeField } from '../types'; -import { KBN_FIELD_TYPES } from '../../kbn_field_types/types'; import type { IFieldType } from './types'; -import { FieldSpec, DataView } from '../..'; -import { shortenDottedString } from '../../utils'; +import { FieldSpec, DataView } from '..'; +import { shortenDottedString } from './utils'; /** @public */ export class DataViewField implements IFieldType { diff --git a/src/plugins/data/common/data_views/fields/field_list.ts b/src/plugins/data_views/common/fields/field_list.ts similarity index 100% rename from src/plugins/data/common/data_views/fields/field_list.ts rename to src/plugins/data_views/common/fields/field_list.ts diff --git a/src/plugins/data/common/data_views/fields/fields.mocks.ts b/src/plugins/data_views/common/fields/fields.mocks.ts similarity index 100% rename from src/plugins/data/common/data_views/fields/fields.mocks.ts rename to src/plugins/data_views/common/fields/fields.mocks.ts diff --git a/src/plugins/data/common/data_views/fields/index.ts b/src/plugins/data_views/common/fields/index.ts similarity index 100% rename from src/plugins/data/common/data_views/fields/index.ts rename to src/plugins/data_views/common/fields/index.ts diff --git a/src/plugins/data/common/data_views/fields/types.ts b/src/plugins/data_views/common/fields/types.ts similarity index 95% rename from src/plugins/data/common/data_views/fields/types.ts rename to src/plugins/data_views/common/fields/types.ts index 2c5934a8e7b3f..2bd1cf5834548 100644 --- a/src/plugins/data/common/data_views/fields/types.ts +++ b/src/plugins/data_views/common/fields/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ import { DataViewFieldBase } from '@kbn/es-query'; -import { FieldSpec, DataView } from '../..'; +import { FieldSpec, DataView } from '..'; /** * @deprecated Use {@link IndexPatternField} diff --git a/src/plugins/data/common/utils/shorten_dotted_string.test.ts b/src/plugins/data_views/common/fields/utils.test.ts similarity index 92% rename from src/plugins/data/common/utils/shorten_dotted_string.test.ts rename to src/plugins/data_views/common/fields/utils.test.ts index 33a44925982ec..0f2ff280eb61b 100644 --- a/src/plugins/data/common/utils/shorten_dotted_string.test.ts +++ b/src/plugins/data_views/common/fields/utils.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { shortenDottedString } from './shorten_dotted_string'; +import { shortenDottedString } from './utils'; describe('shortenDottedString', () => { test('should convert a dot.notated.string into a short string', () => { diff --git a/src/plugins/data/common/data_views/fields/utils.ts b/src/plugins/data_views/common/fields/utils.ts similarity index 75% rename from src/plugins/data/common/data_views/fields/utils.ts rename to src/plugins/data_views/common/fields/utils.ts index 9e05bebc746f0..8344a32d78556 100644 --- a/src/plugins/data/common/data_views/fields/utils.ts +++ b/src/plugins/data_views/common/fields/utils.ts @@ -22,3 +22,15 @@ export function isFilterable(field: IFieldType): boolean { export function isNestedField(field: IFieldType): boolean { return !!field.subType?.nested; } + +const DOT_PREFIX_RE = /(.).+?\./g; + +/** + * Convert a dot.notated.string into a short + * version (d.n.string) + * + * @return {any} + */ +export function shortenDottedString(input: any) { + return typeof input !== 'string' ? input : input.replace(DOT_PREFIX_RE, '$1.'); +} diff --git a/src/plugins/data_views/common/index.ts b/src/plugins/data_views/common/index.ts new file mode 100644 index 0000000000000..e8b36ab3e8fc1 --- /dev/null +++ b/src/plugins/data_views/common/index.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { + RUNTIME_FIELD_TYPES, + FLEET_ASSETS_TO_IGNORE, + META_FIELDS, + DATA_VIEW_SAVED_OBJECT_TYPE, + INDEX_PATTERN_SAVED_OBJECT_TYPE, +} from './constants'; +export type { IFieldType, IIndexPatternFieldList } from './fields'; +export { isFilterable, isNestedField, fieldList, DataViewField, IndexPatternField } from './fields'; +export type { + FieldFormatMap, + RuntimeType, + RuntimeField, + IIndexPattern, + DataViewAttributes, + IndexPatternAttributes, + FieldAttrs, + FieldAttrSet, + OnNotification, + OnError, + UiSettingsCommon, + SavedObjectsClientCommonFindArgs, + SavedObjectsClientCommon, + GetFieldsOptions, + GetFieldsOptionsTimePattern, + IDataViewsApiClient, + IIndexPatternsApiClient, + SavedObject, + AggregationRestrictions, + TypeMeta, + FieldSpecConflictDescriptions, + FieldSpecExportFmt, + FieldSpec, + DataViewFieldMap, + IndexPatternFieldMap, + DataViewSpec, + IndexPatternSpec, + SourceFilter, +} from './types'; +export { DataViewType, IndexPatternType } from './types'; +export { + IndexPatternsService, + IndexPatternsContract, + DataViewsService, + DataViewsContract, +} from './data_views'; +export { IndexPattern, IndexPatternListItem, DataView, DataViewListItem } from './data_views'; +export { DuplicateDataViewError, DataViewSavedObjectConflictError } from './errors'; +export type { + IndexPatternExpressionType, + IndexPatternLoadStartDependencies, + IndexPatternLoadExpressionFunctionDefinition, +} from './expressions'; +export { getIndexPatternLoadMeta } from './expressions'; diff --git a/src/plugins/data/common/data_views/lib/errors.ts b/src/plugins/data_views/common/lib/errors.ts similarity index 93% rename from src/plugins/data/common/data_views/lib/errors.ts rename to src/plugins/data_views/common/lib/errors.ts index 83cc7ea56d020..f8422a6e5dd0d 100644 --- a/src/plugins/data/common/data_views/lib/errors.ts +++ b/src/plugins/data_views/common/lib/errors.ts @@ -8,7 +8,7 @@ /* eslint-disable */ -import { KbnError } from '../../../../kibana_utils/common/'; +import { KbnError } from '../../../kibana_utils/common'; /** * Tried to call a method that relies on SearchSource having an indexPattern assigned diff --git a/src/plugins/data/common/data_views/lib/get_title.ts b/src/plugins/data_views/common/lib/get_title.ts similarity index 85% rename from src/plugins/data/common/data_views/lib/get_title.ts rename to src/plugins/data_views/common/lib/get_title.ts index 94185eae46893..69471583f139c 100644 --- a/src/plugins/data/common/data_views/lib/get_title.ts +++ b/src/plugins/data_views/common/lib/get_title.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { SavedObjectsClientContract } from '../../../../../core/public'; -import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../../constants'; +import { SavedObjectsClientContract } from '../../../../core/public'; +import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../constants'; import { DataViewAttributes } from '../types'; export async function getTitle( diff --git a/src/plugins/data/common/data_views/lib/index.ts b/src/plugins/data_views/common/lib/index.ts similarity index 100% rename from src/plugins/data/common/data_views/lib/index.ts rename to src/plugins/data_views/common/lib/index.ts diff --git a/src/plugins/data/common/data_views/lib/types.ts b/src/plugins/data_views/common/lib/types.ts similarity index 100% rename from src/plugins/data/common/data_views/lib/types.ts rename to src/plugins/data_views/common/lib/types.ts diff --git a/src/plugins/data/common/data_views/lib/validate_data_view.test.ts b/src/plugins/data_views/common/lib/validate_data_view.test.ts similarity index 100% rename from src/plugins/data/common/data_views/lib/validate_data_view.test.ts rename to src/plugins/data_views/common/lib/validate_data_view.test.ts diff --git a/src/plugins/data/common/data_views/lib/validate_data_view.ts b/src/plugins/data_views/common/lib/validate_data_view.ts similarity index 100% rename from src/plugins/data/common/data_views/lib/validate_data_view.ts rename to src/plugins/data_views/common/lib/validate_data_view.ts diff --git a/src/plugins/data/common/data_views/mocks.ts b/src/plugins/data_views/common/mocks.ts similarity index 100% rename from src/plugins/data/common/data_views/mocks.ts rename to src/plugins/data_views/common/mocks.ts diff --git a/src/plugins/data_views/common/stubs.ts b/src/plugins/data_views/common/stubs.ts new file mode 100644 index 0000000000000..c6895da9bfb3a --- /dev/null +++ b/src/plugins/data_views/common/stubs.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './field.stub'; +export * from './data_views/data_view.stub'; diff --git a/src/plugins/data/common/data_views/types.ts b/src/plugins/data_views/common/types.ts similarity index 96% rename from src/plugins/data/common/data_views/types.ts rename to src/plugins/data_views/common/types.ts index 85fe98fbcfeb7..2b184bc1ef2a4 100644 --- a/src/plugins/data/common/data_views/types.ts +++ b/src/plugins/data_views/common/types.ts @@ -10,11 +10,12 @@ import type { DataViewFieldBase, IFieldSubType, DataViewBase } from '@kbn/es-que import { ToastInputFields, ErrorToastOptions } from 'src/core/public/notifications'; // eslint-disable-next-line import type { SavedObject } from 'src/core/server'; +import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { IFieldType } from './fields'; import { RUNTIME_FIELD_TYPES } from './constants'; -import { SerializedFieldFormat } from '../../../expressions/common'; -import { KBN_FIELD_TYPES, DataViewField } from '..'; -import { FieldFormat } from '../../../field_formats/common'; +import { SerializedFieldFormat } from '../../expressions/common'; +import { DataViewField } from './fields'; +import { FieldFormat } from '../../field_formats/common'; export type FieldFormatMap = Record; diff --git a/src/plugins/data/common/data_views/utils.test.ts b/src/plugins/data_views/common/utils.test.ts similarity index 100% rename from src/plugins/data/common/data_views/utils.test.ts rename to src/plugins/data_views/common/utils.test.ts diff --git a/src/plugins/data/common/data_views/utils.ts b/src/plugins/data_views/common/utils.ts similarity index 89% rename from src/plugins/data/common/data_views/utils.ts rename to src/plugins/data_views/common/utils.ts index 2d36ab6c72225..77e9bd76b869c 100644 --- a/src/plugins/data/common/data_views/utils.ts +++ b/src/plugins/data_views/common/utils.ts @@ -7,9 +7,9 @@ */ import type { IndexPatternSavedObjectAttrs } from './data_views'; -import type { SavedObjectsClientCommon } from '../types'; +import type { SavedObjectsClientCommon } from './types'; -import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../constants'; +import { DATA_VIEW_SAVED_OBJECT_TYPE } from './constants'; /** * Returns an object matching a given title diff --git a/src/plugins/data_views/jest.config.js b/src/plugins/data_views/jest.config.js new file mode 100644 index 0000000000000..4c1f067835630 --- /dev/null +++ b/src/plugins/data_views/jest.config.js @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/src/plugins/data_views'], + coverageDirectory: '/target/kibana-coverage/jest/src/plugins/data_views', + coverageReporters: ['text', 'html'], + collectCoverageFrom: ['/src/plugins/data_views/{common,public,server}/**/*.{ts,tsx}'], +}; diff --git a/src/plugins/data_views/kibana.json b/src/plugins/data_views/kibana.json new file mode 100644 index 0000000000000..27bf536ef8040 --- /dev/null +++ b/src/plugins/data_views/kibana.json @@ -0,0 +1,15 @@ +{ + "id": "dataViews", + "version": "kibana", + "server": true, + "ui": true, + "requiredPlugins": ["fieldFormats","expressions"], + "optionalPlugins": ["usageCollection"], + "extraPublicDirs": ["common"], + "requiredBundles": ["kibanaUtils","kibanaReact"], + "owner": { + "name": "App Services", + "githubTeam": "kibana-app-services" + }, + "description": "Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters." +} diff --git a/src/plugins/data/public/data_views/data_views/data_view.stub.ts b/src/plugins/data_views/public/data_views/data_view.stub.ts similarity index 84% rename from src/plugins/data/public/data_views/data_views/data_view.stub.ts rename to src/plugins/data_views/public/data_views/data_view.stub.ts index b3d8448064c65..f37a8a78b234b 100644 --- a/src/plugins/data/public/data_views/data_views/data_view.stub.ts +++ b/src/plugins/data_views/public/data_views/data_view.stub.ts @@ -7,11 +7,11 @@ */ import { CoreSetup } from 'kibana/public'; -import { FieldFormatsStartCommon } from '../../../../field_formats/common'; -import { getFieldFormatsRegistry } from '../../../../field_formats/public/mocks'; -import * as commonStubs from '../../../common/stubs'; -import { DataView, DataViewSpec } from '../../../common'; -import { coreMock } from '../../../../../core/public/mocks'; +import { FieldFormatsStartCommon } from '../../../field_formats/common'; +import { getFieldFormatsRegistry } from '../../../field_formats/public/mocks'; +import * as commonStubs from '../../common/stubs'; +import { DataView, DataViewSpec } from '../../common'; +import { coreMock } from '../../../../core/public/mocks'; /** * Create a custom stub index pattern. Use it in your unit tests where an {@link DataView} expected. * @param spec - Serialized index pattern object diff --git a/src/plugins/data/public/data_views/data_views/data_views_api_client.test.mock.ts b/src/plugins/data_views/public/data_views/data_views_api_client.test.mock.ts similarity index 86% rename from src/plugins/data/public/data_views/data_views/data_views_api_client.test.mock.ts rename to src/plugins/data_views/public/data_views/data_views_api_client.test.mock.ts index c53ca7ad89aa9..2fd17b98f7498 100644 --- a/src/plugins/data/public/data_views/data_views/data_views_api_client.test.mock.ts +++ b/src/plugins/data_views/public/data_views/data_views_api_client.test.mock.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { setup } from '../../../../../core/test_helpers/http_test_setup'; +import { setup } from '../../../../core/test_helpers/http_test_setup'; export const { http } = setup((injectedMetadata) => { injectedMetadata.getBasePath.mockReturnValue('/hola/daro/'); diff --git a/src/plugins/data/public/data_views/data_views/data_views_api_client.test.ts b/src/plugins/data_views/public/data_views/data_views_api_client.test.ts similarity index 100% rename from src/plugins/data/public/data_views/data_views/data_views_api_client.test.ts rename to src/plugins/data_views/public/data_views/data_views_api_client.test.ts diff --git a/src/plugins/data/public/data_views/data_views/data_views_api_client.ts b/src/plugins/data_views/public/data_views/data_views_api_client.ts similarity index 90% rename from src/plugins/data/public/data_views/data_views/data_views_api_client.ts rename to src/plugins/data_views/public/data_views/data_views_api_client.ts index d11ec7cfa003d..d4da9a55c25d1 100644 --- a/src/plugins/data/public/data_views/data_views/data_views_api_client.ts +++ b/src/plugins/data_views/public/data_views/data_views_api_client.ts @@ -7,12 +7,8 @@ */ import { HttpSetup } from 'src/core/public'; -import { DataViewMissingIndices } from '../../../common/data_views/lib'; -import { - GetFieldsOptions, - IDataViewsApiClient, - GetFieldsOptionsTimePattern, -} from '../../../common/data_views/types'; +import { DataViewMissingIndices } from '../../common/lib'; +import { GetFieldsOptions, IDataViewsApiClient, GetFieldsOptionsTimePattern } from '../../common'; const API_BASE_URL: string = `/api/index_patterns/`; diff --git a/src/plugins/data/public/data_views/data_views/index.ts b/src/plugins/data_views/public/data_views/index.ts similarity index 88% rename from src/plugins/data/public/data_views/data_views/index.ts rename to src/plugins/data_views/public/data_views/index.ts index e0d18d47f39db..e476d62774f17 100644 --- a/src/plugins/data/public/data_views/data_views/index.ts +++ b/src/plugins/data_views/public/data_views/index.ts @@ -6,6 +6,6 @@ * Side Public License, v 1. */ -export * from '../../../common/data_views/data_views'; +export * from '../../common/data_views'; export * from './redirect_no_index_pattern'; export * from './data_views_api_client'; diff --git a/src/plugins/data/public/data_views/data_views/redirect_no_index_pattern.tsx b/src/plugins/data_views/public/data_views/redirect_no_index_pattern.tsx similarity index 84% rename from src/plugins/data/public/data_views/data_views/redirect_no_index_pattern.tsx rename to src/plugins/data_views/public/data_views/redirect_no_index_pattern.tsx index 88e18060c4d11..456af90a3c6dd 100644 --- a/src/plugins/data/public/data_views/data_views/redirect_no_index_pattern.tsx +++ b/src/plugins/data_views/public/data_views/redirect_no_index_pattern.tsx @@ -10,7 +10,7 @@ import { EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { CoreStart } from 'kibana/public'; -import { toMountPoint } from '../../../../kibana_react/public'; +import { toMountPoint } from '../../../kibana_react/public'; let bannerId: string; @@ -29,13 +29,10 @@ export const onRedirectNoIndexPattern = clearTimeout(timeoutId); } - const bannerMessage = i18n.translate( - 'data.indexPatterns.ensureDefaultIndexPattern.bannerLabel', - { - defaultMessage: - 'To visualize and explore data in Kibana, you must create an index pattern to retrieve data from Elasticsearch.', - } - ); + const bannerMessage = i18n.translate('dataViews.ensureDefaultIndexPattern.bannerLabel', { + defaultMessage: + 'To visualize and explore data in Kibana, you must create an index pattern to retrieve data from Elasticsearch.', + }); // Avoid being hostile to new users who don't have an index pattern setup yet // give them a friendly info message instead of a terse error message diff --git a/src/plugins/data/public/data_views/expressions/index.ts b/src/plugins/data_views/public/expressions/index.ts similarity index 100% rename from src/plugins/data/public/data_views/expressions/index.ts rename to src/plugins/data_views/public/expressions/index.ts diff --git a/src/plugins/data/public/data_views/expressions/load_index_pattern.test.ts b/src/plugins/data_views/public/expressions/load_index_pattern.test.ts similarity index 92% rename from src/plugins/data/public/data_views/expressions/load_index_pattern.test.ts rename to src/plugins/data_views/public/expressions/load_index_pattern.test.ts index befa78c398984..02a530712e80a 100644 --- a/src/plugins/data/public/data_views/expressions/load_index_pattern.test.ts +++ b/src/plugins/data_views/public/expressions/load_index_pattern.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { IndexPatternLoadStartDependencies } from '../../../common/data_views/expressions'; +import { IndexPatternLoadStartDependencies } from '../../common/expressions'; import { getFunctionDefinition } from './load_index_pattern'; describe('indexPattern expression function', () => { diff --git a/src/plugins/data/public/data_views/expressions/load_index_pattern.ts b/src/plugins/data_views/public/expressions/load_index_pattern.ts similarity index 88% rename from src/plugins/data/public/data_views/expressions/load_index_pattern.ts rename to src/plugins/data_views/public/expressions/load_index_pattern.ts index 979861c7da38e..76119f3e50a45 100644 --- a/src/plugins/data/public/data_views/expressions/load_index_pattern.ts +++ b/src/plugins/data_views/public/expressions/load_index_pattern.ts @@ -11,8 +11,8 @@ import { getIndexPatternLoadMeta, IndexPatternLoadExpressionFunctionDefinition, IndexPatternLoadStartDependencies, -} from '../../../common/data_views/expressions'; -import { DataPublicPluginStart, DataStartDependencies } from '../../types'; +} from '../../common/expressions'; +import { DataViewsPublicPluginStart, DataViewsPublicStartDependencies } from '../types'; /** * Returns the expression function definition. Any stateful dependencies are accessed @@ -60,11 +60,14 @@ export function getFunctionDefinition({ export function getIndexPatternLoad({ getStartServices, }: { - getStartServices: StartServicesAccessor; + getStartServices: StartServicesAccessor< + DataViewsPublicStartDependencies, + DataViewsPublicPluginStart + >; }) { return getFunctionDefinition({ getStartDependencies: async () => { - const [, , { indexPatterns }] = await getStartServices(); + const [, , indexPatterns] = await getStartServices(); return { indexPatterns }; }, }); diff --git a/src/plugins/data_views/public/index.ts b/src/plugins/data_views/public/index.ts new file mode 100644 index 0000000000000..572806df11fa3 --- /dev/null +++ b/src/plugins/data_views/public/index.ts @@ -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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { + ILLEGAL_CHARACTERS_KEY, + CONTAINS_SPACES_KEY, + ILLEGAL_CHARACTERS_VISIBLE, + ILLEGAL_CHARACTERS, + validateDataView, +} from '../common/lib'; +export { flattenHitWrapper, formatHitProvider, onRedirectNoIndexPattern } from './data_views'; + +export { IndexPatternField, IIndexPatternFieldList, TypeMeta } from '../common'; + +export { + IndexPatternsService, + IndexPatternsContract, + IndexPattern, + DataViewsApiClient, + DataViewsService, + DataViewsContract, + DataView, +} from './data_views'; +export { UiSettingsPublicToCommon } from './ui_settings_wrapper'; +export { SavedObjectsClientPublicToCommon } from './saved_objects_client_wrapper'; + +/* + * Plugin setup + */ + +import { DataViewsPublicPlugin } from './plugin'; + +export function plugin() { + return new DataViewsPublicPlugin(); +} + +export type { DataViewsPublicPluginSetup, DataViewsPublicPluginStart } from './types'; + +// Export plugin after all other imports +export type { DataViewsPublicPlugin as DataPlugin }; diff --git a/src/plugins/data_views/public/plugin.ts b/src/plugins/data_views/public/plugin.ts new file mode 100644 index 0000000000000..58f66623b64ab --- /dev/null +++ b/src/plugins/data_views/public/plugin.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import { getIndexPatternLoad } from './expressions'; +import { + DataViewsPublicPluginSetup, + DataViewsPublicPluginStart, + DataViewsPublicSetupDependencies, + DataViewsPublicStartDependencies, +} from './types'; + +import { + DataViewsService, + onRedirectNoIndexPattern, + DataViewsApiClient, + UiSettingsPublicToCommon, + SavedObjectsClientPublicToCommon, +} from '.'; + +export class DataViewsPublicPlugin + implements + Plugin< + DataViewsPublicPluginSetup, + DataViewsPublicPluginStart, + DataViewsPublicSetupDependencies, + DataViewsPublicStartDependencies + > +{ + public setup( + core: CoreSetup, + { expressions }: DataViewsPublicSetupDependencies + ): DataViewsPublicPluginSetup { + expressions.registerFunction(getIndexPatternLoad({ getStartServices: core.getStartServices })); + + return {}; + } + + public start( + core: CoreStart, + { fieldFormats }: DataViewsPublicStartDependencies + ): DataViewsPublicPluginStart { + const { uiSettings, http, notifications, savedObjects, overlays, application } = core; + + return new DataViewsService({ + uiSettings: new UiSettingsPublicToCommon(uiSettings), + savedObjectsClient: new SavedObjectsClientPublicToCommon(savedObjects.client), + apiClient: new DataViewsApiClient(http), + fieldFormats, + onNotification: (toastInputFields) => { + notifications.toasts.add(toastInputFields); + }, + onError: notifications.toasts.addError.bind(notifications.toasts), + onRedirectNoIndexPattern: onRedirectNoIndexPattern( + application.capabilities, + application.navigateToApp, + overlays + ), + }); + } + + public stop() {} +} diff --git a/src/plugins/data/public/data_views/saved_objects_client_wrapper.test.ts b/src/plugins/data_views/public/saved_objects_client_wrapper.test.ts similarity index 96% rename from src/plugins/data/public/data_views/saved_objects_client_wrapper.test.ts rename to src/plugins/data_views/public/saved_objects_client_wrapper.test.ts index 221a18ac7fab7..124a66eba57f2 100644 --- a/src/plugins/data/public/data_views/saved_objects_client_wrapper.test.ts +++ b/src/plugins/data_views/public/saved_objects_client_wrapper.test.ts @@ -9,7 +9,7 @@ import { SavedObjectsClientPublicToCommon } from './saved_objects_client_wrapper'; import { savedObjectsServiceMock } from 'src/core/public/mocks'; -import { DataViewSavedObjectConflictError } from '../../common/data_views'; +import { DataViewSavedObjectConflictError } from '../common'; describe('SavedObjectsClientPublicToCommon', () => { const soClient = savedObjectsServiceMock.createStartContract().client; diff --git a/src/plugins/data/public/data_views/saved_objects_client_wrapper.ts b/src/plugins/data_views/public/saved_objects_client_wrapper.ts similarity index 98% rename from src/plugins/data/public/data_views/saved_objects_client_wrapper.ts rename to src/plugins/data_views/public/saved_objects_client_wrapper.ts index 1db4e3b1ccd24..beaae6ac3fc21 100644 --- a/src/plugins/data/public/data_views/saved_objects_client_wrapper.ts +++ b/src/plugins/data_views/public/saved_objects_client_wrapper.ts @@ -13,7 +13,7 @@ import { SavedObjectsClientCommonFindArgs, SavedObject, DataViewSavedObjectConflictError, -} from '../../common/data_views'; +} from '../common'; type SOClient = Pick; diff --git a/src/plugins/data_views/public/types.ts b/src/plugins/data_views/public/types.ts new file mode 100644 index 0000000000000..20b1cbaf090fa --- /dev/null +++ b/src/plugins/data_views/public/types.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ExpressionsSetup } from 'src/plugins/expressions/public'; +import { FieldFormatsSetup, FieldFormatsStart } from 'src/plugins/field_formats/public'; +import { PublicMethodsOf } from '@kbn/utility-types'; +import { DataViewsService } from './data_views'; + +export interface DataViewsPublicSetupDependencies { + expressions: ExpressionsSetup; + fieldFormats: FieldFormatsSetup; +} + +export interface DataViewsPublicStartDependencies { + fieldFormats: FieldFormatsStart; +} + +/** + * Data plugin public Setup contract + */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DataViewsPublicPluginSetup {} + +/** + * Data plugin public Start contract + */ +export type DataViewsPublicPluginStart = PublicMethodsOf; diff --git a/src/plugins/data/public/data_views/ui_settings_wrapper.ts b/src/plugins/data_views/public/ui_settings_wrapper.ts similarity index 95% rename from src/plugins/data/public/data_views/ui_settings_wrapper.ts rename to src/plugins/data_views/public/ui_settings_wrapper.ts index f8ae317391fa3..91806867b6730 100644 --- a/src/plugins/data/public/data_views/ui_settings_wrapper.ts +++ b/src/plugins/data_views/public/ui_settings_wrapper.ts @@ -7,7 +7,7 @@ */ import { IUiSettingsClient, PublicUiSettingsParams, UserProvidedValues } from 'src/core/public'; -import { UiSettingsCommon } from '../../common'; +import { UiSettingsCommon } from '../common'; export class UiSettingsPublicToCommon implements UiSettingsCommon { private uiSettings: IUiSettingsClient; diff --git a/src/plugins/data/server/data_views/capabilities_provider.ts b/src/plugins/data_views/server/capabilities_provider.ts similarity index 100% rename from src/plugins/data/server/data_views/capabilities_provider.ts rename to src/plugins/data_views/server/capabilities_provider.ts diff --git a/src/plugins/data_views/server/data_views_service_factory.ts b/src/plugins/data_views/server/data_views_service_factory.ts new file mode 100644 index 0000000000000..2f720cd7388f4 --- /dev/null +++ b/src/plugins/data_views/server/data_views_service_factory.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + Logger, + SavedObjectsClientContract, + ElasticsearchClient, + UiSettingsServiceStart, +} from 'kibana/server'; +import { DataViewsService } from '../common'; +import { FieldFormatsStart } from '../../field_formats/server'; +import { UiSettingsServerToCommon } from './ui_settings_wrapper'; +import { IndexPatternsApiServer } from './index_patterns_api_client'; +import { SavedObjectsClientServerToCommon } from './saved_objects_client_wrapper'; + +export const dataViewsServiceFactory = + ({ + logger, + uiSettings, + fieldFormats, + }: { + logger: Logger; + uiSettings: UiSettingsServiceStart; + fieldFormats: FieldFormatsStart; + }) => + async ( + savedObjectsClient: SavedObjectsClientContract, + elasticsearchClient: ElasticsearchClient + ) => { + const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); + const formats = await fieldFormats.fieldFormatServiceFactory(uiSettingsClient); + + return new DataViewsService({ + uiSettings: new UiSettingsServerToCommon(uiSettingsClient), + savedObjectsClient: new SavedObjectsClientServerToCommon(savedObjectsClient), + apiClient: new IndexPatternsApiServer(elasticsearchClient, savedObjectsClient), + fieldFormats: formats, + onError: (error) => { + logger.error(error); + }, + onNotification: ({ title, text }) => { + logger.warn(`${title}${text ? ` : ${text}` : ''}`); + }, + }); + }; diff --git a/src/plugins/data/server/data_views/deprecations/index.ts b/src/plugins/data_views/server/deprecations/index.ts similarity index 100% rename from src/plugins/data/server/data_views/deprecations/index.ts rename to src/plugins/data_views/server/deprecations/index.ts diff --git a/src/plugins/data/server/data_views/deprecations/scripted_fields.test.ts b/src/plugins/data_views/server/deprecations/scripted_fields.test.ts similarity index 100% rename from src/plugins/data/server/data_views/deprecations/scripted_fields.test.ts rename to src/plugins/data_views/server/deprecations/scripted_fields.test.ts diff --git a/src/plugins/data/server/data_views/deprecations/scripted_fields.ts b/src/plugins/data_views/server/deprecations/scripted_fields.ts similarity index 89% rename from src/plugins/data/server/data_views/deprecations/scripted_fields.ts rename to src/plugins/data_views/server/deprecations/scripted_fields.ts index 65cb962196805..9ee2d64e25cb5 100644 --- a/src/plugins/data/server/data_views/deprecations/scripted_fields.ts +++ b/src/plugins/data_views/server/deprecations/scripted_fields.ts @@ -13,7 +13,7 @@ import { RegisterDeprecationsConfig, } from 'kibana/server'; import { i18n } from '@kbn/i18n'; -import { IndexPatternAttributes } from '../../../common'; +import { IndexPatternAttributes } from '../../common'; type IndexPatternAttributesWithFields = Pick; @@ -41,10 +41,10 @@ export const createScriptedFieldsDeprecationsConfig: ( return [ { - title: i18n.translate('data.deprecations.scriptedFieldsTitle', { + title: i18n.translate('dataViews.deprecations.scriptedFieldsTitle', { defaultMessage: 'Found index patterns using scripted fields', }), - message: i18n.translate('data.deprecations.scriptedFieldsMessage', { + message: i18n.translate('dataViews.deprecations.scriptedFieldsMessage', { defaultMessage: `You have {numberOfIndexPatternsWithScriptedFields} index patterns ({titlesPreview}...) that use scripted fields. Scripted fields are deprecated and will be removed in future. Use runtime fields instead.`, values: { titlesPreview: indexPatternTitles.slice(0, PREVIEW_LIMIT).join('; '), @@ -56,10 +56,10 @@ export const createScriptedFieldsDeprecationsConfig: ( level: 'warning', // warning because it is not set in stone WHEN we remove scripted fields, hence this deprecation is not a blocker for 8.0 upgrade correctiveActions: { manualSteps: [ - i18n.translate('data.deprecations.scriptedFields.manualStepOneMessage', { + i18n.translate('dataViews.deprecations.scriptedFields.manualStepOneMessage', { defaultMessage: 'Navigate to Stack Management > Kibana > Index Patterns.', }), - i18n.translate('data.deprecations.scriptedFields.manualStepTwoMessage', { + i18n.translate('dataViews.deprecations.scriptedFields.manualStepTwoMessage', { defaultMessage: 'Update {numberOfIndexPatternsWithScriptedFields} index patterns that have scripted fields to use runtime fields instead. In most cases, to migrate existing scripts, you will need to change "return ;" to "emit();". Index patterns with at least one scripted field: {allTitles}', values: { diff --git a/src/plugins/data/server/data_views/error.ts b/src/plugins/data_views/server/error.ts similarity index 100% rename from src/plugins/data/server/data_views/error.ts rename to src/plugins/data_views/server/error.ts diff --git a/src/plugins/data/server/data_views/expressions/index.ts b/src/plugins/data_views/server/expressions/index.ts similarity index 100% rename from src/plugins/data/server/data_views/expressions/index.ts rename to src/plugins/data_views/server/expressions/index.ts diff --git a/src/plugins/data/server/data_views/expressions/load_index_pattern.test.ts b/src/plugins/data_views/server/expressions/load_index_pattern.test.ts similarity index 94% rename from src/plugins/data/server/data_views/expressions/load_index_pattern.test.ts rename to src/plugins/data_views/server/expressions/load_index_pattern.test.ts index 370d7dcfd7eba..94bd854e6734c 100644 --- a/src/plugins/data/server/data_views/expressions/load_index_pattern.test.ts +++ b/src/plugins/data_views/server/expressions/load_index_pattern.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { IndexPatternLoadStartDependencies } from '../../../common/data_views/expressions'; +import { IndexPatternLoadStartDependencies } from '../../common/expressions'; import { getFunctionDefinition } from './load_index_pattern'; describe('indexPattern expression function', () => { diff --git a/src/plugins/data/server/data_views/expressions/load_index_pattern.ts b/src/plugins/data_views/server/expressions/load_index_pattern.ts similarity index 85% rename from src/plugins/data/server/data_views/expressions/load_index_pattern.ts rename to src/plugins/data_views/server/expressions/load_index_pattern.ts index 4585101f2812c..8ade41132e144 100644 --- a/src/plugins/data/server/data_views/expressions/load_index_pattern.ts +++ b/src/plugins/data_views/server/expressions/load_index_pattern.ts @@ -13,8 +13,8 @@ import { getIndexPatternLoadMeta, IndexPatternLoadExpressionFunctionDefinition, IndexPatternLoadStartDependencies, -} from '../../../common/data_views/expressions'; -import { DataPluginStartDependencies, DataPluginStart } from '../../plugin'; +} from '../../common/expressions'; +import { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from '../types'; /** * Returns the expression function definition. Any stateful dependencies are accessed @@ -39,7 +39,7 @@ export function getFunctionDefinition({ const kibanaRequest = getKibanaRequest ? getKibanaRequest() : null; if (!kibanaRequest) { throw new Error( - i18n.translate('data.indexPatterns.indexPatternLoad.error.kibanaRequest', { + i18n.translate('dataViews.indexPatternLoad.error.kibanaRequest', { defaultMessage: 'A KibanaRequest is required to execute this search on the server. ' + 'Please provide a request object to the expression execution params.', @@ -73,13 +73,17 @@ export function getFunctionDefinition({ export function getIndexPatternLoad({ getStartServices, }: { - getStartServices: StartServicesAccessor; + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + >; }) { return getFunctionDefinition({ getStartDependencies: async (request: KibanaRequest) => { - const [{ elasticsearch, savedObjects }, , { indexPatterns }] = await getStartServices(); + const [{ elasticsearch, savedObjects }, , { indexPatternsServiceFactory }] = + await getStartServices(); return { - indexPatterns: await indexPatterns.indexPatternsServiceFactory( + indexPatterns: await indexPatternsServiceFactory( savedObjects.getScopedClient(request), elasticsearch.client.asScoped(request).asCurrentUser ), diff --git a/src/plugins/data/server/data_views/fetcher/index.ts b/src/plugins/data_views/server/fetcher/index.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/index.ts rename to src/plugins/data_views/server/fetcher/index.ts diff --git a/src/plugins/data_views/server/fetcher/index_not_found_exception.json b/src/plugins/data_views/server/fetcher/index_not_found_exception.json new file mode 100644 index 0000000000000..dc892d95ae397 --- /dev/null +++ b/src/plugins/data_views/server/fetcher/index_not_found_exception.json @@ -0,0 +1,21 @@ +{ + "error" : { + "root_cause" : [ + { + "type" : "index_not_found_exception", + "reason" : "no such index [poop]", + "resource.type" : "index_or_alias", + "resource.id" : "poop", + "index_uuid" : "_na_", + "index" : "poop" + } + ], + "type" : "index_not_found_exception", + "reason" : "no such index [poop]", + "resource.type" : "index_or_alias", + "resource.id" : "poop", + "index_uuid" : "_na_", + "index" : "poop" + }, + "status" : 404 +} diff --git a/src/plugins/data/server/data_views/fetcher/index_patterns_fetcher.test.ts b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts similarity index 95% rename from src/plugins/data/server/data_views/fetcher/index_patterns_fetcher.test.ts rename to src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts index 4bd21fb3a1820..a65d4d551cf7c 100644 --- a/src/plugins/data/server/data_views/fetcher/index_patterns_fetcher.test.ts +++ b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts @@ -8,7 +8,7 @@ import { IndexPatternsFetcher } from '.'; import { ElasticsearchClient } from 'kibana/server'; -import * as indexNotFoundException from '../../../common/search/test_data/index_not_found_exception.json'; +import * as indexNotFoundException from './index_not_found_exception.json'; describe('Index Pattern Fetcher - server', () => { let indexPatterns: IndexPatternsFetcher; diff --git a/src/plugins/data/server/data_views/fetcher/index_patterns_fetcher.ts b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/index_patterns_fetcher.ts rename to src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/errors.ts b/src/plugins/data_views/server/fetcher/lib/errors.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/errors.ts rename to src/plugins/data_views/server/fetcher/lib/errors.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/es_api.test.js b/src/plugins/data_views/server/fetcher/lib/es_api.test.js similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/es_api.test.js rename to src/plugins/data_views/server/fetcher/lib/es_api.test.js diff --git a/src/plugins/data/server/data_views/fetcher/lib/es_api.ts b/src/plugins/data_views/server/fetcher/lib/es_api.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/es_api.ts rename to src/plugins/data_views/server/fetcher/lib/es_api.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json b/src/plugins/data_views/server/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/__fixtures__/es_field_caps_response.json diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_capabilities.test.js b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_capabilities.test.js rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_capabilities.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_capabilities.ts rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_caps_response.test.js b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.test.js similarity index 99% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_caps_response.test.js rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.test.js index c12eff1b5a377..f1e3f314351de 100644 --- a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_caps_response.test.js +++ b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.test.js @@ -13,7 +13,7 @@ import sinon from 'sinon'; import * as shouldReadFieldFromDocValuesNS from './should_read_field_from_doc_values'; import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values'; -import { getKbnFieldType } from '../../../../../common'; +import { getKbnFieldType } from '@kbn/field-types'; import { readFieldCapsResponse } from './field_caps_response'; import esResponse from './__fixtures__/es_field_caps_response.json'; diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_caps_response.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.ts similarity index 98% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_caps_response.ts rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.ts index 3f83fd71b74e4..6dff343f9e00e 100644 --- a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/field_caps_response.ts +++ b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.ts @@ -8,7 +8,7 @@ import { uniq } from 'lodash'; import type { estypes } from '@elastic/elasticsearch'; -import { castEsToKbnFieldTypeName } from '../../../../../common'; +import { castEsToKbnFieldTypeName } from '@kbn/field-types'; import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values'; import { FieldDescriptor } from '../../../fetcher'; diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/index.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/index.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/index.ts rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/index.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/overrides.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/overrides.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/overrides.ts rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/overrides.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/should_read_field_from_doc_values.test.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/should_read_field_from_doc_values.test.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/should_read_field_from_doc_values.test.ts rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/should_read_field_from_doc_values.test.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts rename to src/plugins/data_views/server/fetcher/lib/field_capabilities/should_read_field_from_doc_values.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/index.ts b/src/plugins/data_views/server/fetcher/lib/index.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/index.ts rename to src/plugins/data_views/server/fetcher/lib/index.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/jobs_compatibility.test.js b/src/plugins/data_views/server/fetcher/lib/jobs_compatibility.test.js similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/jobs_compatibility.test.js rename to src/plugins/data_views/server/fetcher/lib/jobs_compatibility.test.js diff --git a/src/plugins/data/server/data_views/fetcher/lib/jobs_compatibility.ts b/src/plugins/data_views/server/fetcher/lib/jobs_compatibility.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/jobs_compatibility.ts rename to src/plugins/data_views/server/fetcher/lib/jobs_compatibility.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/map_capabilities.ts b/src/plugins/data_views/server/fetcher/lib/map_capabilities.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/map_capabilities.ts rename to src/plugins/data_views/server/fetcher/lib/map_capabilities.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/merge_capabilities_with_fields.ts b/src/plugins/data_views/server/fetcher/lib/merge_capabilities_with_fields.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/merge_capabilities_with_fields.ts rename to src/plugins/data_views/server/fetcher/lib/merge_capabilities_with_fields.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/resolve_time_pattern.test.js b/src/plugins/data_views/server/fetcher/lib/resolve_time_pattern.test.js similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/resolve_time_pattern.test.js rename to src/plugins/data_views/server/fetcher/lib/resolve_time_pattern.test.js diff --git a/src/plugins/data/server/data_views/fetcher/lib/resolve_time_pattern.ts b/src/plugins/data_views/server/fetcher/lib/resolve_time_pattern.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/resolve_time_pattern.ts rename to src/plugins/data_views/server/fetcher/lib/resolve_time_pattern.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/time_pattern_to_wildcard.test.ts b/src/plugins/data_views/server/fetcher/lib/time_pattern_to_wildcard.test.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/time_pattern_to_wildcard.test.ts rename to src/plugins/data_views/server/fetcher/lib/time_pattern_to_wildcard.test.ts diff --git a/src/plugins/data/server/data_views/fetcher/lib/time_pattern_to_wildcard.ts b/src/plugins/data_views/server/fetcher/lib/time_pattern_to_wildcard.ts similarity index 100% rename from src/plugins/data/server/data_views/fetcher/lib/time_pattern_to_wildcard.ts rename to src/plugins/data_views/server/fetcher/lib/time_pattern_to_wildcard.ts diff --git a/src/plugins/data/server/data_views/has_user_index_pattern.test.ts b/src/plugins/data_views/server/has_user_index_pattern.test.ts similarity index 99% rename from src/plugins/data/server/data_views/has_user_index_pattern.test.ts rename to src/plugins/data_views/server/has_user_index_pattern.test.ts index efc149b409375..aeaa64b949dbc 100644 --- a/src/plugins/data/server/data_views/has_user_index_pattern.test.ts +++ b/src/plugins/data_views/server/has_user_index_pattern.test.ts @@ -7,7 +7,7 @@ */ import { hasUserIndexPattern } from './has_user_index_pattern'; -import { elasticsearchServiceMock, savedObjectsClientMock } from '../../../../core/server/mocks'; +import { elasticsearchServiceMock, savedObjectsClientMock } from '../../../core/server/mocks'; describe('hasUserIndexPattern', () => { const esClient = elasticsearchServiceMock.createScopedClusterClient().asCurrentUser; diff --git a/src/plugins/data/server/data_views/has_user_index_pattern.ts b/src/plugins/data_views/server/has_user_index_pattern.ts similarity index 91% rename from src/plugins/data/server/data_views/has_user_index_pattern.ts rename to src/plugins/data_views/server/has_user_index_pattern.ts index 97abd0892b836..6566f75ebc52e 100644 --- a/src/plugins/data/server/data_views/has_user_index_pattern.ts +++ b/src/plugins/data_views/server/has_user_index_pattern.ts @@ -6,9 +6,9 @@ * Side Public License, v 1. */ -import { ElasticsearchClient, SavedObjectsClientContract } from '../../../../core/server'; -import { IndexPatternSavedObjectAttrs } from '../../common/data_views/data_views'; -import { FLEET_ASSETS_TO_IGNORE } from '../../common/data_views/constants'; +import { ElasticsearchClient, SavedObjectsClientContract } from '../../../core/server'; +import { IndexPatternSavedObjectAttrs } from '../common/data_views'; +import { FLEET_ASSETS_TO_IGNORE } from '../common/constants'; interface Deps { esClient: ElasticsearchClient; diff --git a/src/plugins/data_views/server/index.ts b/src/plugins/data_views/server/index.ts new file mode 100644 index 0000000000000..1c7eeb073bbe2 --- /dev/null +++ b/src/plugins/data_views/server/index.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { getFieldByName, findIndexPatternById } from './utils'; +export { + IndexPatternsFetcher, + FieldDescriptor, + shouldReadFieldFromDocValues, + mergeCapabilitiesWithFields, + getCapabilitiesForRollupIndices, +} from './fetcher'; +export { IndexPatternsServiceStart } from './types'; + +import { PluginInitializerContext } from 'src/core/server'; +import { DataViewsServerPlugin } from './plugin'; +import { DataViewsServerPluginSetup, DataViewsServerPluginStart } from './types'; +export type { dataViewsServiceFactory } from './data_views_service_factory'; + +/** + * Static code to be shared externally + * @public + */ + +export function plugin(initializerContext: PluginInitializerContext) { + return new DataViewsServerPlugin(initializerContext); +} + +export { + DataViewsServerPlugin as Plugin, + DataViewsServerPluginSetup as PluginSetup, + DataViewsServerPluginStart as PluginStart, +}; diff --git a/src/plugins/data/server/data_views/index_patterns_api_client.ts b/src/plugins/data_views/server/index_patterns_api_client.ts similarity index 94% rename from src/plugins/data/server/data_views/index_patterns_api_client.ts rename to src/plugins/data_views/server/index_patterns_api_client.ts index 4f71bf218dd4d..26ccdd7e02b4c 100644 --- a/src/plugins/data/server/data_views/index_patterns_api_client.ts +++ b/src/plugins/data_views/server/index_patterns_api_client.ts @@ -11,8 +11,8 @@ import { GetFieldsOptions, IIndexPatternsApiClient, GetFieldsOptionsTimePattern, -} from '../../common/data_views/types'; -import { DataViewMissingIndices } from '../../common/data_views/lib'; +} from '../common/types'; +import { DataViewMissingIndices } from '../common/lib'; import { IndexPatternsFetcher } from './fetcher'; import { hasUserIndexPattern } from './has_user_index_pattern'; diff --git a/src/plugins/data_views/server/mocks.ts b/src/plugins/data_views/server/mocks.ts new file mode 100644 index 0000000000000..70a582810a1e2 --- /dev/null +++ b/src/plugins/data_views/server/mocks.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export function createIndexPatternsStartMock() { + const dataViewsServiceFactory = jest.fn().mockResolvedValue({ get: jest.fn() }); + return { + indexPatternsServiceFactory: dataViewsServiceFactory, + dataViewsServiceFactory, + }; +} diff --git a/src/plugins/data_views/server/plugin.ts b/src/plugins/data_views/server/plugin.ts new file mode 100644 index 0000000000000..7285e74847e58 --- /dev/null +++ b/src/plugins/data_views/server/plugin.ts @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CoreSetup, CoreStart, Logger, Plugin, PluginInitializerContext } from 'src/core/server'; +import { dataViewsServiceFactory } from './data_views_service_factory'; +import { registerRoutes } from './routes'; +import { dataViewSavedObjectType } from './saved_objects'; +import { capabilitiesProvider } from './capabilities_provider'; +import { getIndexPatternLoad } from './expressions'; +import { registerIndexPatternsUsageCollector } from './register_index_pattern_usage_collection'; +import { createScriptedFieldsDeprecationsConfig } from './deprecations'; +import { + DataViewsServerPluginSetup, + DataViewsServerPluginStart, + DataViewsServerPluginSetupDependencies, + DataViewsServerPluginStartDependencies, +} from './types'; + +export class DataViewsServerPlugin + implements + Plugin< + DataViewsServerPluginSetup, + DataViewsServerPluginStart, + DataViewsServerPluginSetupDependencies, + DataViewsServerPluginStartDependencies + > +{ + private readonly logger: Logger; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get('dataView'); + } + + public setup( + core: CoreSetup, + { expressions, usageCollection }: DataViewsServerPluginSetupDependencies + ) { + core.savedObjects.registerType(dataViewSavedObjectType); + core.capabilities.registerProvider(capabilitiesProvider); + + registerRoutes(core.http, core.getStartServices); + + expressions.registerFunction(getIndexPatternLoad({ getStartServices: core.getStartServices })); + registerIndexPatternsUsageCollector(core.getStartServices, usageCollection); + core.deprecations.registerDeprecations(createScriptedFieldsDeprecationsConfig(core)); + + return {}; + } + + public start( + { uiSettings }: CoreStart, + { fieldFormats }: DataViewsServerPluginStartDependencies + ) { + const serviceFactory = dataViewsServiceFactory({ + logger: this.logger.get('indexPatterns'), + uiSettings, + fieldFormats, + }); + + return { + indexPatternsServiceFactory: serviceFactory, + dataViewsServiceFactory: serviceFactory, + }; + } + + public stop() {} +} + +export { DataViewsServerPlugin as Plugin }; diff --git a/src/plugins/data/server/data_views/register_index_pattern_usage_collection.test.ts b/src/plugins/data_views/server/register_index_pattern_usage_collection.test.ts similarity index 98% rename from src/plugins/data/server/data_views/register_index_pattern_usage_collection.test.ts rename to src/plugins/data_views/server/register_index_pattern_usage_collection.test.ts index 2c826185757d6..01d3a574a58cb 100644 --- a/src/plugins/data/server/data_views/register_index_pattern_usage_collection.test.ts +++ b/src/plugins/data_views/server/register_index_pattern_usage_collection.test.ts @@ -12,7 +12,7 @@ import { updateMax, getIndexPatternTelemetry, } from './register_index_pattern_usage_collection'; -import { IndexPatternsCommonService } from '..'; +import { DataViewsService } from '../common'; const scriptA = 'emit(0);'; const scriptB = 'emit(1);\nemit(2);'; @@ -32,7 +32,7 @@ const indexPatterns = { getScriptedFields: () => [], fields: [], }), -} as any as IndexPatternsCommonService; +} as any as DataViewsService; describe('index pattern usage collection', () => { it('minMaxAvgLoC calculates min, max, and average ', () => { diff --git a/src/plugins/data/server/data_views/register_index_pattern_usage_collection.ts b/src/plugins/data_views/server/register_index_pattern_usage_collection.ts similarity index 90% rename from src/plugins/data/server/data_views/register_index_pattern_usage_collection.ts rename to src/plugins/data_views/server/register_index_pattern_usage_collection.ts index 36c2a59ce2753..6af2f6df6725e 100644 --- a/src/plugins/data/server/data_views/register_index_pattern_usage_collection.ts +++ b/src/plugins/data_views/server/register_index_pattern_usage_collection.ts @@ -8,9 +8,9 @@ import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { StartServicesAccessor } from 'src/core/server'; -import { IndexPatternsCommonService } from '..'; -import { SavedObjectsClient } from '../../../../core/server'; -import { DataPluginStartDependencies, DataPluginStart } from '../plugin'; +import { DataViewsService } from '../common'; +import { SavedObjectsClient } from '../../../core/server'; +import { DataViewsServerPluginStartDependencies, DataViewsServerPluginStart } from './types'; interface CountSummary { min?: number; @@ -57,7 +57,7 @@ export const updateMax = (currentMax: number | undefined, newVal: number): numbe } }; -export async function getIndexPatternTelemetry(indexPatterns: IndexPatternsCommonService) { +export async function getIndexPatternTelemetry(indexPatterns: DataViewsService) { const ids = await indexPatterns.getIds(); const countSummaryDefaults: CountSummary = { @@ -139,7 +139,10 @@ export async function getIndexPatternTelemetry(indexPatterns: IndexPatternsCommo } export function registerIndexPatternsUsageCollector( - getStartServices: StartServicesAccessor, + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + >, usageCollection?: UsageCollectionSetup ): void { if (!usageCollection) { @@ -150,8 +153,9 @@ export function registerIndexPatternsUsageCollector( type: 'index-patterns', isReady: () => true, fetch: async () => { - const [{ savedObjects, elasticsearch }, , { indexPatterns }] = await getStartServices(); - const indexPatternService = await indexPatterns.indexPatternsServiceFactory( + const [{ savedObjects, elasticsearch }, , { indexPatternsServiceFactory }] = + await getStartServices(); + const indexPatternService = await indexPatternsServiceFactory( new SavedObjectsClient(savedObjects.createInternalRepository()), elasticsearch.client.asInternalUser ); diff --git a/src/plugins/data/server/data_views/routes.ts b/src/plugins/data_views/server/routes.ts similarity index 96% rename from src/plugins/data/server/data_views/routes.ts rename to src/plugins/data_views/server/routes.ts index 9488285fc7e2c..48c359cd9d852 100644 --- a/src/plugins/data/server/data_views/routes.ts +++ b/src/plugins/data_views/server/routes.ts @@ -19,7 +19,7 @@ import { registerPutScriptedFieldRoute } from './routes/scripted_fields/put_scri import { registerGetScriptedFieldRoute } from './routes/scripted_fields/get_scripted_field'; import { registerDeleteScriptedFieldRoute } from './routes/scripted_fields/delete_scripted_field'; import { registerUpdateScriptedFieldRoute } from './routes/scripted_fields/update_scripted_field'; -import type { DataPluginStart, DataPluginStartDependencies } from '../plugin'; +import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from './types'; import { registerManageDefaultIndexPatternRoutes } from './routes/default_index_pattern'; import { registerCreateRuntimeFieldRoute } from './routes/runtime_fields/create_runtime_field'; import { registerGetRuntimeFieldRoute } from './routes/runtime_fields/get_runtime_field'; @@ -30,7 +30,10 @@ import { registerHasUserIndexPatternRoute } from './routes/has_user_index_patter export function registerRoutes( http: HttpServiceSetup, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) { const parseMetaFields = (metaFields: string | string[]) => { let parsedFields: string[] = []; diff --git a/src/plugins/data/server/data_views/routes/create_index_pattern.ts b/src/plugins/data_views/server/routes/create_index_pattern.ts similarity index 84% rename from src/plugins/data/server/data_views/routes/create_index_pattern.ts rename to src/plugins/data_views/server/routes/create_index_pattern.ts index 7049903f84e8c..b87b03f8bd4a1 100644 --- a/src/plugins/data/server/data_views/routes/create_index_pattern.ts +++ b/src/plugins/data_views/server/routes/create_index_pattern.ts @@ -7,15 +7,15 @@ */ import { schema } from '@kbn/config-schema'; -import { IndexPatternSpec } from 'src/plugins/data/common'; +import { IndexPatternSpec } from 'src/plugins/data_views/common'; import { handleErrors } from './util/handle_errors'; import { fieldSpecSchema, runtimeFieldSpecSchema, serializedFieldFormatSchema, } from './util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../core/server'; +import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; const indexPatternSpecSchema = schema.object({ title: schema.string(), @@ -48,7 +48,10 @@ const indexPatternSpecSchema = schema.object({ export const registerCreateIndexPatternRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.post( { @@ -65,8 +68,8 @@ export const registerCreateIndexPatternRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/default_index_pattern.ts b/src/plugins/data_views/server/routes/default_index_pattern.ts similarity index 76% rename from src/plugins/data/server/data_views/routes/default_index_pattern.ts rename to src/plugins/data_views/server/routes/default_index_pattern.ts index cf5986943eb37..620e201a4850d 100644 --- a/src/plugins/data/server/data_views/routes/default_index_pattern.ts +++ b/src/plugins/data_views/server/routes/default_index_pattern.ts @@ -7,13 +7,16 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter, StartServicesAccessor } from '../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../core/server'; +import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; import { handleErrors } from './util/handle_errors'; export const registerManageDefaultIndexPatternRoutes = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.get( { @@ -23,8 +26,8 @@ export const registerManageDefaultIndexPatternRoutes = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); @@ -57,8 +60,8 @@ export const registerManageDefaultIndexPatternRoutes = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/delete_index_pattern.ts b/src/plugins/data_views/server/routes/delete_index_pattern.ts similarity index 75% rename from src/plugins/data/server/data_views/routes/delete_index_pattern.ts rename to src/plugins/data_views/server/routes/delete_index_pattern.ts index 14de079470dcb..0d3f929cdccc3 100644 --- a/src/plugins/data/server/data_views/routes/delete_index_pattern.ts +++ b/src/plugins/data_views/server/routes/delete_index_pattern.ts @@ -8,12 +8,15 @@ import { schema } from '@kbn/config-schema'; import { handleErrors } from './util/handle_errors'; -import { IRouter, StartServicesAccessor } from '../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../core/server'; +import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; export const registerDeleteIndexPatternRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.delete( { @@ -34,8 +37,8 @@ export const registerDeleteIndexPatternRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/fields/update_fields.ts b/src/plugins/data_views/server/routes/fields/update_fields.ts similarity index 87% rename from src/plugins/data/server/data_views/routes/fields/update_fields.ts rename to src/plugins/data_views/server/routes/fields/update_fields.ts index a510fdaa6e1d8..3e45ee46f2bb7 100644 --- a/src/plugins/data/server/data_views/routes/fields/update_fields.ts +++ b/src/plugins/data_views/server/routes/fields/update_fields.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { handleErrors } from '../util/handle_errors'; import { serializedFieldFormatSchema } from '../util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerUpdateFieldsRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.post( { @@ -55,8 +61,8 @@ export const registerUpdateFieldsRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/get_index_pattern.ts b/src/plugins/data_views/server/routes/get_index_pattern.ts similarity index 76% rename from src/plugins/data/server/data_views/routes/get_index_pattern.ts rename to src/plugins/data_views/server/routes/get_index_pattern.ts index 268fd3da8cd6a..7fea748ca3389 100644 --- a/src/plugins/data/server/data_views/routes/get_index_pattern.ts +++ b/src/plugins/data_views/server/routes/get_index_pattern.ts @@ -8,12 +8,15 @@ import { schema } from '@kbn/config-schema'; import { handleErrors } from './util/handle_errors'; -import { IRouter, StartServicesAccessor } from '../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../core/server'; +import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; export const registerGetIndexPatternRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.get( { @@ -34,8 +37,8 @@ export const registerGetIndexPatternRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/has_user_index_pattern.ts b/src/plugins/data_views/server/routes/has_user_index_pattern.ts similarity index 69% rename from src/plugins/data/server/data_views/routes/has_user_index_pattern.ts rename to src/plugins/data_views/server/routes/has_user_index_pattern.ts index 7d67e96f39f6e..af0ad1cc88d2e 100644 --- a/src/plugins/data/server/data_views/routes/has_user_index_pattern.ts +++ b/src/plugins/data_views/server/routes/has_user_index_pattern.ts @@ -7,12 +7,15 @@ */ import { handleErrors } from './util/handle_errors'; -import { IRouter, StartServicesAccessor } from '../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../core/server'; +import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; export const registerHasUserIndexPatternRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.get( { @@ -23,8 +26,8 @@ export const registerHasUserIndexPatternRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/runtime_fields/create_runtime_field.ts b/src/plugins/data_views/server/routes/runtime_fields/create_runtime_field.ts similarity index 82% rename from src/plugins/data/server/data_views/routes/runtime_fields/create_runtime_field.ts rename to src/plugins/data_views/server/routes/runtime_fields/create_runtime_field.ts index faf6d87b6d10b..04b661d14732f 100644 --- a/src/plugins/data/server/data_views/routes/runtime_fields/create_runtime_field.ts +++ b/src/plugins/data_views/server/routes/runtime_fields/create_runtime_field.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { handleErrors } from '../util/handle_errors'; import { runtimeFieldSpecSchema } from '../util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerCreateRuntimeFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.post( { @@ -39,8 +45,8 @@ export const registerCreateRuntimeFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/runtime_fields/delete_runtime_field.ts b/src/plugins/data_views/server/routes/runtime_fields/delete_runtime_field.ts similarity index 79% rename from src/plugins/data/server/data_views/routes/runtime_fields/delete_runtime_field.ts rename to src/plugins/data_views/server/routes/runtime_fields/delete_runtime_field.ts index 58b8529d7cf5a..e5c6b03a64224 100644 --- a/src/plugins/data/server/data_views/routes/runtime_fields/delete_runtime_field.ts +++ b/src/plugins/data_views/server/routes/runtime_fields/delete_runtime_field.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { ErrorIndexPatternFieldNotFound } from '../../error'; import { handleErrors } from '../util/handle_errors'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerDeleteRuntimeFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.delete( { @@ -35,8 +41,8 @@ export const registerDeleteRuntimeFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/runtime_fields/get_runtime_field.ts b/src/plugins/data_views/server/routes/runtime_fields/get_runtime_field.ts similarity index 79% rename from src/plugins/data/server/data_views/routes/runtime_fields/get_runtime_field.ts rename to src/plugins/data_views/server/routes/runtime_fields/get_runtime_field.ts index 6bc2bf396c0b4..b457ae6b0159b 100644 --- a/src/plugins/data/server/data_views/routes/runtime_fields/get_runtime_field.ts +++ b/src/plugins/data_views/server/routes/runtime_fields/get_runtime_field.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { ErrorIndexPatternFieldNotFound } from '../../error'; import { handleErrors } from '../util/handle_errors'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerGetRuntimeFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.get( { @@ -36,8 +42,8 @@ export const registerGetRuntimeFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/runtime_fields/put_runtime_field.ts b/src/plugins/data_views/server/routes/runtime_fields/put_runtime_field.ts similarity index 82% rename from src/plugins/data/server/data_views/routes/runtime_fields/put_runtime_field.ts rename to src/plugins/data_views/server/routes/runtime_fields/put_runtime_field.ts index a5e92fa5a36ec..1c3ed99fdf67e 100644 --- a/src/plugins/data/server/data_views/routes/runtime_fields/put_runtime_field.ts +++ b/src/plugins/data_views/server/routes/runtime_fields/put_runtime_field.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { handleErrors } from '../util/handle_errors'; import { runtimeFieldSpecSchema } from '../util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerPutRuntimeFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.put( { @@ -38,8 +44,8 @@ export const registerPutRuntimeFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/runtime_fields/update_runtime_field.ts b/src/plugins/data_views/server/routes/runtime_fields/update_runtime_field.ts similarity index 83% rename from src/plugins/data/server/data_views/routes/runtime_fields/update_runtime_field.ts rename to src/plugins/data_views/server/routes/runtime_fields/update_runtime_field.ts index 3f3aae46c4388..ca92f310ff281 100644 --- a/src/plugins/data/server/data_views/routes/runtime_fields/update_runtime_field.ts +++ b/src/plugins/data_views/server/routes/runtime_fields/update_runtime_field.ts @@ -7,16 +7,22 @@ */ import { schema } from '@kbn/config-schema'; -import { RuntimeField } from 'src/plugins/data/common'; +import { RuntimeField } from 'src/plugins/data_views/common'; import { ErrorIndexPatternFieldNotFound } from '../../error'; import { handleErrors } from '../util/handle_errors'; import { runtimeFieldSpec, runtimeFieldSpecTypeSchema } from '../util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerUpdateRuntimeFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.post( { @@ -46,8 +52,8 @@ export const registerUpdateRuntimeFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/scripted_fields/create_scripted_field.ts b/src/plugins/data_views/server/routes/scripted_fields/create_scripted_field.ts similarity index 83% rename from src/plugins/data/server/data_views/routes/scripted_fields/create_scripted_field.ts rename to src/plugins/data_views/server/routes/scripted_fields/create_scripted_field.ts index 4d7b1d87cd9eb..e620960afbe13 100644 --- a/src/plugins/data/server/data_views/routes/scripted_fields/create_scripted_field.ts +++ b/src/plugins/data_views/server/routes/scripted_fields/create_scripted_field.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { handleErrors } from '../util/handle_errors'; import { fieldSpecSchema } from '../util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerCreateScriptedFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.post( { @@ -38,8 +44,8 @@ export const registerCreateScriptedFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/scripted_fields/delete_scripted_field.ts b/src/plugins/data_views/server/routes/scripted_fields/delete_scripted_field.ts similarity index 81% rename from src/plugins/data/server/data_views/routes/scripted_fields/delete_scripted_field.ts rename to src/plugins/data_views/server/routes/scripted_fields/delete_scripted_field.ts index 169351c220ecf..bd1bfe0ec4e25 100644 --- a/src/plugins/data/server/data_views/routes/scripted_fields/delete_scripted_field.ts +++ b/src/plugins/data_views/server/routes/scripted_fields/delete_scripted_field.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { ErrorIndexPatternFieldNotFound } from '../../error'; import { handleErrors } from '../util/handle_errors'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerDeleteScriptedFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.delete( { @@ -39,8 +45,8 @@ export const registerDeleteScriptedFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/scripted_fields/get_scripted_field.ts b/src/plugins/data_views/server/routes/scripted_fields/get_scripted_field.ts similarity index 81% rename from src/plugins/data/server/data_views/routes/scripted_fields/get_scripted_field.ts rename to src/plugins/data_views/server/routes/scripted_fields/get_scripted_field.ts index 28f3f75a7aa1b..ae9cca2c79b48 100644 --- a/src/plugins/data/server/data_views/routes/scripted_fields/get_scripted_field.ts +++ b/src/plugins/data_views/server/routes/scripted_fields/get_scripted_field.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { ErrorIndexPatternFieldNotFound } from '../../error'; import { handleErrors } from '../util/handle_errors'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerGetScriptedFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.get( { @@ -39,8 +45,8 @@ export const registerGetScriptedFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/scripted_fields/put_scripted_field.ts b/src/plugins/data_views/server/routes/scripted_fields/put_scripted_field.ts similarity index 83% rename from src/plugins/data/server/data_views/routes/scripted_fields/put_scripted_field.ts rename to src/plugins/data_views/server/routes/scripted_fields/put_scripted_field.ts index 368ad53eb2258..a6cee3762513e 100644 --- a/src/plugins/data/server/data_views/routes/scripted_fields/put_scripted_field.ts +++ b/src/plugins/data_views/server/routes/scripted_fields/put_scripted_field.ts @@ -9,12 +9,18 @@ import { schema } from '@kbn/config-schema'; import { handleErrors } from '../util/handle_errors'; import { fieldSpecSchema } from '../util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerPutScriptedFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.put( { @@ -38,8 +44,8 @@ export const registerPutScriptedFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/scripted_fields/update_scripted_field.ts b/src/plugins/data_views/server/routes/scripted_fields/update_scripted_field.ts similarity index 86% rename from src/plugins/data/server/data_views/routes/scripted_fields/update_scripted_field.ts rename to src/plugins/data_views/server/routes/scripted_fields/update_scripted_field.ts index bf10a3ee6389e..2917838293ec8 100644 --- a/src/plugins/data/server/data_views/routes/scripted_fields/update_scripted_field.ts +++ b/src/plugins/data_views/server/routes/scripted_fields/update_scripted_field.ts @@ -7,16 +7,22 @@ */ import { schema } from '@kbn/config-schema'; -import { FieldSpec } from 'src/plugins/data/common'; +import { FieldSpec } from 'src/plugins/data_views/common'; import { ErrorIndexPatternFieldNotFound } from '../../error'; import { handleErrors } from '../util/handle_errors'; import { fieldSpecSchemaFields } from '../util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../../core/server'; +import type { + DataViewsServerPluginStart, + DataViewsServerPluginStartDependencies, +} from '../../types'; export const registerUpdateScriptedFieldRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.post( { @@ -59,8 +65,8 @@ export const registerUpdateScriptedFieldRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/update_index_pattern.ts b/src/plugins/data_views/server/routes/update_index_pattern.ts similarity index 91% rename from src/plugins/data/server/data_views/routes/update_index_pattern.ts rename to src/plugins/data_views/server/routes/update_index_pattern.ts index 1c88550c154c5..1421057d65d26 100644 --- a/src/plugins/data/server/data_views/routes/update_index_pattern.ts +++ b/src/plugins/data_views/server/routes/update_index_pattern.ts @@ -13,8 +13,8 @@ import { runtimeFieldSpecSchema, serializedFieldFormatSchema, } from './util/schemas'; -import { IRouter, StartServicesAccessor } from '../../../../../core/server'; -import type { DataPluginStart, DataPluginStartDependencies } from '../../plugin'; +import { IRouter, StartServicesAccessor } from '../../../../core/server'; +import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; const indexPatternUpdateSchema = schema.object({ title: schema.maybe(schema.string()), @@ -37,7 +37,10 @@ const indexPatternUpdateSchema = schema.object({ export const registerUpdateIndexPatternRoute = ( router: IRouter, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor< + DataViewsServerPluginStartDependencies, + DataViewsServerPluginStart + > ) => { router.post( { @@ -62,8 +65,8 @@ export const registerUpdateIndexPatternRoute = ( handleErrors(async (ctx, req, res) => { const savedObjectsClient = ctx.core.savedObjects.client; const elasticsearchClient = ctx.core.elasticsearch.client.asCurrentUser; - const [, , { indexPatterns }] = await getStartServices(); - const indexPatternsService = await indexPatterns.indexPatternsServiceFactory( + const [, , { indexPatternsServiceFactory }] = await getStartServices(); + const indexPatternsService = await indexPatternsServiceFactory( savedObjectsClient, elasticsearchClient ); diff --git a/src/plugins/data/server/data_views/routes/util/handle_errors.ts b/src/plugins/data_views/server/routes/util/handle_errors.ts similarity index 100% rename from src/plugins/data/server/data_views/routes/util/handle_errors.ts rename to src/plugins/data_views/server/routes/util/handle_errors.ts diff --git a/src/plugins/data/server/data_views/routes/util/schemas.ts b/src/plugins/data_views/server/routes/util/schemas.ts similarity index 96% rename from src/plugins/data/server/data_views/routes/util/schemas.ts rename to src/plugins/data_views/server/routes/util/schemas.ts index 79ee1ffa1ab97..79f493f303801 100644 --- a/src/plugins/data/server/data_views/routes/util/schemas.ts +++ b/src/plugins/data_views/server/routes/util/schemas.ts @@ -7,7 +7,7 @@ */ import { schema, Type } from '@kbn/config-schema'; -import { RUNTIME_FIELD_TYPES, RuntimeType } from '../../../../common'; +import { RUNTIME_FIELD_TYPES, RuntimeType } from '../../../common'; export const serializedFieldFormatSchema = schema.object({ id: schema.maybe(schema.string()), diff --git a/src/plugins/data/server/saved_objects/index_patterns.ts b/src/plugins/data_views/server/saved_objects/data_views.ts similarity index 88% rename from src/plugins/data/server/saved_objects/index_patterns.ts rename to src/plugins/data_views/server/saved_objects/data_views.ts index a809f2ce73e1b..d340732873235 100644 --- a/src/plugins/data/server/saved_objects/index_patterns.ts +++ b/src/plugins/data_views/server/saved_objects/data_views.ts @@ -8,10 +8,10 @@ import type { SavedObjectsType } from 'kibana/server'; import { indexPatternSavedObjectTypeMigrations } from './index_pattern_migrations'; -import { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../../common'; +import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../../common'; -export const indexPatternSavedObjectType: SavedObjectsType = { - name: INDEX_PATTERN_SAVED_OBJECT_TYPE, +export const dataViewSavedObjectType: SavedObjectsType = { + name: DATA_VIEW_SAVED_OBJECT_TYPE, hidden: false, namespaceType: 'single', management: { diff --git a/src/plugins/data/common/utils/index.ts b/src/plugins/data_views/server/saved_objects/index.ts similarity index 81% rename from src/plugins/data/common/utils/index.ts rename to src/plugins/data_views/server/saved_objects/index.ts index e07fd18594471..ff0f524ae961c 100644 --- a/src/plugins/data/common/utils/index.ts +++ b/src/plugins/data_views/server/saved_objects/index.ts @@ -6,5 +6,4 @@ * Side Public License, v 1. */ -/** @internal */ -export { shortenDottedString } from './shorten_dotted_string'; +export { dataViewSavedObjectType } from './data_views'; diff --git a/src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts b/src/plugins/data_views/server/saved_objects/index_pattern_migrations.test.ts similarity index 100% rename from src/plugins/data/server/saved_objects/index_pattern_migrations.test.ts rename to src/plugins/data_views/server/saved_objects/index_pattern_migrations.test.ts diff --git a/src/plugins/data/server/saved_objects/index_pattern_migrations.ts b/src/plugins/data_views/server/saved_objects/index_pattern_migrations.ts similarity index 100% rename from src/plugins/data/server/saved_objects/index_pattern_migrations.ts rename to src/plugins/data_views/server/saved_objects/index_pattern_migrations.ts diff --git a/src/plugins/data/common/utils/shorten_dotted_string.ts b/src/plugins/data_views/server/saved_objects/migrations/to_v7_12_0.ts similarity index 57% rename from src/plugins/data/common/utils/shorten_dotted_string.ts rename to src/plugins/data_views/server/saved_objects/migrations/to_v7_12_0.ts index 53f7471913dc3..955028c0f9bf2 100644 --- a/src/plugins/data/common/utils/shorten_dotted_string.ts +++ b/src/plugins/data_views/server/saved_objects/migrations/to_v7_12_0.ts @@ -6,14 +6,12 @@ * Side Public License, v 1. */ -const DOT_PREFIX_RE = /(.).+?\./g; +import type { SavedObjectMigrationFn } from 'kibana/server'; /** - * Convert a dot.notated.string into a short - * version (d.n.string) - * - * @return {any} + * Drop the previous document's attributes, which report `averageDuration` incorrectly. + * @param doc */ -export function shortenDottedString(input: any) { - return typeof input !== 'string' ? input : input.replace(DOT_PREFIX_RE, '$1.'); -} +export const migrate712: SavedObjectMigrationFn = (doc) => { + return { ...doc, attributes: {} }; +}; diff --git a/src/plugins/data/server/data_views/saved_objects_client_wrapper.test.ts b/src/plugins/data_views/server/saved_objects_client_wrapper.test.ts similarity index 96% rename from src/plugins/data/server/data_views/saved_objects_client_wrapper.test.ts rename to src/plugins/data_views/server/saved_objects_client_wrapper.test.ts index bbe857894b3f0..b03532421ecab 100644 --- a/src/plugins/data/server/data_views/saved_objects_client_wrapper.test.ts +++ b/src/plugins/data_views/server/saved_objects_client_wrapper.test.ts @@ -9,7 +9,7 @@ import { SavedObjectsClientServerToCommon } from './saved_objects_client_wrapper'; import { SavedObjectsClientContract } from 'src/core/server'; -import { DataViewSavedObjectConflictError } from '../../common/data_views'; +import { DataViewSavedObjectConflictError } from '../common'; describe('SavedObjectsClientPublicToCommon', () => { const soClient = { resolve: jest.fn() } as unknown as SavedObjectsClientContract; diff --git a/src/plugins/data/server/data_views/saved_objects_client_wrapper.ts b/src/plugins/data_views/server/saved_objects_client_wrapper.ts similarity index 98% rename from src/plugins/data/server/data_views/saved_objects_client_wrapper.ts rename to src/plugins/data_views/server/saved_objects_client_wrapper.ts index b37648a3f038e..dc7163c405d4f 100644 --- a/src/plugins/data/server/data_views/saved_objects_client_wrapper.ts +++ b/src/plugins/data_views/server/saved_objects_client_wrapper.ts @@ -11,7 +11,7 @@ import { SavedObjectsClientCommon, SavedObjectsClientCommonFindArgs, DataViewSavedObjectConflictError, -} from '../../common/data_views'; +} from '../common'; export class SavedObjectsClientServerToCommon implements SavedObjectsClientCommon { private savedObjectClient: SavedObjectsClientContract; diff --git a/src/plugins/data_views/server/types.ts b/src/plugins/data_views/server/types.ts new file mode 100644 index 0000000000000..4a57a1d01b9c3 --- /dev/null +++ b/src/plugins/data_views/server/types.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Logger, SavedObjectsClientContract, ElasticsearchClient } from 'kibana/server'; +import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; +import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; +import { DataViewsService } from '../common'; +import { FieldFormatsSetup, FieldFormatsStart } from '../../field_formats/server'; + +type ServiceFactory = ( + savedObjectsClient: SavedObjectsClientContract, + elasticsearchClient: ElasticsearchClient +) => Promise; +export interface DataViewsServerPluginStart { + dataViewsServiceFactory: ServiceFactory; + /** + * @deprecated Renamed to dataViewsServiceFactory + */ + indexPatternsServiceFactory: ServiceFactory; +} + +export interface IndexPatternsServiceSetupDeps { + expressions: ExpressionsServerSetup; + usageCollection?: UsageCollectionSetup; +} + +export interface IndexPatternsServiceStartDeps { + fieldFormats: FieldFormatsStart; + logger: Logger; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DataViewsServerPluginSetup {} + +export type IndexPatternsServiceStart = DataViewsServerPluginStart; + +export interface DataViewsServerPluginSetupDependencies { + fieldFormats: FieldFormatsSetup; + expressions: ExpressionsServerSetup; + usageCollection?: UsageCollectionSetup; +} + +export interface DataViewsServerPluginStartDependencies { + fieldFormats: FieldFormatsStart; + logger: Logger; +} diff --git a/src/plugins/data/server/data_views/ui_settings_wrapper.ts b/src/plugins/data_views/server/ui_settings_wrapper.ts similarity index 95% rename from src/plugins/data/server/data_views/ui_settings_wrapper.ts rename to src/plugins/data_views/server/ui_settings_wrapper.ts index dce552205db2e..f42d43c1c24f4 100644 --- a/src/plugins/data/server/data_views/ui_settings_wrapper.ts +++ b/src/plugins/data_views/server/ui_settings_wrapper.ts @@ -7,7 +7,7 @@ */ import { IUiSettingsClient } from 'src/core/server'; -import { UiSettingsCommon } from '../../common'; +import { UiSettingsCommon } from '../common'; export class UiSettingsServerToCommon implements UiSettingsCommon { private uiSettings: IUiSettingsClient; diff --git a/src/plugins/data/server/data_views/utils.ts b/src/plugins/data_views/server/utils.ts similarity index 92% rename from src/plugins/data/server/data_views/utils.ts rename to src/plugins/data_views/server/utils.ts index 7f1a953c482d0..bb7d23f832233 100644 --- a/src/plugins/data/server/data_views/utils.ts +++ b/src/plugins/data_views/server/utils.ts @@ -9,10 +9,10 @@ import { SavedObjectsClientContract } from 'kibana/server'; import { IFieldType, - INDEX_PATTERN_SAVED_OBJECT_TYPE, + DATA_VIEW_SAVED_OBJECT_TYPE, IndexPatternAttributes, SavedObject, -} from '../../common'; +} from '../common'; export const getFieldByName = ( fieldName: string, @@ -29,7 +29,7 @@ export const findIndexPatternById = async ( index: string ): Promise | undefined> => { const savedObjectsResponse = await savedObjectsClient.find({ - type: INDEX_PATTERN_SAVED_OBJECT_TYPE, + type: DATA_VIEW_SAVED_OBJECT_TYPE, fields: ['fields'], search: `"${index}"`, searchFields: ['title'], diff --git a/src/plugins/data_views/tsconfig.json b/src/plugins/data_views/tsconfig.json new file mode 100644 index 0000000000000..f5c80ce30cce0 --- /dev/null +++ b/src/plugins/data_views/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + "config.ts", + "common/**/*.json", + "public/**/*.json", + "server/**/*.json" + ], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../usage_collection/tsconfig.json" }, + { "path": "../kibana_utils/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" }, + { "path": "../field_formats/tsconfig.json" }, + { "path": "../expressions/tsconfig.json" } + ] +} diff --git a/src/plugins/home/server/services/new_instance_status.ts b/src/plugins/home/server/services/new_instance_status.ts index b72ada27ecbad..e19380e928822 100644 --- a/src/plugins/home/server/services/new_instance_status.ts +++ b/src/plugins/home/server/services/new_instance_status.ts @@ -7,7 +7,6 @@ */ import type { IScopedClusterClient, SavedObjectsClientContract } from '../../../../core/server'; -import type { IndexPatternSavedObjectAttrs } from '../../../data/common/data_views/data_views'; const LOGS_INDEX_PATTERN = 'logs-*'; const METRICS_INDEX_PATTERN = 'metrics-*'; @@ -23,7 +22,7 @@ interface Deps { } export const isNewInstance = async ({ esClient, soClient }: Deps): Promise => { - const indexPatterns = await soClient.find({ + const indexPatterns = await soClient.find<{ title: string }>({ type: 'index-pattern', fields: ['title'], search: `*`, diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts index 7a0bb4584e83a..31713d8ad7d5e 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts @@ -8,7 +8,7 @@ import { SavedObjectReference } from '../../../../../core/types'; import { VisParams } from '../../../common'; -import { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../../../../data/public'; +import { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../../../../data/common'; const isControlsVis = (visType: string) => visType === 'input_control_vis'; diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts index 98970a0127c71..a3917699fcab3 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts @@ -8,7 +8,7 @@ import { SavedObjectReference } from '../../../../../core/types'; import { VisParams } from '../../../common'; -import { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../../../../data/public'; +import { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../../../../data/common'; /** @internal **/ const REF_NAME_POSTFIX = '_ref_name'; diff --git a/test/api_integration/apis/index_patterns/deprecations/scripted_fields.ts b/test/api_integration/apis/index_patterns/deprecations/scripted_fields.ts index 168c2b005d80d..c32b9b4241206 100644 --- a/test/api_integration/apis/index_patterns/deprecations/scripted_fields.ts +++ b/test/api_integration/apis/index_patterns/deprecations/scripted_fields.ts @@ -30,7 +30,9 @@ export default function ({ getService }: FtrProviderContext) { const { body } = await supertest.get('/api/deprecations/'); const { deprecations } = body as DeprecationsGetResponse; - const dataPluginDeprecations = deprecations.filter(({ domainId }) => domainId === 'data'); + const dataPluginDeprecations = deprecations.filter( + ({ domainId }) => domainId === 'dataViews' + ); expect(dataPluginDeprecations.length).to.be(0); }); @@ -59,7 +61,9 @@ export default function ({ getService }: FtrProviderContext) { const { body } = await supertest.get('/api/deprecations/'); const { deprecations } = body as DeprecationsGetResponse; - const dataPluginDeprecations = deprecations.filter(({ domainId }) => domainId === 'data'); + const dataPluginDeprecations = deprecations.filter( + ({ domainId }) => domainId === 'dataViews' + ); expect(dataPluginDeprecations.length).to.be(1); expect(dataPluginDeprecations[0].message).to.contain(title); diff --git a/test/api_integration/apis/index_patterns/es_errors/errors.js b/test/api_integration/apis/index_patterns/es_errors/errors.js index ac656e487323d..d5ca92c371617 100644 --- a/test/api_integration/apis/index_patterns/es_errors/errors.js +++ b/test/api_integration/apis/index_patterns/es_errors/errors.js @@ -15,7 +15,7 @@ import { createNoMatchingIndicesError, isNoMatchingIndicesError, convertEsError, -} from '../../../../../src/plugins/data/server/data_views/fetcher/lib/errors'; +} from '../../../../../src/plugins/data_views/server/fetcher/lib/errors'; import { getIndexNotFoundError, getDocNotFoundError } from './lib'; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/top_values/top_values.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/top_values/top_values.tsx index 45e8944c7c667..e2793512e23df 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/top_values/top_values.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/top_values/top_values.tsx @@ -23,7 +23,7 @@ import { roundToDecimalPlace, kibanaFieldFormat } from '../utils'; import { ExpandedRowFieldHeader } from '../stats_table/components/expanded_row_field_header'; import { FieldVisStats } from '../../../../../common/types'; import { ExpandedRowPanel } from '../stats_table/components/field_data_expanded_row/expanded_row_panel'; -import { IndexPatternField } from '../../../../../../../../src/plugins/data/common/data_views/fields'; +import { IndexPatternField } from '../../../../../../../../src/plugins/data_views/common'; interface Props { stats: FieldVisStats | undefined; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts index 4fb50aecc1062..3dd81015393b4 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/utils/saved_search_utils.test.ts @@ -13,7 +13,7 @@ import { import type { SavedSearchSavedObject } from '../../../../common'; import type { SavedSearch } from '../../../../../../../src/plugins/discover/public'; import type { Filter, FilterStateStore } from '@kbn/es-query'; -import { stubbedSavedObjectIndexPattern } from '../../../../../../../src/plugins/data/common/data_views/data_view.stub'; +import { stubbedSavedObjectIndexPattern } from '../../../../../../../src/plugins/data_views/common/data_view.stub'; import { IndexPattern } from '../../../../../../../src/plugins/data/common'; import { fieldFormatsMock } from '../../../../../../../src/plugins/field_formats/common/mocks'; import { uiSettingsServiceMock } from 'src/core/public/mocks'; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 5da17d8a746a0..53932d381dfdd 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1653,12 +1653,12 @@ "data.functions.esaggs.help": "AggConfig 集約を実行します", "data.functions.esaggs.inspector.dataRequest.description": "このリクエストはElasticsearchにクエリし、ビジュアライゼーション用のデータを取得します。", "data.functions.esaggs.inspector.dataRequest.title": "データ", - "data.functions.indexPatternLoad.help": "インデックスパターンを読み込みます", - "data.functions.indexPatternLoad.id.help": "読み込むインデックスパターンID", - "data.indexPatterns.ensureDefaultIndexPattern.bannerLabel": "Kibanaでデータの可視化と閲覧を行うには、Elasticsearchからデータを取得するためのインデックスパターンの作成が必要です。", - "data.indexPatterns.fetchFieldErrorTitle": "インデックスパターンのフィールド取得中にエラーが発生 {title}(ID:{id})", - "data.indexPatterns.indexPatternLoad.error.kibanaRequest": "サーバーでこの検索を実行するには、KibanaRequest が必要です。式実行パラメーターに要求オブジェクトを渡してください。", - "data.indexPatterns.unableWriteLabel": "インデックスパターンを書き込めません。このインデックスパターンへの最新の変更を取得するには、ページを更新してください。", + "dataViews.indexPatternLoad.help": "インデックスパターンを読み込みます", + "dataViews.functions.indexPatternLoad.id.help": "読み込むインデックスパターンID", + "dataViews.ensureDefaultIndexPattern.bannerLabel": "Kibanaでデータの可視化と閲覧を行うには、Elasticsearchからデータを取得するためのインデックスパターンの作成が必要です。", + "dataViews.fetchFieldErrorTitle": "インデックスパターンのフィールド取得中にエラーが発生 {title}(ID:{id})", + "dataViews.indexPatternLoad.error.kibanaRequest": "サーバーでこの検索を実行するには、KibanaRequest が必要です。式実行パラメーターに要求オブジェクトを渡してください。", + "dataViews.unableWriteLabel": "インデックスパターンを書き込めません。このインデックスパターンへの最新の変更を取得するには、ページを更新してください。", "data.inspector.table..dataDescriptionTooltip": "ビジュアライゼーションの元のデータを表示", "data.inspector.table.dataTitle": "データ", "data.inspector.table.downloadCSVToggleButtonLabel": "CSV をダウンロード", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 6d5b94f49cb6f..1f00b1c910190 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1669,12 +1669,12 @@ "data.functions.esaggs.help": "运行 AggConfig 聚合", "data.functions.esaggs.inspector.dataRequest.description": "此请求查询 Elasticsearch,以获取可视化的数据。", "data.functions.esaggs.inspector.dataRequest.title": "数据", - "data.functions.indexPatternLoad.help": "加载索引模式", - "data.functions.indexPatternLoad.id.help": "要加载的索引模式 id", - "data.indexPatterns.ensureDefaultIndexPattern.bannerLabel": "要在 Kibana 中可视化和浏览数据,必须创建索引模式,以从 Elasticsearch 中检索数据。", - "data.indexPatterns.fetchFieldErrorTitle": "提取索引模式 {title} (ID: {id}) 的字段时出错", - "data.indexPatterns.indexPatternLoad.error.kibanaRequest": "在服务器上执行此搜索时需要 Kibana 请求。请向表达式执行模式参数提供请求对象。", - "data.indexPatterns.unableWriteLabel": "无法写入索引模式!请刷新页面以获取此索引模式的最新更改。", + "dataViews.indexPatternLoad.help": "加载索引模式", + "dataViews.functions.indexPatternLoad.id.help": "要加载的索引模式 id", + "dataViews.ensureDefaultIndexPattern.bannerLabel": "要在 Kibana 中可视化和浏览数据,必须创建索引模式,以从 Elasticsearch 中检索数据。", + "dataViews.fetchFieldErrorTitle": "提取索引模式 {title} (ID: {id}) 的字段时出错", + "dataViews.indexPatternLoad.error.kibanaRequest": "在服务器上执行此搜索时需要 Kibana 请求。请向表达式执行模式参数提供请求对象。", + "dataViews.unableWriteLabel": "无法写入索引模式!请刷新页面以获取此索引模式的最新更改。", "data.inspector.table..dataDescriptionTooltip": "查看可视化后面的数据", "data.inspector.table.dataTitle": "数据", "data.inspector.table.downloadCSVToggleButtonLabel": "下载 CSV", From 6b9ef32ffede072f9588b413a1728c741726869b Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Mon, 4 Oct 2021 19:10:14 +0200 Subject: [PATCH 54/98] :bug: Fix color fallback for different type of layers (#113642) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../xy_visualization/to_expression.test.ts | 39 +++++++++++++++++++ .../public/xy_visualization/to_expression.ts | 7 +++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts index 2a4941995054b..d174fb831c2dc 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts @@ -13,6 +13,7 @@ import { Operation } from '../types'; import { createMockDatasource, createMockFramePublicAPI } from '../mocks'; import { layerTypes } from '../../common'; import { fieldFormatsServiceMock } from '../../../../../src/plugins/field_formats/public/mocks'; +import { defaultThresholdColor } from './color_assignment'; describe('#toExpression', () => { const xyVisualization = getXyVisualization({ @@ -319,4 +320,42 @@ describe('#toExpression', () => { ) as Ast; expect(expression.chain[0].arguments.valueLabels[0] as Ast).toEqual('inside'); }); + + it('should compute the correct series color fallback based on the layer type', () => { + const expression = xyVisualization.toExpression( + { + legend: { position: Position.Bottom, isVisible: true }, + valueLabels: 'inside', + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + layerType: layerTypes.DATA, + seriesType: 'area', + splitAccessor: 'd', + xAccessor: 'a', + accessors: ['b', 'c'], + yConfig: [{ forAccessor: 'a' }], + }, + { + layerId: 'threshold', + layerType: layerTypes.THRESHOLD, + seriesType: 'area', + splitAccessor: 'd', + xAccessor: 'a', + accessors: ['b', 'c'], + yConfig: [{ forAccessor: 'a' }], + }, + ], + }, + { ...frame.datasourceLayers, threshold: mockDatasource.publicAPIMock } + ) as Ast; + + function getYConfigColorForLayer(ast: Ast, index: number) { + return ((ast.chain[0].arguments.layers[index] as Ast).chain[0].arguments.yConfig[0] as Ast) + .chain[0].arguments.color; + } + expect(getYConfigColorForLayer(expression, 0)).toEqual([]); + expect(getYConfigColorForLayer(expression, 1)).toEqual([defaultThresholdColor]); + }); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index 2fce7c6a612ae..bb65b69a8d121 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -335,7 +335,12 @@ export const buildExpression = ( arguments: { forAccessor: [yConfig.forAccessor], axisMode: yConfig.axisMode ? [yConfig.axisMode] : [], - color: [yConfig.color || defaultThresholdColor], + color: + layer.layerType === layerTypes.THRESHOLD + ? [yConfig.color || defaultThresholdColor] + : yConfig.color + ? [yConfig.color] + : [], lineStyle: [yConfig.lineStyle || 'solid'], lineWidth: [yConfig.lineWidth || 1], fill: [yConfig.fill || 'none'], From 51df1e58a38892e4db648678899c185a9f44e596 Mon Sep 17 00:00:00 2001 From: Diana Derevyankina <54894989+DziyanaDzeraviankina@users.noreply.github.com> Date: Mon, 4 Oct 2021 20:15:57 +0300 Subject: [PATCH 55/98] [TSVB] Rename Index pattern to Data view (#110253) * [TSVB] Rename Index pattern to Data view * Update some labels * Make asterisk bold to indicate it's text input * Remove redundant translation * Remove "now" from TSVB callout notification title * Update variable name to match the text Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../index_pattern_select.tsx | 37 ++++++++++--------- .../switch_mode_popover.tsx | 9 ++--- .../application/components/series_config.js | 4 +- .../use_index_patter_mode_callout.tsx | 12 +++--- .../components/vis_types/timeseries/config.js | 4 +- .../translations/translations/ja-JP.json | 13 +------ .../translations/translations/zh-CN.json | 13 +------ 7 files changed, 38 insertions(+), 54 deletions(-) diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 1029ac67cc43c..d28e2c5e0fb9a 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -33,22 +33,28 @@ export interface IndexPatternSelectProps { | null; } -const defaultIndexPatternHelpText = i18n.translate( - 'visTypeTimeseries.indexPatternSelect.defaultIndexPatternText', - { - defaultMessage: 'Default index pattern is used.', - } +const queryAllIndicesHelpText = ( + *, + }} + /> ); -const queryAllIndexesHelpText = i18n.translate( - 'visTypeTimeseries.indexPatternSelect.queryAllIndexesText', - { - defaultMessage: 'To query all indexes use *', - } +const getIndexPatternHelpText = (useKibanaIndices: boolean) => ( + ); const indexPatternLabel = i18n.translate('visTypeTimeseries.indexPatternSelect.label', { - defaultMessage: 'Index pattern', + defaultMessage: 'Data view', }); export const IndexPatternSelect = ({ @@ -103,17 +109,14 @@ export const IndexPatternSelect = ({ diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx index 43ef091da251d..5e66b50eac467 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx @@ -79,7 +79,7 @@ export const SwitchModePopover = ({ onModeChange, useKibanaIndices }: PopoverPro aria-label={i18n.translate( 'visTypeTimeseries.indexPatternSelect.switchModePopover.areaLabel', { - defaultMessage: 'Configure index pattern selection mode', + defaultMessage: 'Configure data view selection mode', } )} onClick={onButtonClick} @@ -97,14 +97,13 @@ export const SwitchModePopover = ({ onModeChange, useKibanaIndices }: PopoverPro > {i18n.translate('visTypeTimeseries.indexPatternSelect.switchModePopover.title', { - defaultMessage: 'Index pattern selection mode', + defaultMessage: 'Data view mode', })} { { } iconType="cheer" @@ -42,13 +42,13 @@ export const UseIndexPatternModeCallout = () => { >

    @@ -59,7 +59,7 @@ export const UseIndexPatternModeCallout = () => { diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/config.js b/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/config.js index 4257c35a6d4c2..208f9af9bb250 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/config.js +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/config.js @@ -538,8 +538,8 @@ export const TimeseriesConfig = injectI18n(function (props) { Date: Mon, 4 Oct 2021 18:18:45 +0100 Subject: [PATCH 56/98] Better message for unanticipated authorisation errors (#113460) * Custom message for unanticipated 401 errors * Refactor logout reasons * Fix types Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/security/common/types.ts | 7 ++ .../authentication/login/components/index.ts | 1 + .../login/components/login_form/index.ts | 1 + .../components/login_form/login_form.tsx | 8 +-- .../authentication/login/login_page.tsx | 72 +++++++++---------- .../public/session/session_expired.mock.ts | 6 +- .../public/session/session_expired.test.ts | 15 +++- .../public/session/session_expired.ts | 9 +-- .../public/session/session_timeout.ts | 10 ++- ...thorized_response_http_interceptor.test.ts | 1 + .../unauthorized_response_http_interceptor.ts | 3 +- 11 files changed, 79 insertions(+), 54 deletions(-) diff --git a/x-pack/plugins/security/common/types.ts b/x-pack/plugins/security/common/types.ts index 690aced63b187..e6354841cc9e0 100644 --- a/x-pack/plugins/security/common/types.ts +++ b/x-pack/plugins/security/common/types.ts @@ -12,3 +12,10 @@ export interface SessionInfo { canBeExtended: boolean; provider: AuthenticationProvider; } + +export enum LogoutReason { + 'SESSION_EXPIRED' = 'SESSION_EXPIRED', + 'AUTHENTICATION_ERROR' = 'AUTHENTICATION_ERROR', + 'LOGGED_OUT' = 'LOGGED_OUT', + 'UNAUTHENTICATED' = 'UNAUTHENTICATED', +} diff --git a/x-pack/plugins/security/public/authentication/login/components/index.ts b/x-pack/plugins/security/public/authentication/login/components/index.ts index 63928e4e82e37..a2c12a3c0055a 100644 --- a/x-pack/plugins/security/public/authentication/login/components/index.ts +++ b/x-pack/plugins/security/public/authentication/login/components/index.ts @@ -5,5 +5,6 @@ * 2.0. */ +export type { LoginFormProps } from './login_form'; export { LoginForm, LoginFormMessageType } from './login_form'; export { DisabledLoginForm } from './disabled_login_form'; diff --git a/x-pack/plugins/security/public/authentication/login/components/login_form/index.ts b/x-pack/plugins/security/public/authentication/login/components/login_form/index.ts index d12ea30c784cb..f1b469f669c0e 100644 --- a/x-pack/plugins/security/public/authentication/login/components/login_form/index.ts +++ b/x-pack/plugins/security/public/authentication/login/components/login_form/index.ts @@ -5,4 +5,5 @@ * 2.0. */ +export type { LoginFormProps } from './login_form'; export { LoginForm, MessageType as LoginFormMessageType } from './login_form'; diff --git a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx index f60e525e0949d..b8808415fc60b 100644 --- a/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx +++ b/x-pack/plugins/security/public/authentication/login/components/login_form/login_form.tsx @@ -36,7 +36,7 @@ import type { HttpStart, IHttpFetchError, NotificationsStart } from 'src/core/pu import type { LoginSelector, LoginSelectorProvider } from '../../../../../common/login_state'; import { LoginValidator } from './validate_login'; -interface Props { +export interface LoginFormProps { http: HttpStart; notifications: NotificationsStart; selector: LoginSelector; @@ -78,7 +78,7 @@ export enum PageMode { LoginHelp, } -export class LoginForm extends Component { +export class LoginForm extends Component { private readonly validator: LoginValidator; /** @@ -88,7 +88,7 @@ export class LoginForm extends Component { */ private readonly suggestedProvider?: LoginSelectorProvider; - constructor(props: Props) { + constructor(props: LoginFormProps) { super(props); this.validator = new LoginValidator({ shouldValidate: false }); @@ -513,7 +513,7 @@ export class LoginForm extends Component { ); window.location.href = location; - } catch (err) { + } catch (err: any) { this.props.notifications.toasts.addError( err?.body?.message ? new Error(err?.body?.message) : err, { diff --git a/x-pack/plugins/security/public/authentication/login/login_page.tsx b/x-pack/plugins/security/public/authentication/login/login_page.tsx index 40438ac1c78f3..e22c38b956e8d 100644 --- a/x-pack/plugins/security/public/authentication/login/login_page.tsx +++ b/x-pack/plugins/security/public/authentication/login/login_page.tsx @@ -12,7 +12,6 @@ import classNames from 'classnames'; import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import { BehaviorSubject } from 'rxjs'; -import { parse } from 'url'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -23,6 +22,8 @@ import { LOGOUT_REASON_QUERY_STRING_PARAMETER, } from '../../../common/constants'; import type { LoginState } from '../../../common/login_state'; +import type { LogoutReason } from '../../../common/types'; +import type { LoginFormProps } from './components'; import { DisabledLoginForm, LoginForm, LoginFormMessageType } from './components'; interface Props { @@ -36,36 +37,33 @@ interface State { loginState: LoginState | null; } -const messageMap = new Map([ - [ - 'SESSION_EXPIRED', - { - type: LoginFormMessageType.Info, - content: i18n.translate('xpack.security.login.sessionExpiredDescription', { - defaultMessage: 'Your session has timed out. Please log in again.', - }), - }, - ], - [ - 'LOGGED_OUT', - { - type: LoginFormMessageType.Info, - content: i18n.translate('xpack.security.login.loggedOutDescription', { - defaultMessage: 'You have logged out of Elastic.', - }), - }, - ], - [ - 'UNAUTHENTICATED', - { - type: LoginFormMessageType.Danger, - content: i18n.translate('xpack.security.unauthenticated.errorDescription', { - defaultMessage: - "We hit an authentication error. Please check your credentials and try again. If you still can't log in, contact your system administrator.", - }), - }, - ], -]); +const loginFormMessages: Record> = { + SESSION_EXPIRED: { + type: LoginFormMessageType.Info, + content: i18n.translate('xpack.security.login.sessionExpiredDescription', { + defaultMessage: 'Your session has timed out. Please log in again.', + }), + }, + AUTHENTICATION_ERROR: { + type: LoginFormMessageType.Info, + content: i18n.translate('xpack.security.login.authenticationErrorDescription', { + defaultMessage: 'An unexpected authentication error occurred. Please log in again.', + }), + }, + LOGGED_OUT: { + type: LoginFormMessageType.Info, + content: i18n.translate('xpack.security.login.loggedOutDescription', { + defaultMessage: 'You have logged out of Elastic.', + }), + }, + UNAUTHENTICATED: { + type: LoginFormMessageType.Danger, + content: i18n.translate('xpack.security.unauthenticated.errorDescription', { + defaultMessage: + "We hit an authentication error. Please check your credentials and try again. If you still can't log in, contact your system administrator.", + }), + }, +}; export class LoginPage extends Component { state = { loginState: null } as State; @@ -77,7 +75,7 @@ export class LoginPage extends Component { try { this.setState({ loginState: await this.props.http.get('/internal/security/login_state') }); } catch (err) { - this.props.fatalErrors.add(err); + this.props.fatalErrors.add(err as Error); } loadingCount$.next(0); @@ -235,17 +233,19 @@ export class LoginPage extends Component { ); } - const query = parse(window.location.href, true).query; + const { searchParams } = new URL(window.location.href); + return ( ); }; diff --git a/x-pack/plugins/security/public/session/session_expired.mock.ts b/x-pack/plugins/security/public/session/session_expired.mock.ts index f3a0e2b88f7eb..aa9134556cab7 100644 --- a/x-pack/plugins/security/public/session/session_expired.mock.ts +++ b/x-pack/plugins/security/public/session/session_expired.mock.ts @@ -5,10 +5,12 @@ * 2.0. */ -import type { ISessionExpired } from './session_expired'; +import type { PublicMethodsOf } from '@kbn/utility-types'; + +import type { SessionExpired } from './session_expired'; export function createSessionExpiredMock() { return { logout: jest.fn(), - } as jest.Mocked; + } as jest.Mocked>; } diff --git a/x-pack/plugins/security/public/session/session_expired.test.ts b/x-pack/plugins/security/public/session/session_expired.test.ts index 40059722cee87..12fec1665ff00 100644 --- a/x-pack/plugins/security/public/session/session_expired.test.ts +++ b/x-pack/plugins/security/public/session/session_expired.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { LogoutReason } from '../../common/types'; import { SessionExpired } from './session_expired'; describe('#logout', () => { @@ -41,7 +42,7 @@ describe('#logout', () => { it(`redirects user to the logout URL with 'msg' and 'next' parameters`, async () => { const sessionExpired = new SessionExpired(LOGOUT_URL, TENANT); - sessionExpired.logout(); + sessionExpired.logout(LogoutReason.SESSION_EXPIRED); const next = `&next=${encodeURIComponent(CURRENT_URL)}`; await expect(window.location.assign).toHaveBeenCalledWith( @@ -49,12 +50,22 @@ describe('#logout', () => { ); }); + it(`redirects user to the logout URL with custom reason 'msg'`, async () => { + const sessionExpired = new SessionExpired(LOGOUT_URL, TENANT); + sessionExpired.logout(LogoutReason.AUTHENTICATION_ERROR); + + const next = `&next=${encodeURIComponent(CURRENT_URL)}`; + await expect(window.location.assign).toHaveBeenCalledWith( + `${LOGOUT_URL}?msg=AUTHENTICATION_ERROR${next}` + ); + }); + it(`adds 'provider' parameter when sessionStorage contains the provider name for this tenant`, async () => { const providerName = 'basic'; mockGetItem.mockReturnValueOnce(providerName); const sessionExpired = new SessionExpired(LOGOUT_URL, TENANT); - sessionExpired.logout(); + sessionExpired.logout(LogoutReason.SESSION_EXPIRED); expect(mockGetItem).toHaveBeenCalledTimes(1); expect(mockGetItem).toHaveBeenCalledWith(`${TENANT}/session_provider`); diff --git a/x-pack/plugins/security/public/session/session_expired.ts b/x-pack/plugins/security/public/session/session_expired.ts index 0bfbde1f31b36..ad1d4658817b4 100644 --- a/x-pack/plugins/security/public/session/session_expired.ts +++ b/x-pack/plugins/security/public/session/session_expired.ts @@ -10,10 +10,7 @@ import { LOGOUT_REASON_QUERY_STRING_PARAMETER, NEXT_URL_QUERY_STRING_PARAMETER, } from '../../common/constants'; - -export interface ISessionExpired { - logout(): void; -} +import type { LogoutReason } from '../../common/types'; const getNextParameter = () => { const { location } = window; @@ -32,11 +29,11 @@ const getProviderParameter = (tenant: string) => { export class SessionExpired { constructor(private logoutUrl: string, private tenant: string) {} - logout() { + logout(reason: LogoutReason) { const next = getNextParameter(); const provider = getProviderParameter(this.tenant); window.location.assign( - `${this.logoutUrl}?${LOGOUT_REASON_QUERY_STRING_PARAMETER}=SESSION_EXPIRED${next}${provider}` + `${this.logoutUrl}?${LOGOUT_REASON_QUERY_STRING_PARAMETER}=${reason}${next}${provider}` ); } } diff --git a/x-pack/plugins/security/public/session/session_timeout.ts b/x-pack/plugins/security/public/session/session_timeout.ts index 7a23f1bb25ad2..8b83f34f642fd 100644 --- a/x-pack/plugins/security/public/session/session_timeout.ts +++ b/x-pack/plugins/security/public/session/session_timeout.ts @@ -24,9 +24,10 @@ import { SESSION_GRACE_PERIOD_MS, SESSION_ROUTE, } from '../../common/constants'; +import { LogoutReason } from '../../common/types'; import type { SessionInfo } from '../../common/types'; import { createSessionExpirationToast } from './session_expiration_toast'; -import type { ISessionExpired } from './session_expired'; +import type { SessionExpired } from './session_expired'; export interface SessionState extends Pick { lastExtensionTime: number; @@ -58,7 +59,7 @@ export class SessionTimeout { constructor( private notifications: NotificationsSetup, - private sessionExpired: ISessionExpired, + private sessionExpired: Pick, private http: HttpSetup, private tenant: string ) {} @@ -168,7 +169,10 @@ export class SessionTimeout { const fetchSessionInMs = showWarningInMs - SESSION_CHECK_MS; // Schedule logout when session is about to expire - this.stopLogoutTimer = startTimer(() => this.sessionExpired.logout(), logoutInMs); + this.stopLogoutTimer = startTimer( + () => this.sessionExpired.logout(LogoutReason.SESSION_EXPIRED), + logoutInMs + ); // Hide warning if session has been extended if (showWarningInMs > 0) { diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts index 35bdb911b6ed1..6d955bb5ad89e 100644 --- a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts @@ -56,6 +56,7 @@ it(`logs out 401 responses`, async () => { await drainPromiseQueue(); expect(fetchResolved).toBe(false); expect(fetchRejected).toBe(false); + expect(sessionExpired.logout).toHaveBeenCalledWith('AUTHENTICATION_ERROR'); }); it(`ignores anonymous paths`, async () => { diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts index 43945c8f43c0f..92c5c4485bcad 100644 --- a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts @@ -12,6 +12,7 @@ import type { IHttpInterceptController, } from 'src/core/public'; +import { LogoutReason } from '../../common/types'; import type { SessionExpired } from './session_expired'; export class UnauthorizedResponseHttpInterceptor implements HttpInterceptor { @@ -39,7 +40,7 @@ export class UnauthorizedResponseHttpInterceptor implements HttpInterceptor { } if (response.status === 401) { - this.sessionExpired.logout(); + this.sessionExpired.logout(LogoutReason.AUTHENTICATION_ERROR); controller.halt(); } } From a4eab441c0e5494389922e02c1d83c4814dc7518 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 4 Oct 2021 13:36:12 -0400 Subject: [PATCH 57/98] [Fleet] Use elastic_agent package to build monitoring permissions for agent (#112730) --- .../fleet/common/constants/agent_policy.ts | 14 ++ .../plugins/fleet/server/constants/index.ts | 1 + .../full_agent_policy.test.ts.snap | 57 ++--- .../monitoring_permissions.test.ts.snap | 195 ++++++++++++++++++ .../agent_policies/full_agent_policy.test.ts | 47 +++++ .../agent_policies/full_agent_policy.ts | 78 +++---- .../monitoring_permissions.test.ts | 101 +++++++++ .../agent_policies/monitoring_permissions.ts | 91 ++++++++ 8 files changed, 485 insertions(+), 99 deletions(-) create mode 100644 x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/monitoring_permissions.test.ts.snap create mode 100644 x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.test.ts create mode 100644 x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.ts diff --git a/x-pack/plugins/fleet/common/constants/agent_policy.ts b/x-pack/plugins/fleet/common/constants/agent_policy.ts index d0bde39e9f2d7..95078d8ead84f 100644 --- a/x-pack/plugins/fleet/common/constants/agent_policy.ts +++ b/x-pack/plugins/fleet/common/constants/agent_policy.ts @@ -11,3 +11,17 @@ export const agentPolicyStatuses = { Active: 'active', Inactive: 'inactive', } as const; + +export const AGENT_POLICY_DEFAULT_MONITORING_DATASETS = [ + 'elastic_agent', + 'elastic_agent.elastic_agent', + 'elastic_agent.apm_server', + 'elastic_agent.filebeat', + 'elastic_agent.fleet_server', + 'elastic_agent.metricbeat', + 'elastic_agent.osquerybeat', + 'elastic_agent.packetbeat', + 'elastic_agent.endpoint_security', + 'elastic_agent.auditbeat', + 'elastic_agent.heartbeat', +]; diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index 0dcd5e7f47800..2ce457242c6b5 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -50,6 +50,7 @@ export { DEFAULT_OUTPUT, DEFAULT_PACKAGES, PACKAGE_POLICY_DEFAULT_INDEX_PRIVILEGES, + AGENT_POLICY_DEFAULT_MONITORING_DATASETS, // Fleet Server index FLEET_SERVER_SERVERS_INDEX, ENROLLMENT_API_KEYS_INDEX, diff --git a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap index 970bccbafa634..36044d35703ee 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap +++ b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/full_agent_policy.test.ts.snap @@ -51,25 +51,14 @@ Object { "cluster": Array [ "monitor", ], + }, + "_elastic_agent_monitoring": Object { "indices": Array [ Object { "names": Array [ - "metrics-elastic_agent-default", - "metrics-elastic_agent.elastic_agent-default", - "metrics-elastic_agent.apm_server-default", - "metrics-elastic_agent.filebeat-default", - "metrics-elastic_agent.fleet_server-default", - "metrics-elastic_agent.metricbeat-default", - "metrics-elastic_agent.osquerybeat-default", - "metrics-elastic_agent.packetbeat-default", - "metrics-elastic_agent.endpoint_security-default", - "metrics-elastic_agent.auditbeat-default", - "metrics-elastic_agent.heartbeat-default", - ], - "privileges": Array [ - "auto_configure", - "create_doc", + "metrics-default", ], + "privileges": Array [], }, ], }, @@ -148,25 +137,14 @@ Object { "cluster": Array [ "monitor", ], + }, + "_elastic_agent_monitoring": Object { "indices": Array [ Object { "names": Array [ - "metrics-elastic_agent-default", - "metrics-elastic_agent.elastic_agent-default", - "metrics-elastic_agent.apm_server-default", - "metrics-elastic_agent.filebeat-default", - "metrics-elastic_agent.fleet_server-default", - "metrics-elastic_agent.metricbeat-default", - "metrics-elastic_agent.osquerybeat-default", - "metrics-elastic_agent.packetbeat-default", - "metrics-elastic_agent.endpoint_security-default", - "metrics-elastic_agent.auditbeat-default", - "metrics-elastic_agent.heartbeat-default", - ], - "privileges": Array [ - "auto_configure", - "create_doc", + "metrics-default", ], + "privileges": Array [], }, ], }, @@ -245,25 +223,14 @@ Object { "cluster": Array [ "monitor", ], + }, + "_elastic_agent_monitoring": Object { "indices": Array [ Object { "names": Array [ - "metrics-elastic_agent-default", - "metrics-elastic_agent.elastic_agent-default", - "metrics-elastic_agent.apm_server-default", - "metrics-elastic_agent.filebeat-default", - "metrics-elastic_agent.fleet_server-default", - "metrics-elastic_agent.metricbeat-default", - "metrics-elastic_agent.osquerybeat-default", - "metrics-elastic_agent.packetbeat-default", - "metrics-elastic_agent.endpoint_security-default", - "metrics-elastic_agent.auditbeat-default", - "metrics-elastic_agent.heartbeat-default", - ], - "privileges": Array [ - "auto_configure", - "create_doc", + "metrics-default", ], + "privileges": Array [], }, ], }, diff --git a/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/monitoring_permissions.test.ts.snap b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/monitoring_permissions.test.ts.snap new file mode 100644 index 0000000000000..a54d4beb6c041 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agent_policies/__snapshots__/monitoring_permissions.test.ts.snap @@ -0,0 +1,195 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`getMonitoringPermissions With elastic agent package installed should return default logs and metrics permissions if both are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [ + Object { + "names": Array [ + "logs-elastic_agent.metricbeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + Object { + "names": Array [ + "metrics-elastic_agent.metricbeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + Object { + "names": Array [ + "logs-elastic_agent.filebeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + Object { + "names": Array [ + "metrics-elastic_agent.filebeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + ], + }, +} +`; + +exports[`getMonitoringPermissions With elastic agent package installed should return default logs permissions if only logs are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [ + Object { + "names": Array [ + "logs-elastic_agent.metricbeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + Object { + "names": Array [ + "logs-elastic_agent.filebeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + ], + }, +} +`; + +exports[`getMonitoringPermissions With elastic agent package installed should return default metrics permissions if only metrics are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [ + Object { + "names": Array [ + "metrics-elastic_agent.metricbeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + Object { + "names": Array [ + "metrics-elastic_agent.filebeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + ], + }, +} +`; + +exports[`getMonitoringPermissions Without elastic agent package installed should return default logs and metrics permissions if both are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [ + Object { + "names": Array [ + "logs-elastic_agent-testnamespace123", + "logs-elastic_agent.elastic_agent-testnamespace123", + "logs-elastic_agent.apm_server-testnamespace123", + "logs-elastic_agent.filebeat-testnamespace123", + "logs-elastic_agent.fleet_server-testnamespace123", + "logs-elastic_agent.metricbeat-testnamespace123", + "logs-elastic_agent.osquerybeat-testnamespace123", + "logs-elastic_agent.packetbeat-testnamespace123", + "logs-elastic_agent.endpoint_security-testnamespace123", + "logs-elastic_agent.auditbeat-testnamespace123", + "logs-elastic_agent.heartbeat-testnamespace123", + "metrics-elastic_agent-testnamespace123", + "metrics-elastic_agent.elastic_agent-testnamespace123", + "metrics-elastic_agent.apm_server-testnamespace123", + "metrics-elastic_agent.filebeat-testnamespace123", + "metrics-elastic_agent.fleet_server-testnamespace123", + "metrics-elastic_agent.metricbeat-testnamespace123", + "metrics-elastic_agent.osquerybeat-testnamespace123", + "metrics-elastic_agent.packetbeat-testnamespace123", + "metrics-elastic_agent.endpoint_security-testnamespace123", + "metrics-elastic_agent.auditbeat-testnamespace123", + "metrics-elastic_agent.heartbeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + ], + }, +} +`; + +exports[`getMonitoringPermissions Without elastic agent package installed should return default logs permissions if only logs are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [ + Object { + "names": Array [ + "logs-elastic_agent-testnamespace123", + "logs-elastic_agent.elastic_agent-testnamespace123", + "logs-elastic_agent.apm_server-testnamespace123", + "logs-elastic_agent.filebeat-testnamespace123", + "logs-elastic_agent.fleet_server-testnamespace123", + "logs-elastic_agent.metricbeat-testnamespace123", + "logs-elastic_agent.osquerybeat-testnamespace123", + "logs-elastic_agent.packetbeat-testnamespace123", + "logs-elastic_agent.endpoint_security-testnamespace123", + "logs-elastic_agent.auditbeat-testnamespace123", + "logs-elastic_agent.heartbeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + ], + }, +} +`; + +exports[`getMonitoringPermissions Without elastic agent package installed should return default metrics permissions if only metrics are enabled 1`] = ` +Object { + "_elastic_agent_monitoring": Object { + "indices": Array [ + Object { + "names": Array [ + "metrics-elastic_agent-testnamespace123", + "metrics-elastic_agent.elastic_agent-testnamespace123", + "metrics-elastic_agent.apm_server-testnamespace123", + "metrics-elastic_agent.filebeat-testnamespace123", + "metrics-elastic_agent.fleet_server-testnamespace123", + "metrics-elastic_agent.metricbeat-testnamespace123", + "metrics-elastic_agent.osquerybeat-testnamespace123", + "metrics-elastic_agent.packetbeat-testnamespace123", + "metrics-elastic_agent.endpoint_security-testnamespace123", + "metrics-elastic_agent.auditbeat-testnamespace123", + "metrics-elastic_agent.heartbeat-testnamespace123", + ], + "privileges": Array [ + "auto_configure", + "create_doc", + ], + }, + ], + }, +} +`; diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts index 8df1234982ee6..9a9b200d14130 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts @@ -13,7 +13,11 @@ import { agentPolicyService } from '../agent_policy'; import { agentPolicyUpdateEventHandler } from '../agent_policy_update'; import { getFullAgentPolicy } from './full_agent_policy'; +import { getMonitoringPermissions } from './monitoring_permissions'; +const mockedGetElasticAgentMonitoringPermissions = getMonitoringPermissions as jest.Mock< + ReturnType +>; const mockedAgentPolicyService = agentPolicyService as jest.Mocked; function mockAgentPolicy(data: Partial) { @@ -87,6 +91,8 @@ jest.mock('../agent_policy_update'); jest.mock('../agents'); jest.mock('../package_policy'); +jest.mock('./monitoring_permissions'); + function getAgentPolicyUpdateMock() { return agentPolicyUpdateEventHandler as unknown as jest.Mock< typeof agentPolicyUpdateEventHandler @@ -97,6 +103,29 @@ describe('getFullAgentPolicy', () => { beforeEach(() => { getAgentPolicyUpdateMock().mockClear(); mockedAgentPolicyService.get.mockReset(); + mockedGetElasticAgentMonitoringPermissions.mockReset(); + mockedGetElasticAgentMonitoringPermissions.mockImplementation( + async (soClient, { logs, metrics }, namespace) => { + const names: string[] = []; + if (logs) { + names.push(`logs-${namespace}`); + } + if (metrics) { + names.push(`metrics-${namespace}`); + } + + return { + _elastic_agent_monitoring: { + indices: [ + { + names, + privileges: [], + }, + ], + }, + }; + } + ); }); it('should return a policy without monitoring if monitoring is not enabled', async () => { @@ -200,6 +229,24 @@ describe('getFullAgentPolicy', () => { }); }); + it('should get the permissions for monitoring', async () => { + mockAgentPolicy({ + namespace: 'testnamespace', + revision: 1, + monitoring_enabled: ['metrics'], + }); + await getFullAgentPolicy(savedObjectsClientMock.create(), 'agent-policy'); + + expect(mockedGetElasticAgentMonitoringPermissions).toHaveBeenCalledWith( + expect.anything(), + { + logs: false, + metrics: true, + }, + 'testnamespace' + ); + }); + it('should support a different monitoring output', async () => { mockAgentPolicy({ namespace: 'default', diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts index 4e8b3a2c1952e..561c463b998d4 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts @@ -24,21 +24,9 @@ import { import { storedPackagePoliciesToAgentInputs, dataTypes, outputType } from '../../../common'; import type { FullAgentPolicyOutputPermissions } from '../../../common'; import { getSettings } from '../settings'; -import { PACKAGE_POLICY_DEFAULT_INDEX_PRIVILEGES, DEFAULT_OUTPUT } from '../../constants'; - -const MONITORING_DATASETS = [ - 'elastic_agent', - 'elastic_agent.elastic_agent', - 'elastic_agent.apm_server', - 'elastic_agent.filebeat', - 'elastic_agent.fleet_server', - 'elastic_agent.metricbeat', - 'elastic_agent.osquerybeat', - 'elastic_agent.packetbeat', - 'elastic_agent.endpoint_security', - 'elastic_agent.auditbeat', - 'elastic_agent.heartbeat', -]; +import { DEFAULT_OUTPUT } from '../../constants'; + +import { getMonitoringPermissions } from './monitoring_permissions'; export async function getFullAgentPolicy( soClient: SavedObjectsClientContract, @@ -125,41 +113,17 @@ export async function getFullAgentPolicy( cluster: DEFAULT_PERMISSIONS.cluster, }; - // TODO: fetch this from the elastic agent package https://github.com/elastic/kibana/issues/107738 - const monitoringNamespace = fullAgentPolicy.agent?.monitoring.namespace; - const monitoringPermissions: FullAgentPolicyOutputPermissions = - monitoringOutputId === dataOutputId - ? dataPermissions - : { - _elastic_agent_checks: { - cluster: DEFAULT_PERMISSIONS.cluster, - }, - }; - if ( - fullAgentPolicy.agent?.monitoring.enabled && - monitoringNamespace && - monitoringOutput && - monitoringOutput.type === outputType.Elasticsearch - ) { - let names: string[] = []; - if (fullAgentPolicy.agent.monitoring.logs) { - names = names.concat( - MONITORING_DATASETS.map((dataset) => `logs-${dataset}-${monitoringNamespace}`) - ); - } - if (fullAgentPolicy.agent.monitoring.metrics) { - names = names.concat( - MONITORING_DATASETS.map((dataset) => `metrics-${dataset}-${monitoringNamespace}`) - ); - } - - monitoringPermissions._elastic_agent_checks.indices = [ - { - names, - privileges: PACKAGE_POLICY_DEFAULT_INDEX_PRIVILEGES, - }, - ]; - } + const monitoringPermissions = await getMonitoringPermissions( + soClient, + { + logs: agentPolicy.monitoring_enabled?.includes(dataTypes.Logs) ?? false, + metrics: agentPolicy.monitoring_enabled?.includes(dataTypes.Metrics) ?? false, + }, + agentPolicy.namespace + ); + monitoringPermissions._elastic_agent_checks = { + cluster: DEFAULT_PERMISSIONS.cluster, + }; // Only add permissions if output.type is "elasticsearch" fullAgentPolicy.output_permissions = Object.keys(fullAgentPolicy.outputs).reduce< @@ -167,10 +131,16 @@ export async function getFullAgentPolicy( >((outputPermissions, outputId) => { const output = fullAgentPolicy.outputs[outputId]; if (output && output.type === outputType.Elasticsearch) { - outputPermissions[outputId] = - outputId === getOutputIdForAgentPolicy(dataOutput) - ? dataPermissions - : monitoringPermissions; + const permissions: FullAgentPolicyOutputPermissions = {}; + if (outputId === getOutputIdForAgentPolicy(monitoringOutput)) { + Object.assign(permissions, monitoringPermissions); + } + + if (outputId === getOutputIdForAgentPolicy(dataOutput)) { + Object.assign(permissions, dataPermissions); + } + + outputPermissions[outputId] = permissions; } return outputPermissions; }, {}); diff --git a/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.test.ts b/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.test.ts new file mode 100644 index 0000000000000..3d928bed0f661 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.test.ts @@ -0,0 +1,101 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { savedObjectsClientMock } from 'src/core/server/mocks'; + +import type { Installation, PackageInfo } from '../../types'; +import { getPackageInfo, getInstallation } from '../epm/packages'; + +import { getMonitoringPermissions } from './monitoring_permissions'; + +jest.mock('../epm/packages'); + +const mockedGetInstallation = getInstallation as jest.Mock>; +const mockedGetPackageInfo = getPackageInfo as jest.Mock>; + +describe('getMonitoringPermissions', () => { + describe('Without elastic agent package installed', () => { + it('should return default logs and metrics permissions if both are enabled', async () => { + const permissions = await getMonitoringPermissions( + savedObjectsClientMock.create(), + { logs: true, metrics: true }, + 'testnamespace123' + ); + expect(permissions).toMatchSnapshot(); + }); + it('should return default logs permissions if only logs are enabled', async () => { + const permissions = await getMonitoringPermissions( + savedObjectsClientMock.create(), + { logs: true, metrics: false }, + 'testnamespace123' + ); + expect(permissions).toMatchSnapshot(); + }); + it('should return default metrics permissions if only metrics are enabled', async () => { + const permissions = await getMonitoringPermissions( + savedObjectsClientMock.create(), + { logs: false, metrics: true }, + 'testnamespace123' + ); + expect(permissions).toMatchSnapshot(); + }); + }); + + describe('With elastic agent package installed', () => { + beforeEach(() => { + // Mock a simplified elastic agent package with only 4 datastreams logs and metrics for filebeat and metricbeat + mockedGetInstallation.mockResolvedValue({ + name: 'elastic_agent', + version: '1.0.0', + } as Installation); + mockedGetPackageInfo.mockResolvedValue({ + data_streams: [ + { + type: 'logs', + dataset: 'elastic_agent.metricbeat', + }, + { + type: 'metrics', + dataset: 'elastic_agent.metricbeat', + }, + { + type: 'logs', + dataset: 'elastic_agent.filebeat', + }, + { + type: 'metrics', + dataset: 'elastic_agent.filebeat', + }, + ], + } as PackageInfo); + }); + it('should return default logs and metrics permissions if both are enabled', async () => { + const permissions = await getMonitoringPermissions( + savedObjectsClientMock.create(), + { logs: true, metrics: true }, + 'testnamespace123' + ); + expect(permissions).toMatchSnapshot(); + }); + it('should return default logs permissions if only logs are enabled', async () => { + const permissions = await getMonitoringPermissions( + savedObjectsClientMock.create(), + { logs: true, metrics: false }, + 'testnamespace123' + ); + expect(permissions).toMatchSnapshot(); + }); + it('should return default metrics permissions if only metrics are enabled', async () => { + const permissions = await getMonitoringPermissions( + savedObjectsClientMock.create(), + { logs: false, metrics: true }, + 'testnamespace123' + ); + expect(permissions).toMatchSnapshot(); + }); + }); +}); diff --git a/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.ts b/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.ts new file mode 100644 index 0000000000000..3533d829e1342 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agent_policies/monitoring_permissions.ts @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SavedObjectsClientContract } from 'kibana/server'; + +import { getPackageInfo, getInstallation } from '../epm/packages'; +import { getDataStreamPrivileges } from '../package_policies_to_agent_permissions'; +import { + PACKAGE_POLICY_DEFAULT_INDEX_PRIVILEGES, + AGENT_POLICY_DEFAULT_MONITORING_DATASETS, +} from '../../constants'; +import type { FullAgentPolicyOutputPermissions } from '../../../common'; +import { FLEET_ELASTIC_AGENT_PACKAGE } from '../../../common'; +import { dataTypes } from '../../../common'; + +function buildDefault(enabled: { logs: boolean; metrics: boolean }, namespace: string) { + let names: string[] = []; + if (enabled.logs) { + names = names.concat( + AGENT_POLICY_DEFAULT_MONITORING_DATASETS.map((dataset) => `logs-${dataset}-${namespace}`) + ); + } + if (enabled.metrics) { + names = names.concat( + AGENT_POLICY_DEFAULT_MONITORING_DATASETS.map((dataset) => `metrics-${dataset}-${namespace}`) + ); + } + + return { + _elastic_agent_monitoring: { + indices: [ + { + names, + privileges: PACKAGE_POLICY_DEFAULT_INDEX_PRIVILEGES, + }, + ], + }, + }; +} + +export async function getMonitoringPermissions( + soClient: SavedObjectsClientContract, + enabled: { logs: boolean; metrics: boolean }, + namespace: string +): Promise { + const installation = await getInstallation({ + savedObjectsClient: soClient, + pkgName: FLEET_ELASTIC_AGENT_PACKAGE, + }); + + if (!installation) { + return buildDefault(enabled, namespace); + } + + const pkg = await getPackageInfo({ + savedObjectsClient: soClient, + pkgName: installation.name, + pkgVersion: installation.version, + }); + + if (!pkg.data_streams || pkg.data_streams.length === 0) { + return buildDefault(enabled, namespace); + } + + return { + _elastic_agent_monitoring: { + indices: pkg.data_streams + .map((ds) => { + if (ds.type === dataTypes.Logs && !enabled.logs) { + return; + } + if (ds.type === dataTypes.Metrics && !enabled.metrics) { + return; + } + return getDataStreamPrivileges(ds, namespace); + }) + .filter( + ( + i + ): i is { + names: string[]; + privileges: string[]; + } => typeof i !== 'undefined' + ), + }, + }; +} From eddbc8db6f8d287cff91c59d3271f156d0a25c94 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Mon, 4 Oct 2021 13:36:45 -0400 Subject: [PATCH 58/98] Update doc slugs to improve analytic tracking, move to appropriate folders (#113630) * Update the slugs to improve google analytics drilldown tracking * more slug updates * Fix some formatting issues in building blocks * update paths Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- STYLEGUIDE.mdx | 2 +- dev_docs/api_welcome.mdx | 2 +- .../{ => contributing}/best_practices.mdx | 2 +- .../{ => contributing}/dev_principles.mdx | 8 +- dev_docs/contributing/how_we_use_github.mdx | 2 +- dev_docs/getting_started/add_data.mdx | 2 +- dev_docs/getting_started/dev_welcome.mdx | 2 +- .../getting_started/hello_world_plugin.mdx | 2 +- .../setting_up_a_development_env.mdx | 2 +- .../{ => getting_started}/troubleshooting.mdx | 2 +- dev_docs/key_concepts/anatomy_of_a_plugin.mdx | 2 +- .../{ => key_concepts}/building_blocks.mdx | 98 +++++---- dev_docs/key_concepts/data_views.mdx | 11 +- .../kibana_platform_plugin_intro.mdx | 2 +- dev_docs/key_concepts/performance.mdx | 20 +- dev_docs/key_concepts/persistable_state.mdx | 27 ++- dev_docs/key_concepts/saved_objects.mdx | 39 ++-- .../building_a_kibana_distributable.mdx | 2 +- dev_docs/tutorials/data/search.mdx | 192 +++++++++--------- dev_docs/tutorials/debugging.mdx | 6 +- dev_docs/tutorials/saved_objects.mdx | 2 +- dev_docs/tutorials/submit_a_pull_request.mdx | 2 +- dev_docs/tutorials/testing_plugins.mdx | 2 +- legacy_rfcs/README.md | 2 +- src/plugins/data/README.mdx | 2 +- src/plugins/usage_collection/README.mdx | 2 +- 27 files changed, 220 insertions(+), 219 deletions(-) rename dev_docs/{ => contributing}/best_practices.mdx (99%) rename dev_docs/{ => contributing}/dev_principles.mdx (98%) rename dev_docs/{ => getting_started}/troubleshooting.mdx (94%) rename dev_docs/{ => key_concepts}/building_blocks.mdx (51%) rename dev_docs/{ => key_concepts}/kibana_platform_plugin_intro.mdx (99%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 14dfaa84cebb6..8a19562eaff47 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,5 @@ # Contributing to Kibana -If you are an employee at Elastic, please check out our Developer Guide [here](https://docs.elastic.dev/kibana-dev-docs/welcome). +If you are an employee at Elastic, please check out our Developer Guide [here](https://docs.elastic.dev/kibana-dev-docs/getting-started/welcome). If you are an external developer, we have a legacy developer guide [here](https://www.elastic.co/guide/en/kibana/master/development.html), or you can view the raw docs from our new, internal Developer Guide [here](./dev_docs/getting_started/dev_welcome.mdx). Eventually, our internal Developer Guide will be opened for public consumption. diff --git a/STYLEGUIDE.mdx b/STYLEGUIDE.mdx index 95f29c674da9b..56117d0fd7e59 100644 --- a/STYLEGUIDE.mdx +++ b/STYLEGUIDE.mdx @@ -1,6 +1,6 @@ --- id: kibStyleGuide -slug: /kibana-dev-docs/styleguide +slug: /kibana-dev-docs/contributing/styleguide title: Style Guide summary: JavaScript/TypeScript styleguide. date: 2021-05-06 diff --git a/dev_docs/api_welcome.mdx b/dev_docs/api_welcome.mdx index be9281113b3d5..00d5bfb9644af 100644 --- a/dev_docs/api_welcome.mdx +++ b/dev_docs/api_welcome.mdx @@ -1,6 +1,6 @@ --- id: kibDevDocsApiWelcome -slug: /kibana-dev-docs/api-welcome +slug: /kibana-dev-docs/api-meta/welcome title: Welcome summary: How to use our automatically generated API documentation date: 2021-02-25 diff --git a/dev_docs/best_practices.mdx b/dev_docs/contributing/best_practices.mdx similarity index 99% rename from dev_docs/best_practices.mdx rename to dev_docs/contributing/best_practices.mdx index 767e525c0afa7..27983d92ed121 100644 --- a/dev_docs/best_practices.mdx +++ b/dev_docs/contributing/best_practices.mdx @@ -1,6 +1,6 @@ --- id: kibBestPractices -slug: /kibana-dev-docs/best-practices +slug: /kibana-dev-docs/contributing/best-practices title: Best practices summary: Best practices to follow when building a Kibana plugin. date: 2021-03-17 diff --git a/dev_docs/dev_principles.mdx b/dev_docs/contributing/dev_principles.mdx similarity index 98% rename from dev_docs/dev_principles.mdx rename to dev_docs/contributing/dev_principles.mdx index 4b238ea24f694..0b8f68d232367 100644 --- a/dev_docs/dev_principles.mdx +++ b/dev_docs/contributing/dev_principles.mdx @@ -1,10 +1,10 @@ --- id: kibDevPrinciples -slug: /kibana-dev-docs/dev-principles +slug: /kibana-dev-docs/contributing/dev-principles title: Developer principles -summary: Follow our development principles to help keep our code base stable, maintainable and scalable. +summary: Follow our development principles to help keep our code base stable, maintainable and scalable. date: 2021-03-04 -tags: ['kibana','onboarding', 'dev', 'architecture'] +tags: ['kibana', 'onboarding', 'dev', 'architecture'] --- Over time, the Kibana project has been shaped by certain principles. Like Kibana itself, some of these principles were formed by intention while others were the result of evolution and circumstance, but today all are important for the continued success and maintainability of Kibana. @@ -117,4 +117,4 @@ The primary consumers of the code we write, the APIs that we create, and the fea Features that we anticipate end users, admins, and plugin developers consuming should be documented through our official docs, but module-level READMEs and code comments are also appropriate. -Documentation is critical part of developing features and code, so an undocumented feature is an incomplete feature. \ No newline at end of file +Documentation is critical part of developing features and code, so an undocumented feature is an incomplete feature. diff --git a/dev_docs/contributing/how_we_use_github.mdx b/dev_docs/contributing/how_we_use_github.mdx index f18bcbcf556f5..ff7901fdf08da 100644 --- a/dev_docs/contributing/how_we_use_github.mdx +++ b/dev_docs/contributing/how_we_use_github.mdx @@ -1,6 +1,6 @@ --- id: kibGitHub -slug: /kibana-dev-docs/github +slug: /kibana-dev-docs/contributing/github title: How we use Github summary: Forking, branching, committing and using labels in the Kibana GitHub repo date: 2021-09-16 diff --git a/dev_docs/getting_started/add_data.mdx b/dev_docs/getting_started/add_data.mdx index b09e3f6262e77..46822b82fc40d 100644 --- a/dev_docs/getting_started/add_data.mdx +++ b/dev_docs/getting_started/add_data.mdx @@ -1,6 +1,6 @@ --- id: kibDevAddData -slug: /kibana-dev-docs/tutorial/sample-data +slug: /kibana-dev-docs/getting-started/sample-data title: Add data summary: Learn how to add data to Kibana date: 2021-08-11 diff --git a/dev_docs/getting_started/dev_welcome.mdx b/dev_docs/getting_started/dev_welcome.mdx index 5e569bd377ee0..4080e0850b946 100644 --- a/dev_docs/getting_started/dev_welcome.mdx +++ b/dev_docs/getting_started/dev_welcome.mdx @@ -1,6 +1,6 @@ --- id: kibDevDocsWelcome -slug: /kibana-dev-docs/welcome +slug: /kibana-dev-docs/getting-started/welcome title: Welcome summary: Build custom solutions and applications on top of Kibana. date: 2021-01-02 diff --git a/dev_docs/getting_started/hello_world_plugin.mdx b/dev_docs/getting_started/hello_world_plugin.mdx index 7c02d2807472c..b95d0cac201fc 100644 --- a/dev_docs/getting_started/hello_world_plugin.mdx +++ b/dev_docs/getting_started/hello_world_plugin.mdx @@ -1,6 +1,6 @@ --- id: kibHelloWorldApp -slug: /kibana-dev-docs/hello-world-app +slug: /kibana-dev-docs/getting-started/hello-world-app title: Hello World summary: Build a very basic plugin that registers an application that says "Hello World!". date: 2021-08-03 diff --git a/dev_docs/getting_started/setting_up_a_development_env.mdx b/dev_docs/getting_started/setting_up_a_development_env.mdx index 04e0511e255b1..4338083b1bc8d 100644 --- a/dev_docs/getting_started/setting_up_a_development_env.mdx +++ b/dev_docs/getting_started/setting_up_a_development_env.mdx @@ -1,6 +1,6 @@ --- id: kibDevTutorialSetupDevEnv -slug: /kibana-dev-docs/tutorial/setup-dev-env +slug: /kibana-dev-docs/getting-started/setup-dev-env title: Set up a Development Environment summary: Learn how to setup a development environment for contributing to the Kibana repository date: 2021-04-26 diff --git a/dev_docs/troubleshooting.mdx b/dev_docs/getting_started/troubleshooting.mdx similarity index 94% rename from dev_docs/troubleshooting.mdx rename to dev_docs/getting_started/troubleshooting.mdx index f624a8cd77507..e0adfbad86a84 100644 --- a/dev_docs/troubleshooting.mdx +++ b/dev_docs/getting_started/troubleshooting.mdx @@ -1,6 +1,6 @@ --- id: kibTroubleshooting -slug: /kibana-dev-docs/troubleshooting +slug: /kibana-dev-docs/getting-started/troubleshooting title: Troubleshooting summary: A collection of tips for working around strange issues. date: 2021-09-08 diff --git a/dev_docs/key_concepts/anatomy_of_a_plugin.mdx b/dev_docs/key_concepts/anatomy_of_a_plugin.mdx index 3739f907c3d87..ca9119f4d21b3 100644 --- a/dev_docs/key_concepts/anatomy_of_a_plugin.mdx +++ b/dev_docs/key_concepts/anatomy_of_a_plugin.mdx @@ -1,6 +1,6 @@ --- id: kibDevAnatomyOfAPlugin -slug: /kibana-dev-docs/anatomy-of-a-plugin +slug: /kibana-dev-docs/key-concepts/anatomy-of-a-plugin title: Anatomy of a plugin summary: Anatomy of a Kibana plugin. date: 2021-08-03 diff --git a/dev_docs/building_blocks.mdx b/dev_docs/key_concepts/building_blocks.mdx similarity index 51% rename from dev_docs/building_blocks.mdx rename to dev_docs/key_concepts/building_blocks.mdx index 6320a7db4558c..da3d0f32780be 100644 --- a/dev_docs/building_blocks.mdx +++ b/dev_docs/key_concepts/building_blocks.mdx @@ -1,26 +1,28 @@ --- id: kibBuildingBlocks -slug: /kibana-dev-docs/building-blocks +slug: /kibana-dev-docs/key-concepts/building-blocks title: Building blocks summary: Consider these building blocks when developing your plugin. date: 2021-02-24 -tags: ['kibana','onboarding', 'dev', 'architecture'] +tags: ['kibana', 'onboarding', 'dev', 'architecture'] --- -When building a plugin in Kibana, there are a handful of architectural "building blocks" you can use. Some of these building blocks are "higher-level", -and some are "lower-level". High-level building blocks come +When building a plugin in Kibana, there are a handful of architectural "building blocks" you can use. Some of these building blocks are "higher-level", +and some are "lower-level". High-level building blocks come with many built-in capabilities, require less maintenance, and evolve new feature sets over time with little to no - impact on consumers. When developers use high-level building blocks, new features are exposed consistently, across all of Kibana, at the same time. - On the downside, they are not as flexible as our low-level building blocks. - - Low-level building blocks - provide greater flexibility, but require more code to stitch them together into a meaningful UX. This results in higher maintenance cost for consumers and greater UI/UX variability - across Kibana. - - For example, if an application is using and - , - their application would automatically support runtime fields. If the app is instead using the - lower-level , additional work would be required. +impact on consumers. When developers use high-level building blocks, new features are exposed consistently, across all of Kibana, at the same time. +On the downside, they are not as flexible as our low-level building blocks. + +Low-level building blocks +provide greater flexibility, but require more code to stitch them together into a meaningful UX. This results in higher maintenance cost for consumers and greater UI/UX variability +across Kibana. + +For example, if an application is using and , their application would +automatically support runtime fields. If the app is instead using the lower-level , additional work would be required. Armed with this knowledge, you can choose what works best for your use case! @@ -32,23 +34,15 @@ The following high-level building blocks can be rendered directly into your appl ### Query Bar -The provides a high-level Query Bar component that comes with support for Lucene, KQL, Saved Queries, -and . - -If you would like to expose the ability to search and filter on Elasticsearch data, the Query Bar provided by the - - is your go-to building block. +The provides a high-level Query Bar component that comes with support for Lucene, KQL, Saved Queries, +and . If you would like to expose the ability to search and filter on Elasticsearch data, the Query Bar provided by the is your go-to building block. **Github labels**: `Team:AppServices`, `Feature:QueryBar` ### Dashboard Embeddable Add a Dashboard Embeddable directly inside your application to provide users with a set of visualizations and graphs that work seamlessly -with the . Every feature that is added to a registered - -(Lens, Maps, Saved Searches and more) will be available automatically, as well as any - that are - added to the Embeddable context menu panel (for example, drilldowns, custom panel time ranges, and "share to" features). +with the . Every feature that is added to a registered (Lens, Maps, Saved Searches and more) will be available automatically, as well as any that are added to the Embeddable context menu panel (for example, drilldowns, custom panel time ranges, and "share to" features). The Dashboard Embeddable is one of the highest-level UI components you can add to your application. @@ -56,11 +50,7 @@ The Dashboard Embeddable is one of the highest-level UI components you can add t ### Lens Embeddable -Check out the Lens Embeddable if you wish to show users visualizations based on Elasticsearch data without worrying about query building and chart rendering. It's built on top of the - , and integrates with - - and . Using the same configuration, it's also possible to link to - a prefilled Lens editor, allowing the user to drill deeper and explore their data. +Check out the Lens Embeddable if you wish to show users visualizations based on Elasticsearch data without worrying about query building and chart rendering. It's built on top of the , and integrates with and . Using the same configuration, it's also possible to link to a prefilled Lens editor, allowing the user to drill deeper and explore their data. **Github labels**: `Team:VisEditors`, `Feature:Lens` @@ -72,7 +62,7 @@ Check out the Map Embeddable if you wish to embed a map in your application. ### KibanaPageTemplate -All Kibana pages should use KibanaPageTemplate to setup their pages. It's a thin wrapper around [EuiPageTemplate](https://elastic.github.io/eui/#/layout/page) that makes setting up common types of Kibana pages quicker and easier while also adhering to any Kibana-specific requirements. +All Kibana pages should use KibanaPageTemplate to setup their pages. It's a thin wrapper around [EuiPageTemplate](https://elastic.github.io/eui/#/layout/page) that makes setting up common types of Kibana pages quicker and easier while also adhering to any Kibana-specific requirements. Check out for more implementation guidance. @@ -82,10 +72,11 @@ Check out are a high-level, space-aware abstraction layer that sits -above Data Streams and Elasticsearch indices. Index Patterns provide users the -ability to define and customize the data they wish to search and filter on, on a per-space basis. For example, users can specify a set of indices, -and they can customize the field list with runtime fields, formatting options and custom labels. + are a high-level, space-aware +abstraction layer that sits above Data Streams and Elasticsearch indices. Index Patterns provide users +the ability to define and customize the data they wish to search and filter on, on a per-space basis. +For example, users can specify a set of indices, and they can customize the field list with runtime fields, +formatting options and custom labels. Index Patterns are used in many other high-level building blocks so we highly recommend you consider this building block for your search needs. @@ -93,18 +84,23 @@ Index Patterns are used in many other high-level building blocks so we highly re ### Search Source - is a high-level search service offered by the -. It requires an -, and abstracts away the raw ES DSL and search endpoint. Internally -it uses the ES . Use Search Source if you need to query data -from Elasticsearch, and you aren't already using one of the high-level UI Components that handles this internally. + is a high-level search service +offered by the . It requires +an , and abstracts away +the raw ES DSL and search endpoint. Internally it uses the ES +. Use Search Source if you need to query data from Elasticsearch, and you aren't already using one of +the high-level UI Components that handles this internally. **Github labels**: `Team:AppServices`, `Feature:Search` ### Search Strategies -Search Strategies are a low-level building block that abstracts away search details, like what REST endpoint is being called. The ES Search Strategy -is a very lightweight abstraction layer that sits just above querying ES with the elasticsearch-js client. Other search stragies are offered for other +Search Strategies are a low-level building block that abstracts away search details, like what REST endpoint is being called. The ES Search Strategy +is a very lightweight abstraction layer that sits just above querying ES with the elasticsearch-js client. Other search stragies are offered for other languages, like EQL and SQL. These are very low-level building blocks so expect a lot of glue work to make these work with the higher-level abstractions. **Github labels**: `Team:AppServices`, `Feature:Search` @@ -112,24 +108,24 @@ languages, like EQL and SQL. These are very low-level building blocks so expect ### Expressions Expressions are a low-level building block that can be used if you have advanced search needs that requiring piping results into additional functionality, like -joining and manipulating data. Lens and Canvas are built on top of Expressions. Most developers should be able to use - or - , rather than need to access the Expression language directly. +joining and manipulating data. Lens and Canvas are built on top of Expressions. Most developers should be able to use or , rather than need to +access the Expression language directly.{' '} **Github labels**: `Team:AppServices`, `Feature:ExpressionLanguage` ## Saved Objects - should be used if you need to persist application-level information. If you were building a TODO -application, each TODO item would be a `Saved Object`. Saved objects come pre-wired with support for bulk export/import, security features like space sharing and -space isolation, and tags. + should be used if you need to persist +application-level information. If you were building a TODO application, each TODO item would be a `Saved +Object`. Saved objects come pre-wired with support for bulk export/import, security features like space +sharing and space isolation, and tags. **Github labels**: `Team:Core`, `Feature:Saved Objects` # Integration building blocks Use the following building blocks to create an inter-connected, cross-application, holistic Kibana experience. These building blocks allow you to expose functionality - that promotes your own application into other applications, as well as help developers of other applications integrate into your app. +that promotes your own application into other applications, as well as help developers of other applications integrate into your app. ## UI Actions & Triggers @@ -141,6 +137,6 @@ application could register a UI Action called "View in Maps" to appear any time ## Embeddables Embeddables help you integrate your application with the Dashboard application. Register your custom UI Widget as an Embeddable and users will -be able to add it as a panel on a Dashboard. With a little extra work, it can also be exposed in Canvas workpads. +be able to add it as a panel on a Dashboard. With a little extra work, it can also be exposed in Canvas workpads. **Github labels**: `Team:AppServices`, `Feature:Embeddables` diff --git a/dev_docs/key_concepts/data_views.mdx b/dev_docs/key_concepts/data_views.mdx index e2b64c8705c48..c514af21c0cf7 100644 --- a/dev_docs/key_concepts/data_views.mdx +++ b/dev_docs/key_concepts/data_views.mdx @@ -1,16 +1,16 @@ --- id: kibDataViewsKeyConcepts -slug: /kibana-dev-docs/data-view-intro +slug: /kibana-dev-docs/key-concepts/data-view-intro title: Data Views summary: Data views are the central method of defining queryable data sets in Kibana date: 2021-08-11 -tags: ['kibana','dev', 'contributor', 'api docs'] +tags: ['kibana', 'dev', 'contributor', 'api docs'] --- -*Note: Kibana index patterns are currently being renamed to data views. There will be some naming inconsistencies until the transition is complete.* +_Note: Kibana index patterns are currently being renamed to data views. There will be some naming inconsistencies until the transition is complete._ Data views (formerly Kibana index patterns or KIPs) are the central method of describing sets of indices for queries. Usage is strongly recommended -as a number of high level rely on them. Further, they provide a consistent view of data across +as a number of high level rely on them. Further, they provide a consistent view of data across a variety Kibana apps. Data views are defined by a wildcard string (an index pattern) which matches indices, data streams, and index aliases, optionally specify a @@ -20,8 +20,6 @@ on the data view via runtime fields. Schema-on-read functionality is provided by ![image](../assets/data_view_diagram.png) - - The data view API is made available via the data plugin (`data.indexPatterns`, soon to be renamed) and most commonly used with (`data.search.search.SearchSource`) to perform queries. SearchSource will apply existing filters and queries from the search bar UI. @@ -29,4 +27,3 @@ Users can create data views via [Data view management](https://www.elastic.co/gu Additionally, they can be created through the data view API. Data views also allow formatters and custom labels to be defined for fields. - diff --git a/dev_docs/kibana_platform_plugin_intro.mdx b/dev_docs/key_concepts/kibana_platform_plugin_intro.mdx similarity index 99% rename from dev_docs/kibana_platform_plugin_intro.mdx rename to dev_docs/key_concepts/kibana_platform_plugin_intro.mdx index 252a6dcd9cd8e..b2255dbc8e5c4 100644 --- a/dev_docs/kibana_platform_plugin_intro.mdx +++ b/dev_docs/key_concepts/kibana_platform_plugin_intro.mdx @@ -1,6 +1,6 @@ --- id: kibPlatformIntro -slug: /kibana-dev-docs/platform-intro +slug: /kibana-dev-docs/key-concepts/platform-intro title: Plugins and the Kibana platform summary: An introduction to the Kibana platform and how to use it to build a plugin. date: 2021-01-06 diff --git a/dev_docs/key_concepts/performance.mdx b/dev_docs/key_concepts/performance.mdx index 2870262825e4a..0201c7774f854 100644 --- a/dev_docs/key_concepts/performance.mdx +++ b/dev_docs/key_concepts/performance.mdx @@ -1,6 +1,6 @@ --- id: kibDevPerformance -slug: /kibana-dev-docs/performance +slug: /kibana-dev-docs/key-concepts/performance title: Performance summary: Performance tips for Kibana development. date: 2021-09-02 @@ -9,13 +9,13 @@ tags: ['kibana', 'onboarding', 'dev', 'performance'] ## Keep Kibana fast -*tl;dr*: Load as much code lazily as possible. Everyone loves snappy +_tl;dr_: Load as much code lazily as possible. Everyone loves snappy applications with a responsive UI and hates spinners. Users deserve the best experience whether they run Kibana locally or in the cloud, regardless of their hardware and environment. There are 2 main aspects of the perceived speed of an application: loading time -and responsiveness to user actions. Kibana loads and bootstraps *all* +and responsiveness to user actions. Kibana loads and bootstraps _all_ the plugins whenever a user lands on any page. It means that every new application affects the overall _loading performance_, as plugin code is loaded _eagerly_ to initialize the plugin and provide plugin API to dependent @@ -60,12 +60,12 @@ export class MyPlugin implements Plugin { ### Understanding plugin bundle size -Kibana Platform plugins are pre-built with `@kbn/optimizer` +Kibana Platform plugins are pre-built with `@kbn/optimizer` and distributed as package artifacts. This means that it is no -longer necessary for us to include the `optimizer` in the +longer necessary for us to include the `optimizer` in the distributable version of Kibana Every plugin artifact contains all plugin dependencies required to run the plugin, except some -stateful dependencies shared across plugin bundles via +stateful dependencies shared across plugin bundles via `@kbn/ui-shared-deps-npm` and `@kbn/ui-shared-deps-src`. This means that plugin artifacts _tend to be larger_ than they were in the legacy platform. To understand the current size of your plugin @@ -101,7 +101,7 @@ node scripts/build_kibana_platform_plugins.js --dist --no-examples --profile Many OSS tools allow you to analyze the generated stats file: -* [An official tool](https://webpack.github.io/analyse/#modules) from -Webpack authors -* [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/) -* [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) +- [An official tool](https://webpack.github.io/analyse/#modules) from + Webpack authors +- [webpack-visualizer](https://chrisbateman.github.io/webpack-visualizer/) +- [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) diff --git a/dev_docs/key_concepts/persistable_state.mdx b/dev_docs/key_concepts/persistable_state.mdx index 4368417170eed..189259cf1085b 100644 --- a/dev_docs/key_concepts/persistable_state.mdx +++ b/dev_docs/key_concepts/persistable_state.mdx @@ -1,19 +1,19 @@ --- id: kibDevDocsPersistableStateIntro -slug: /kibana-dev-docs/persistable-state-intro +slug: /kibana-dev-docs/key-concepts/persistable-state-intro title: Persistable State summary: Persitable state is a key concept to understand when building a Kibana plugin. date: 2021-02-02 -tags: ['kibana','dev', 'contributor', 'api docs'] +tags: ['kibana', 'dev', 'contributor', 'api docs'] --- - “Persistable state” is developer-defined state that supports being persisted by a plugin other than the one defining it. Persistable State needs to be serializable and the owner can/should provide utilities to migrate it, extract and inject any it may contain, as well as telemetry collection utilities. - +“Persistable state” is developer-defined state that supports being persisted by a plugin other than the one defining it. Persistable State needs to be serializable and the owner can/should provide utilities to migrate it, extract and inject any it may contain, as well as telemetry collection utilities. + ## Exposing state that can be persisted Any plugin that exposes state that another plugin might persist should implement interface on their `setup` contract. This will allow plugins persisting the state to easily access migrations and other utilities. -Example: Data plugin allows you to generate filters. Those filters can be persisted by applications in their saved +Example: Data plugin allows you to generate filters. Those filters can be persisted by applications in their saved objects or in the URL. In order to allow apps to migrate the filters in case the structure changes in the future, the Data plugin implements `PersistableStateService` on . note: There is currently no obvious way for a plugin to know which state is safe to persist. The developer must manually look for a matching `PersistableStateService`, or ad-hoc provided migration utilities (as is the case with Rule Type Parameters). @@ -26,9 +26,10 @@ interface on their `setup` contract and each item in the collection should imple Example: Embeddable plugin owns the registry of embeddable factories to which other plugins can register new embeddable factories. Dashboard plugin stores a bunch of embeddable panels input in its saved object and URL. Embeddable plugin setup contract implements `PersistableStateService` -interface and each `EmbeddableFactory` needs to implement `PersistableStateDefinition` interface. +interface and each `EmbeddableFactory` needs to implement `PersistableStateDefinition` interface. Embeddable plugin exposes this interfaces: + ``` // EmbeddableInput implements Serializable @@ -45,7 +46,7 @@ If the state your plugin is storing can be provided by other plugins (your plugi ## Storing persistable state as part of saved object -Any plugin that stores any persistable state as part of their saved object should make sure that its saved object migration +Any plugin that stores any persistable state as part of their saved object should make sure that its saved object migration and reference extraction and injection methods correctly use the matching `PersistableStateService` implementation for the state they are storing. Take a look at [example saved object](https://github.com/elastic/kibana/blob/master/examples/embeddable_examples/server/searchable_list_saved_object.ts#L32) which stores an embeddable state. Note how the `migrations`, `extractReferences` and `injectReferences` are defined. @@ -58,13 +59,17 @@ of `PersistableStateService` should be called, which will migrate the state from note: Currently there is no recommended way on how to store version in url and its up to every application to decide on how to implement that. ## Available state operations - + ### Extraction/Injection of References In order to support import and export, and space-sharing capabilities, Saved Objects need to explicitly list any references they contain to other Saved Objects. To support persisting your state in saved objects owned by another plugin, the and methods of Persistable State interface should be implemented. - + [See example embeddable providing extract/inject functions](https://github.com/elastic/kibana/blob/master/examples/embeddable_examples/public/migrations/migrations_embeddable_factory.ts) @@ -72,7 +77,7 @@ To support persisting your state in saved objects owned by another plugin, the < As your plugin evolves, you may need to change your state in a breaking way. If that happens, you should write a migration to upgrade the state that existed prior to the change. -. +. [See an example saved object storing embeddable state implementing saved object migration function](https://github.com/elastic/kibana/blob/master/examples/embeddable_examples/server/searchable_list_saved_object.ts) @@ -80,4 +85,4 @@ As your plugin evolves, you may need to change your state in a breaking way. If ## Telemetry -You might want to collect statistics about how your state is used. If that is the case you should implement the telemetry method of Persistable State interface. +You might want to collect statistics about how your state is used. If that is the case you should implement the telemetry method of Persistable State interface. diff --git a/dev_docs/key_concepts/saved_objects.mdx b/dev_docs/key_concepts/saved_objects.mdx index bef92bf028697..7fe66b9eab95c 100644 --- a/dev_docs/key_concepts/saved_objects.mdx +++ b/dev_docs/key_concepts/saved_objects.mdx @@ -1,39 +1,42 @@ --- id: kibDevDocsSavedObjectsIntro -slug: /kibana-dev-docs/saved-objects-intro +slug: /kibana-dev-docs/key-concepts/saved-objects-intro title: Saved Objects summary: Saved Objects are a key concept to understand when building a Kibana plugin. date: 2021-02-02 -tags: ['kibana','dev', 'contributor', 'api docs'] +tags: ['kibana', 'dev', 'contributor', 'api docs'] --- "Saved Objects" are developer defined, persisted entities, stored in the Kibana system index (which is also sometimes referred to as the `.kibana` index). The Saved Objects service allows Kibana plugins to use Elasticsearch like a primary database. Think of it as an Object Document Mapper for Elasticsearch. - Some examples of Saved Object types are dashboards, lens, canvas workpads, index patterns, cases, ml jobs, and advanced settings. Some Saved Object types are - exposed to the user in the [Saved Object management UI](https://www.elastic.co/guide/en/kibana/current/managing-saved-objects.html), but not all. +Some examples of Saved Object types are dashboards, lens, canvas workpads, index patterns, cases, ml jobs, and advanced settings. Some Saved Object types are +exposed to the user in the [Saved Object management UI](https://www.elastic.co/guide/en/kibana/current/managing-saved-objects.html), but not all. Developers create and manage their Saved Objects using the SavedObjectClient, while other data in Elasticsearch should be accessed via the data plugin's search services. ![image](../assets/saved_object_vs_data_indices.png) - - + ## References In order to support import and export, and space-sharing capabilities, Saved Objects need to explicitly list any references they contain to other Saved Objects. The parent should have a reference to it's children, not the other way around. That way when a "parent" is exported (or shared to a space), - all the "children" will be automatically included. However, when a "child" is exported, it will not include all "parents". +all the "children" will be automatically included. However, when a "child" is exported, it will not include all "parents". - + ## Migrations and Backward compatibility As your plugin evolves, you may need to change your Saved Object type in a breaking way (for example, changing the type of an attribtue, or removing an attribute). If that happens, you should write a migration to upgrade the Saved Objects that existed prior to the change. -. +. ## Security @@ -47,30 +50,30 @@ Saved Objects are "space aware". They exist in the space they were created in, a Feature controls provide another level of isolation and shareability for Saved Objects. Admins can give users and roles read, write or none permissions for each Saved Object type. -### Object level security (OLS) +### Object level security (OLS) OLS is an oft-requested feature that is not implemented yet. When it is, it will provide users with even more sharing and privacy flexibility. Individual objects can be private to the user, shared with a selection of others, or made public. Much like how sharing Google Docs works. - + ## Scalability By default all saved object types go into a single index. If you expect your saved object type to have a lot of unique fields, or if you expect there -to be many of them, you can have your objects go in a separate index by using the `indexPattern` field. Reporting and task manager are two +to be many of them, you can have your objects go in a separate index by using the `indexPattern` field. Reporting and task manager are two examples of features that use this capability. ## Searchability -Because saved objects are stored in system indices, they cannot be searched like other data can. If you see the phrase “[X] as data” it is +Because saved objects are stored in system indices, they cannot be searched like other data can. If you see the phrase “[X] as data” it is referring to this searching limitation. Users will not be able to create custom dashboards using saved object data, like they would for data stored in Elasticsearch data indices. ## Saved Objects by value Sometimes Saved Objects end up persisted inside another Saved Object. We call these Saved Objects “by value”, as opposed to "by - reference". If an end user creates a visualization and adds it to a dashboard without saving it to the visualization - library, the data ends up nested inside the dashboard Saved Object. This helps keep the visualization library smaller. It also avoids - issues with edits propagating - since an entity can only exist in a single place. - Note that from the end user stand point, we don’t use these terms “by reference” and “by value”. +reference". If an end user creates a visualization and adds it to a dashboard without saving it to the visualization +library, the data ends up nested inside the dashboard Saved Object. This helps keep the visualization library smaller. It also avoids +issues with edits propagating - since an entity can only exist in a single place. +Note that from the end user stand point, we don’t use these terms “by reference” and “by value”. ## Sharing Saved Objects @@ -80,7 +83,7 @@ on how it is registered. If you are adding a **new** object type, when you register it: 1. Use `namespaceType: 'multiple-isolated'` to make these objects exist in exactly one space -2. Use `namespaceType: 'multiple'` to make these objects exist in one *or more* spaces +2. Use `namespaceType: 'multiple'` to make these objects exist in one _or more_ spaces 3. Use `namespaceType: 'agnostic'` if you want these objects to always exist in all spaces If you have an **existing** "legacy" object type that is not shareable (using `namespaceType: 'single'`), see the [legacy developer guide diff --git a/dev_docs/tutorials/building_a_kibana_distributable.mdx b/dev_docs/tutorials/building_a_kibana_distributable.mdx index 7b06525a5b977..e73481058ab35 100644 --- a/dev_docs/tutorials/building_a_kibana_distributable.mdx +++ b/dev_docs/tutorials/building_a_kibana_distributable.mdx @@ -1,6 +1,6 @@ --- id: kibDevTutorialBuildingDistributable -slug: /kibana-dev-docs/tutorial/building-distributable +slug: /kibana-dev-docs/tutorials/building-distributable title: Building a Kibana distributable summary: Learn how to build a Kibana distributable date: 2021-05-10 diff --git a/dev_docs/tutorials/data/search.mdx b/dev_docs/tutorials/data/search.mdx index 9cf46bb96c72a..81080b0c27418 100644 --- a/dev_docs/tutorials/data/search.mdx +++ b/dev_docs/tutorials/data/search.mdx @@ -2,14 +2,14 @@ id: kibDevTutorialDataSearchAndSessions slug: /kibana-dev-docs/tutorials/data/search-and-sessions title: Kibana data.search Services -summary: Kibana Search Services +summary: Kibana Search Services date: 2021-02-10 tags: ['kibana', 'onboarding', 'dev', 'tutorials', 'search', 'sessions', 'search-sessions'] --- ## Search service -### Low level search +### Low level search Searching data stored in Elasticsearch can be done in various ways, for example using the Elasticsearch REST API or using an `Elasticsearch Client` for low level access. @@ -50,7 +50,7 @@ export class MyPlugin implements Plugin { } else { // handle partial results if you want. } - }, + }, error: (e) => { // handle error thrown, for example a server hangup }, @@ -69,36 +69,36 @@ Note: The `data` plugin contains services to help you generate the `query` and ` The `search` method can throw several types of errors, for example: - - `EsError` for errors originating in Elasticsearch errors - - `PainlessError` for errors originating from a Painless script - - `AbortError` if the search was aborted via an `AbortController` - - `HttpError` in case of a network error +- `EsError` for errors originating in Elasticsearch errors +- `PainlessError` for errors originating from a Painless script +- `AbortError` if the search was aborted via an `AbortController` +- `HttpError` in case of a network error -To display the errors in the context of an application, use the helper method provided on the `data.search` service. These errors are shown in a toast message, using the `core.notifications` service. +To display the errors in the context of an application, use the helper method provided on the `data.search` service. These errors are shown in a toast message, using the `core.notifications` service. ```ts data.search.search(req).subscribe({ - next: (result) => {}, + next: (result) => {}, error: (e) => { data.search.showError(e); }, -}) +}); ``` If you decide to handle errors by yourself, watch for errors coming from `Elasticsearch`. They have an additional `attributes` property that holds the raw error from `Elasticsearch`. ```ts data.search.search(req).subscribe({ - next: (result) => {}, + next: (result) => {}, error: (e) => { if (e instanceof IEsError) { showErrorReason(e.attributes); } }, -}) +}); ``` -#### Stop a running search +#### Stop a running search The search service `search` method supports a second argument called `options`. One of these options provides an `abortSignal` to stop searches from running to completion, if the result is no longer needed. @@ -106,20 +106,22 @@ The search service `search` method supports a second argument called `options`. import { AbortError } from '../../src/data/public'; const abortController = new AbortController(); -data.search.search(req, { - abortSignal: abortController.signal, -}).subscribe({ - next: (result) => { - // handle result - }, - error: (e) => { - if (e instanceof AbortError) { - // you can ignore this error - return; - } - // handle error, for example a server hangup - }, -}); +data.search + .search(req, { + abortSignal: abortController.signal, + }) + .subscribe({ + next: (result) => { + // handle result + }, + error: (e) => { + if (e instanceof AbortError) { + // you can ignore this error + return; + } + // handle error, for example a server hangup + }, + }); // Abort the search request after a second setTimeout(() => { @@ -135,13 +137,15 @@ For example, to run an EQL query using the `data.search` service, you should to ```ts const req = getEqlRequest(); -data.search.search(req, { - strategy: EQL_SEARCH_STRATEGY, -}).subscribe({ - next: (result) => { - // handle EQL result - }, -}); +data.search + .search(req, { + strategy: EQL_SEARCH_STRATEGY, + }) + .subscribe({ + next: (result) => { + // handle EQL result + }, + }); ``` ##### Custom search strategies @@ -154,18 +158,18 @@ The following example shows how to define, register, and use a search strategy t // ./myPlugin/server/myStrategy.ts /** - * Your custom search strategy should implement the ISearchStrategy interface, requiring at minimum a `search` function. + * Your custom search strategy should implement the ISearchStrategy interface, requiring at minimum a `search` function. */ export const mySearchStrategyProvider = ( data: PluginStart ): ISearchStrategy => { const preprocessRequest = (request: IMyStrategyRequest) => { // Custom preprocessing - } + }; const formatResponse = (response: IMyStrategyResponse) => { // Custom post-processing - } + }; // Get the default search strategy const es = data.search.getSearchStrategy(ES_SEARCH_STRATEGY); @@ -179,16 +183,12 @@ export const mySearchStrategyProvider = ( ```ts // ./myPlugin/server/plugin.ts -import type { - CoreSetup, - CoreStart, - Plugin, -} from 'kibana/server'; +import type { CoreSetup, CoreStart, Plugin } from 'kibana/server'; import { mySearchStrategyProvider } from './my_strategy'; /** - * Your plugin will receive the `data` plugin contact in both the setup and start lifecycle hooks. + * Your plugin will receive the `data` plugin contact in both the setup and start lifecycle hooks. */ export interface MyPluginSetupDeps { data: PluginSetup; @@ -199,13 +199,10 @@ export interface MyPluginStartDeps { } /** - * In your custom server side plugin, register the strategy from the setup contract + * In your custom server side plugin, register the strategy from the setup contract */ export class MyPlugin implements Plugin { - public setup( - core: CoreSetup, - deps: MyPluginSetupDeps - ) { + public setup(core: CoreSetup, deps: MyPluginSetupDeps) { core.getStartServices().then(([_, depsStart]) => { const myStrategy = mySearchStrategyProvider(depsStart.data); deps.data.search.registerSearchStrategy('myCustomStrategy', myStrategy); @@ -217,13 +214,15 @@ export class MyPlugin implements Plugin { ```ts // ./myPlugin/public/plugin.ts const req = getRequest(); -data.search.search(req, { - strategy: 'myCustomStrategy', -}).subscribe({ - next: (result) => { - // handle result - }, -}); +data.search + .search(req, { + strategy: 'myCustomStrategy', + }) + .subscribe({ + next: (result) => { + // handle result + }, + }); ``` ##### Async search and custom async search strategies @@ -234,7 +233,7 @@ This synchronous execution works great in most cases. However, with the introduc The [async_search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/async-search.html) is what drives more advanced `Kibana` `search` features, such as `partial results` and `search sessions`. [When available](https://www.elastic.co/subscriptions), the default search strategy of `Kibana` is automatically set to the **async** default search strategy (`ENHANCED_ES_SEARCH_STRATEGY`), empowering Kibana to run longer queries, with an **optional** duration restriction defined by the UI setting `search:timeout`. -If you are implementing your own async custom search strategy, make sure to implement `cancel` and `extend`, as shown in the following example: +If you are implementing your own async custom search strategy, make sure to implement `cancel` and `extend`, as shown in the following example: ```ts // ./myPlugin/server/myEnhancedStrategy.ts @@ -245,7 +244,7 @@ export const myEnhancedSearchStrategyProvider = ( const ese = data.search.getSearchStrategy(ENHANCED_ES_SEARCH_STRATEGY); return { search: (request, options, deps) => { - // search will be called multiple times, + // search will be called multiple times, // be sure your response formatting is capable of handling partial results, as well as the final result. return formatResponse(ese.search(request, options, deps)); }, @@ -286,7 +285,7 @@ function searchWithSearchSource() { .setField('query', query) .setField('fields', selectedFields.length ? selectedFields.map((f) => f.name) : ['*']) .setField('aggs', getAggsDsl()); - + searchSource.fetch$().subscribe({ next: () => {}, error: () => {}, @@ -296,7 +295,7 @@ function searchWithSearchSource() { ### Partial results -When searching using an `async` strategy (such as async DSL and async EQL), the search service will stream back partial results. +When searching using an `async` strategy (such as async DSL and async EQL), the search service will stream back partial results. Although you can ignore the partial results and wait for the final result before rendering, you can also use the partial results to create a more interactive experience for your users. It is highly advised, however, to make sure users are aware that the results they are seeing are partial. @@ -310,7 +309,7 @@ data.search.search(req).subscribe({ renderPartialResult(res); } }, -}) +}); // Skipping partial results const finalResult = await data.search.search(req).toPromise(); @@ -320,31 +319,29 @@ const finalResult = await data.search.search(req).toPromise(); A search session is a higher level concept than search. A search session describes a grouping of one or more async search requests with additional context. -Search sessions are handy when you want to enable a user to run something asynchronously (for example, a dashboard over a long period of time), and then quickly restore the results at a later time. The `Search Service` transparently fetches results from the `.async-search` index, instead of running each request again. +Search sessions are handy when you want to enable a user to run something asynchronously (for example, a dashboard over a long period of time), and then quickly restore the results at a later time. The `Search Service` transparently fetches results from the `.async-search` index, instead of running each request again. Internally, any search run within a search session is saved into an object, allowing Kibana to manage their lifecycle. Most saved objects are deleted automatically after a short period of time, but if a user chooses to save the search session, the saved object is persisted, so that results can be restored in a later time. -Stored search sessions are listed in the *Management* application, under *Kibana > Search Sessions*, making it easy to find, manage, and restore them. +Stored search sessions are listed in the _Management_ application, under _Kibana > Search Sessions_, making it easy to find, manage, and restore them. As a developer, you might encounter these two common, use cases: - * Running a search inside an existing search session - * Supporting search sessions in your application +- Running a search inside an existing search session +- Supporting search sessions in your application #### Running a search inside an existing search session For this example, assume you are implementing a new type of `Embeddable` that will be shown on dashboards. The same principle applies, however, to any search requests that you are running, as long as the application you are running inside is managing an active session. -Because the Dashboard application is already managing a search session, all you need to do is pass down the `searchSessionId` argument to any `search` call. This applies to both the low and high level search APIs. +Because the Dashboard application is already managing a search session, all you need to do is pass down the `searchSessionId` argument to any `search` call. This applies to both the low and high level search APIs. -The search information will be added to the saved object for the search session. +The search information will be added to the saved object for the search session. ```ts -export class SearchEmbeddable - extends Embeddable { - +export class SearchEmbeddable extends Embeddable { private async fetchData() { - // Every embeddable receives an optional `searchSessionId` input parameter. + // Every embeddable receives an optional `searchSessionId` input parameter. const { searchSessionId } = this.input; // Setup your search source @@ -355,9 +352,11 @@ export class SearchEmbeddable this.updateOutput({ loading: true, error: undefined }); // Make the request, wait for the final result - const {rawResponse: resp} = await searchSource.fetch$({ - sessionId: searchSessionId, - }).toPromise(); + const { rawResponse: resp } = await searchSource + .fetch$({ + sessionId: searchSessionId, + }) + .toPromise(); this.useSearchResult(resp); @@ -368,35 +367,37 @@ export class SearchEmbeddable } } } - -``` +``` You can also retrieve the active `Search Session ID` from the `Search Service` directly: ```ts async function fetchData(data: DataPublicPluginStart) { try { - return await searchSource.fetch$({ + return await searchSource + .fetch$({ sessionId: data.search.sessions.getSessionId(), - }).toPromise(); + }) + .toPromise(); } catch (e) { // handle search errors } } - ``` - Search sessions are initiated by the client. If you are using a route that runs server side searches, you can send the `searchSessionId` to the server, and then pass it down to the server side `data.search` function call. + Search sessions are initiated by the client. If you are using a route that runs server side + searches, you can send the `searchSessionId` to the server, and then pass it down to the server + side `data.search` function call. #### Supporting search sessions in your application Before implementing the ability to create and restore search sessions in your application, ask yourself the following questions: -1. **Does your application normally run long operations?** For example, it makes sense for a user to generate a Dashboard or a Canvas report from data stored in cold storage. However, when editing a single visualization, it is best to work with a shorter timeframe of hot or warm data. +1. **Does your application normally run long operations?** For example, it makes sense for a user to generate a Dashboard or a Canvas report from data stored in cold storage. However, when editing a single visualization, it is best to work with a shorter timeframe of hot or warm data. 2. **Does it make sense for your application to restore a search session?** For example, you might want to restore an interesting configuration of filters of older documents you found in Discover. However, a single Lens or Map visualization might not be as helpful, outside the context of a specific dashboard. -3. **What is a search session in the context of your application?** Although Discover and Dashboard start a new search session every time the time range or filters change, or when the user clicks **Refresh**, you can manage your sessions differently. For example, if your application has tabs, you might group searches from multiple tabs into a single search session. You must be able to clearly define the **state** used to create the search session`. The **state** refers to any setting that might change the queries being set to `Elasticsearch`. +3. **What is a search session in the context of your application?** Although Discover and Dashboard start a new search session every time the time range or filters change, or when the user clicks **Refresh**, you can manage your sessions differently. For example, if your application has tabs, you might group searches from multiple tabs into a single search session. You must be able to clearly define the **state** used to create the search session`. The **state** refers to any setting that might change the queries being set to `Elasticsearch`. Once you answer those questions, proceed to implement the following bits of code in your application. @@ -409,8 +410,8 @@ export class MyPlugin implements Plugin { public start(core: CoreStart, { data }: MyPluginStartDependencies) { const sessionRestorationDataProvider: SearchSessionInfoProvider = { data, - getDashboard - } + getDashboard, + }; data.search.session.enableStorage({ getName: async () => { @@ -430,32 +431,34 @@ export class MyPlugin implements Plugin { ``` - The restore state of a search session may be different from the initial state used to create it. For example, where the initial state may contain relative dates, in the restore state, those must be converted to absolute dates. Read more about the [NowProvider](). + The restore state of a search session may be different from the initial state used to create it. + For example, where the initial state may contain relative dates, in the restore state, those must + be converted to absolute dates. Read more about the [NowProvider](). - Calling `enableStorage` will also enable the `Search Session Indicator` component in the chrome component of your solution. The `Search Session Indicator` is a small button, used by default to engage users and save new search sessions. To implement your own UI, contact the Kibana application services team to decouple this behavior. + Calling `enableStorage` will also enable the `Search Session Indicator` component in the chrome + component of your solution. The `Search Session Indicator` is a small button, used by default to + engage users and save new search sessions. To implement your own UI, contact the Kibana + application services team to decouple this behavior. -##### Start a new search session +##### Start a new search session -Make sure to call `start` when the **state** you previously defined changes. +Make sure to call `start` when the **state** you previously defined changes. ```ts - function onSearchSessionConfigChange() { this.searchSessionId = data.search.sessions.start(); } - ``` -Pass the `searchSessionId` to every `search` call inside your application. If you're using `Embeddables`, pass down the `searchSessionId` as `input`. +Pass the `searchSessionId` to every `search` call inside your application. If you're using `Embeddables`, pass down the `searchSessionId` as `input`. If you can't pass the `searchSessionId` directly, you can retrieve it from the service. ```ts const currentSearchSessionId = data.search.sessions.getSessionId(); - ``` ##### Clear search sessions @@ -466,19 +469,17 @@ Creating a new search session clears the previous one. You must explicitly `clea function onDestroy() { data.search.session.clear(); } - ``` If you don't call `clear`, you will see a warning in the console while developing. However, when running in production, you will get a fatal error. This is done to avoid leakage of unrelated search requests into an existing search session left open by mistake. -##### Restore search sessions +##### Restore search sessions -The last step of the integration is restoring an existing search session. The `searchSessionId` parameter and the rest of the restore state are passed into the application via the URL. Non-URL support is planned for future releases. +The last step of the integration is restoring an existing search session. The `searchSessionId` parameter and the rest of the restore state are passed into the application via the URL. Non-URL support is planned for future releases. If you detect the presense of a `searchSessionId` parameter in the URL, call the `restore` method **instead** of calling `start`. The previous example would now become: ```ts - function onSearchSessionConfigChange(searchSessionIdFromUrl?: string) { if (searchSessionIdFromUrl) { data.search.sessions.restore(searchSessionIdFromUrl); @@ -486,7 +487,6 @@ function onSearchSessionConfigChange(searchSessionIdFromUrl?: string) { data.search.sessions.start(); } } - ``` Once you `restore` the session, as long as all `search` requests run with the same `searchSessionId`, the search session should be seamlessly restored. diff --git a/dev_docs/tutorials/debugging.mdx b/dev_docs/tutorials/debugging.mdx index c0efd249be066..c612893e4f1f9 100644 --- a/dev_docs/tutorials/debugging.mdx +++ b/dev_docs/tutorials/debugging.mdx @@ -1,6 +1,6 @@ --- id: kibDevTutorialDebugging -slug: /kibana-dev-docs/tutorial/debugging +slug: /kibana-dev-docs/tutorials/debugging title: Debugging in development summary: Learn how to debug Kibana while running from source date: 2021-04-26 @@ -27,7 +27,7 @@ You will need to run Jest directly from the Node script: `node --inspect-brk scripts/functional_test_runner` -### Development Server +### Development Server `node --inspect-brk scripts/kibana` @@ -58,4 +58,4 @@ logging: level: debug - name: elasticsearch.query level: debug -``` \ No newline at end of file +``` diff --git a/dev_docs/tutorials/saved_objects.mdx b/dev_docs/tutorials/saved_objects.mdx index 35efbb97a0a03..29a0b60983d90 100644 --- a/dev_docs/tutorials/saved_objects.mdx +++ b/dev_docs/tutorials/saved_objects.mdx @@ -1,6 +1,6 @@ --- id: kibDevTutorialSavedObject -slug: /kibana-dev-docs/tutorial/saved-objects +slug: /kibana-dev-docs/tutorials/saved-objects title: Register a new saved object type summary: Learn how to register a new saved object type. date: 2021-02-05 diff --git a/dev_docs/tutorials/submit_a_pull_request.mdx b/dev_docs/tutorials/submit_a_pull_request.mdx index 2be5973bb3854..5436ebf24e03e 100644 --- a/dev_docs/tutorials/submit_a_pull_request.mdx +++ b/dev_docs/tutorials/submit_a_pull_request.mdx @@ -1,6 +1,6 @@ --- id: kibDevTutorialSubmitPullRequest -slug: /kibana-dev-docs/tutorial/submit-pull-request +slug: /kibana-dev-docs/tutorials/submit-pull-request title: Submitting a Kibana pull request summary: Learn how to submit a Kibana pull request date: 2021-06-24 diff --git a/dev_docs/tutorials/testing_plugins.mdx b/dev_docs/tutorials/testing_plugins.mdx index bc92af33d3493..14089bc3fa315 100644 --- a/dev_docs/tutorials/testing_plugins.mdx +++ b/dev_docs/tutorials/testing_plugins.mdx @@ -1,6 +1,6 @@ --- id: kibDevTutorialTestingPlugins -slug: /kibana-dev-docs/tutorial/testing-plugins +slug: /kibana-dev-docs/tutorials/testing-plugins title: Testing Kibana Plugins summary: Learn how to test different aspects of Kibana plugins date: 2021-07-05 diff --git a/legacy_rfcs/README.md b/legacy_rfcs/README.md index f9f9502ad954b..4ef4db56c004f 100644 --- a/legacy_rfcs/README.md +++ b/legacy_rfcs/README.md @@ -1,3 +1,3 @@ # Kibana RFCs -We no longer follow this RFC process. Internal developers should review the new RFC process in our [internal developer guide](https://docs.elastic.dev/kibana-team/rfc-process) +We no longer follow this RFC process. Internal developers should review the new RFC process in our [internal developer guide](https://docs.elastic.dev/kibana-dev-docs/contributing/rfc-process) diff --git a/src/plugins/data/README.mdx b/src/plugins/data/README.mdx index 18b755275b4aa..e24a949a0c2ec 100644 --- a/src/plugins/data/README.mdx +++ b/src/plugins/data/README.mdx @@ -1,6 +1,6 @@ --- id: kibDataPlugin -slug: /kibana-dev-docs/services/data-plugin +slug: /kibana-dev-docs/key-concepts/data-plugin title: Data services image: https://source.unsplash.com/400x175/?Search summary: The data plugin contains services for searching, querying and filtering. diff --git a/src/plugins/usage_collection/README.mdx b/src/plugins/usage_collection/README.mdx index a6f6f6c8e5971..a58f197818bf4 100644 --- a/src/plugins/usage_collection/README.mdx +++ b/src/plugins/usage_collection/README.mdx @@ -1,6 +1,6 @@ --- id: kibUsageCollectionPlugin -slug: /kibana-dev-docs/services/usage-collection-plugin +slug: /kibana-dev-docs/key-concepts/usage-collection-plugin title: Usage collection service summary: The Usage Collection Service defines a set of APIs for other plugins to report the usage of their features. date: 2021-02-24 From 500fb00271d69f27714fbbd587621671fd569d23 Mon Sep 17 00:00:00 2001 From: Kellen <9484709+goodroot@users.noreply.github.com> Date: Mon, 4 Oct 2021 10:48:22 -0700 Subject: [PATCH 59/98] updates DevPrinciples URL (#113785) --- dev_docs/contributing/standards.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev_docs/contributing/standards.mdx b/dev_docs/contributing/standards.mdx index 3d41de8f229cc..5f61be80ee207 100644 --- a/dev_docs/contributing/standards.mdx +++ b/dev_docs/contributing/standards.mdx @@ -9,7 +9,7 @@ tags: ['contributor', 'dev', 'github', 'getting started', 'onboarding', 'kibana' ## Developer principles -We expect all developers to read and abide by our overarching . +We expect all developers to read and abide by our overarching . ## Style guide From 02129d991109afb41593980963a6dc5e908dff5d Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Mon, 4 Oct 2021 19:55:05 +0200 Subject: [PATCH 60/98] prevent undefined filterQuery error (#113522) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../timelines/public/components/t_grid/helpers.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx b/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx index 5fe766077a74c..02c3d10a76058 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx @@ -228,14 +228,13 @@ export const getCombinedFilterQuery = ({ to, filters, ...combineQueriesParams -}: CombineQueries & { from: string; to: string }): string => { - return replaceStatusField( +}: CombineQueries & { from: string; to: string }): string => + replaceStatusField( combineQueries({ ...combineQueriesParams, filters: [...filters, buildTimeRangeFilter(from, to)], - })!.filterQuery + })?.filterQuery ); -}; /** * This function is a temporary patch to prevent queries using old `signal.status` field. @@ -243,8 +242,8 @@ export const getCombinedFilterQuery = ({ * must be replaced by `ALERT_WORKFLOW_STATUS` field name constant * @deprecated */ -const replaceStatusField = (query: string): string => - query.replaceAll('signal.status', ALERT_WORKFLOW_STATUS); +const replaceStatusField = (filterQuery?: string): string => + filterQuery?.replaceAll('signal.status', ALERT_WORKFLOW_STATUS) ?? ''; /** * The CSS class name of a "stateful event", which appears in both From 006e3713a60fe786e15ef7c851bbc05bba4e8cd4 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Mon, 4 Oct 2021 14:20:39 -0400 Subject: [PATCH 61/98] Fix bulkResolve for duplicate requests (#113798) --- .../saved_objects_client.test.ts | 64 ++++++++----------- .../saved_objects/saved_objects_client.ts | 6 +- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/core/public/saved_objects/saved_objects_client.test.ts b/src/core/public/saved_objects/saved_objects_client.test.ts index 101f86b299ffc..3fc2f0fbb3175 100644 --- a/src/core/public/saved_objects/saved_objects_client.test.ts +++ b/src/core/public/saved_objects/saved_objects_client.test.ts @@ -216,61 +216,51 @@ describe('SavedObjectsClient', () => { `); }); - test('removes duplicates when calling `_bulk_resolve`', async () => { + test('handles duplicates correctly', async () => { // Await #resolve call to ensure batchQueue is empty and throttle has reset mockResolvedObjects({ ...doc, type: 'type2' }); await savedObjectsClient.resolve('type2', doc.id); http.fetch.mockClear(); - mockResolvedObjects(doc, { ...doc, type: 'some-type', id: 'some-id' }); // the client will only request two objects, so we only mock two results - savedObjectsClient.resolve(doc.type, doc.id); - savedObjectsClient.resolve('some-type', 'some-id'); - await savedObjectsClient.resolve(doc.type, doc.id); + mockResolvedObjects(doc, { ...doc, type: 'type2' }, { ...doc, type: 'type3' }); // the client will only request three objects, so we only mock three results + const call1 = savedObjectsClient.resolve(doc.type, doc.id); + const call2 = savedObjectsClient.resolve('type2', doc.id); + const call3 = savedObjectsClient.resolve(doc.type, doc.id); + const objFromCall4 = await savedObjectsClient.resolve('type3', doc.id); + const objFromCall1 = await call1; + const objFromCall2 = await call2; + const objFromCall3 = await call3; + // Assertion 1: all calls should return the expected object + expect(objFromCall1.saved_object).toEqual( + expect.objectContaining({ type: doc.type, id: doc.id, error: undefined }) + ); + expect(objFromCall2.saved_object).toEqual( + expect.objectContaining({ type: 'type2', id: doc.id, error: undefined }) + ); + expect(objFromCall3.saved_object).toEqual( + expect.objectContaining({ type: doc.type, id: doc.id, error: undefined }) + ); + expect(objFromCall4.saved_object).toEqual( + expect.objectContaining({ type: 'type3', id: doc.id, error: undefined }) + ); + + // Assertion 2: requests should be deduplicated (call1 and call3) expect(http.fetch).toHaveBeenCalledTimes(1); expect(http.fetch.mock.calls[0]).toMatchInlineSnapshot(` Array [ "/api/saved_objects/_bulk_resolve", Object { - "body": "[{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"config\\"},{\\"id\\":\\"some-id\\",\\"type\\":\\"some-type\\"}]", + "body": "[{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"config\\"},{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"type2\\"},{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"type3\\"}]", "method": "POST", "query": undefined, }, ] `); - }); - - test('resolves with correct object when there are duplicates present', async () => { - // Await #resolve call to ensure batchQueue is empty and throttle has reset - mockResolvedObjects({ ...doc, type: 'type2' }); - await savedObjectsClient.resolve('type2', doc.id); - http.fetch.mockClear(); - - mockResolvedObjects(doc); - const call1 = savedObjectsClient.resolve(doc.type, doc.id); - const objFromCall2 = await savedObjectsClient.resolve(doc.type, doc.id); - const objFromCall1 = await call1; - - expect(objFromCall1.saved_object.type).toBe(doc.type); - expect(objFromCall1.saved_object.id).toBe(doc.id); - - expect(objFromCall2.saved_object.type).toBe(doc.type); - expect(objFromCall2.saved_object.id).toBe(doc.id); - }); - - test('do not share instances or references between duplicate callers', async () => { - // Await #resolve call to ensure batchQueue is empty and throttle has reset - await savedObjectsClient.resolve('type2', doc.id); - mockResolvedObjects({ ...doc, type: 'type2' }); - http.fetch.mockClear(); - - mockResolvedObjects(doc); - const call1 = savedObjectsClient.resolve(doc.type, doc.id); - const objFromCall2 = await savedObjectsClient.resolve(doc.type, doc.id); - const objFromCall1 = await call1; + // Assertion 3: deduplicated requests should not share response object instances or references objFromCall1.saved_object.set('title', 'new title'); - expect(objFromCall2.saved_object.get('title')).toEqual('Example title'); + expect(objFromCall3.saved_object.get('title')).toEqual('Example title'); // unchanged }); test('resolves with ResolvedSimpleSavedObject instance', async () => { diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index 0b0bc58729e3f..d3810d8932f1a 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -167,13 +167,13 @@ const getObjectsToResolve = (queue: BatchResolveQueueEntry[]) => { const responseIndices: number[] = []; const objectsToResolve: ObjectTypeAndId[] = []; const inserted = new Map(); - queue.forEach(({ id, type }, currentIndex) => { + queue.forEach(({ id, type }) => { const key = `${type}|${id}`; const indexForTypeAndId = inserted.get(key); if (indexForTypeAndId === undefined) { - inserted.set(key, currentIndex); + inserted.set(key, objectsToResolve.length); + responseIndices.push(objectsToResolve.length); objectsToResolve.push({ id, type }); - responseIndices.push(currentIndex); } else { responseIndices.push(indexForTypeAndId); } From d8b4f4bdcb10a9fa494e4e0a7633522401ea6d6b Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Mon, 4 Oct 2021 20:29:18 +0200 Subject: [PATCH 62/98] [Reporting] Improve _read code in ContentStream (#113237) --- .../reporting/server/lib/content_stream.ts | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/reporting/server/lib/content_stream.ts b/x-pack/plugins/reporting/server/lib/content_stream.ts index 23cc8a302dbef..3c0fdaa91f32e 100644 --- a/x-pack/plugins/reporting/server/lib/content_stream.ts +++ b/x-pack/plugins/reporting/server/lib/content_stream.ts @@ -179,28 +179,27 @@ export class ContentStream extends Duplex { return this.jobSize != null && this.bytesRead >= this.jobSize; } - async _read() { - try { - const content = this.chunksRead ? await this.readChunk() : await this.readHead(); - if (!content) { - this.logger.debug(`Chunk is empty.`); - this.push(null); - return; - } - - const buffer = this.decode(content); - - this.push(buffer); - this.chunksRead++; - this.bytesRead += buffer.byteLength; - - if (this.isRead()) { - this.logger.debug(`Read ${this.bytesRead} of ${this.jobSize} bytes.`); - this.push(null); - } - } catch (error) { - this.destroy(error); - } + _read() { + (this.chunksRead ? this.readChunk() : this.readHead()) + .then((content) => { + if (!content) { + this.logger.debug(`Chunk is empty.`); + this.push(null); + return; + } + + const buffer = this.decode(content); + + this.push(buffer); + this.chunksRead++; + this.bytesRead += buffer.byteLength; + + if (this.isRead()) { + this.logger.debug(`Read ${this.bytesRead} of ${this.jobSize} bytes.`); + this.push(null); + } + }) + .catch((err) => this.destroy(err)); } private async removeChunks() { From 1f60a1662f05bc2b0c6cd2e8a81edc91cf6da625 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Mon, 4 Oct 2021 21:42:07 +0300 Subject: [PATCH 63/98] [@kbn/securitysolution-es-utils] remove transport API in favour of typed public API (#113717) * remove transport API in favour of typed public API * put elasticsearch_client back * fix create index call * fix setpolicy * fix unit tests in SecuritySolution --- .../src/create_boostrap_index/index.ts | 7 +++---- .../src/delete_all_index/index.ts | 2 +- .../src/delete_policy/index.ts | 10 ++++------ .../src/delete_template/index.ts | 2 +- .../src/elasticsearch_client/index.ts | 15 +-------------- .../src/get_index_aliases/index.ts | 2 +- .../src/get_index_count/index.ts | 2 +- .../src/get_index_exists/index.ts | 2 +- .../src/get_policy_exists/index.ts | 8 +++----- .../src/get_template_exists/index.ts | 2 +- .../src/read_index/index.ts | 2 +- .../src/read_privileges/index.ts | 6 ++---- .../src/set_policy/index.ts | 8 +++----- .../src/set_template/index.ts | 2 +- .../routes/__mocks__/request_context.ts | 4 ++-- .../privileges/read_privileges_route.test.ts | 4 ++-- 16 files changed, 28 insertions(+), 50 deletions(-) diff --git a/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts b/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts index 9671d35dc554e..6a177f5caac21 100644 --- a/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; // See the reference(s) below on explanations about why -000001 was chosen and // why the is_write_index is true as well as the bootstrapping step which is needed. @@ -16,9 +16,8 @@ export const createBootstrapIndex = async ( index: string ): Promise => { return ( - await esClient.transport.request({ - path: `/${index}-000001`, - method: 'PUT', + await esClient.indices.create({ + index: `${index}-000001`, body: { aliases: { [index]: { diff --git a/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts b/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts index 4df4724aaf2b5..580c104752aea 100644 --- a/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const deleteAllIndex = async ( esClient: ElasticsearchClient, diff --git a/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts b/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts index 34c1d2e5da45f..60a15f6d4625d 100644 --- a/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts @@ -6,16 +6,14 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const deletePolicy = async ( esClient: ElasticsearchClient, policy: string ): Promise => { return ( - await esClient.transport.request({ - path: `/_ilm/policy/${policy}`, - method: 'DELETE', - }) - ).body; + // @ts-expect-error policy_id is required by mistake. fixed in the v8.0 + (await esClient.ilm.deleteLifecycle({ policy })).body + ); }; diff --git a/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts b/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts index 2e7a71af9f772..86565a0c43b3a 100644 --- a/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const deleteTemplate = async ( esClient: ElasticsearchClient, diff --git a/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts b/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts index 0c2252bdc1f03..a1fb3ff3ecf31 100644 --- a/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts @@ -10,12 +10,6 @@ // as these types aren't part of any package yet. Once they are, remove this completely import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; -import type { - ApiResponse, - TransportRequestOptions, - TransportRequestParams, - TransportRequestPromise, -} from '@elastic/elasticsearch/lib/Transport'; /** * Client used to query the elasticsearch cluster. @@ -25,11 +19,4 @@ import type { export type ElasticsearchClient = Omit< KibanaClient, 'connectionPool' | 'transport' | 'serializer' | 'extend' | 'child' | 'close' -> & { - transport: { - request( - params: TransportRequestParams, - options?: TransportRequestOptions - ): TransportRequestPromise; - }; -}; +>; diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts b/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts index 885103c1fb584..ba00c1144edfc 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; interface AliasesResponse { [indexName: string]: { diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts b/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts index 523b41303a569..b1dcd4fd0ad9b 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; /** * Retrieves the count of documents in a given index diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts index b7d12cab3f48c..9208773048474 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const getIndexExists = async ( esClient: ElasticsearchClient, diff --git a/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts index cefd47dbe9d07..8172cfb2abaa0 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts @@ -5,17 +5,15 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const getPolicyExists = async ( esClient: ElasticsearchClient, policy: string ): Promise => { try { - await esClient.transport.request({ - path: `/_ilm/policy/${policy}`, - method: 'GET', + await esClient.ilm.getLifecycle({ + policy, }); // Return true that there exists a policy which is not 404 or some error // Since there is not a policy exists API, this is how we create one by calling diff --git a/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts index c56c5b968d45c..72a3a93654482 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const getTemplateExists = async ( esClient: ElasticsearchClient, diff --git a/packages/kbn-securitysolution-es-utils/src/read_index/index.ts b/packages/kbn-securitysolution-es-utils/src/read_index/index.ts index cc16645120b70..206a4208b2ecc 100644 --- a/packages/kbn-securitysolution-es-utils/src/read_index/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/read_index/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const readIndex = async (esClient: ElasticsearchClient, index: string): Promise => { return esClient.indices.get({ diff --git a/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts b/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts index aab641367339c..772a6afa18c95 100644 --- a/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts @@ -6,16 +6,14 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const readPrivileges = async ( esClient: ElasticsearchClient, index: string ): Promise => { return ( - await esClient.transport.request({ - path: '/_security/user/_has_privileges', - method: 'POST', + await esClient.security.hasPrivileges({ body: { cluster: [ 'all', diff --git a/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts b/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts index dc45ca3e1c089..f6c2dcf7c3c3a 100644 --- a/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts @@ -5,8 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const setPolicy = async ( esClient: ElasticsearchClient, @@ -14,9 +13,8 @@ export const setPolicy = async ( body: Record ): Promise => { return ( - await esClient.transport.request({ - path: `/_ilm/policy/${policy}`, - method: 'PUT', + await esClient.ilm.putLifecycle({ + policy, body, }) ).body; diff --git a/packages/kbn-securitysolution-es-utils/src/set_template/index.ts b/packages/kbn-securitysolution-es-utils/src/set_template/index.ts index 89aaa44f29e0d..20f6fd5719d51 100644 --- a/packages/kbn-securitysolution-es-utils/src/set_template/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/set_template/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ElasticsearchClient } from '../elasticsearch_client'; +import type { ElasticsearchClient } from '../elasticsearch_client'; export const setTemplate = async ( esClient: ElasticsearchClient, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts index b47a9fc3a5d60..6039ad6ab6126 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_context.ts @@ -35,8 +35,8 @@ type SecuritySolutionRequestHandlerContextMock = SecuritySolutionRequestHandlerC asCurrentUser: { updateByQuery: jest.Mock; search: jest.Mock; - transport: { - request: jest.Mock; + security: { + hasPrivileges: jest.Mock; }; }; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts index b79bdc857a171..7ffa45e2bf7ee 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/privileges/read_privileges_route.test.ts @@ -19,7 +19,7 @@ describe('read_privileges route', () => { server = serverMock.create(); ({ context } = requestContextMock.createTools()); - context.core.elasticsearch.client.asCurrentUser.transport.request.mockResolvedValue({ + context.core.elasticsearch.client.asCurrentUser.security.hasPrivileges.mockResolvedValue({ body: getMockPrivilegesResult(), }); @@ -65,7 +65,7 @@ describe('read_privileges route', () => { }); test('returns 500 when bad response from cluster', async () => { - context.core.elasticsearch.client.asCurrentUser.transport.request.mockResolvedValue( + context.core.elasticsearch.client.asCurrentUser.security.hasPrivileges.mockResolvedValue( elasticsearchClientMock.createErrorTransportRequestPromise(new Error('Test error')) ); const response = await server.inject( From abffa79ba2be019faedb027f973f14aa4a581e1f Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 4 Oct 2021 20:57:25 +0200 Subject: [PATCH 64/98] [Uptime] Refactor snapshots into RTL (#113727) --- .../fingerprint_col.test.tsx.snap | 202 -- .../certificates/fingerprint_col.test.tsx | 21 +- .../uptime_date_picker.test.tsx.snap | 184 -- .../common/uptime_date_picker.test.tsx | 102 +- .../__snapshots__/license_info.test.tsx.snap | 78 - .../ml/__snapshots__/ml_flyout.test.tsx.snap | 242 --- .../monitor/ml/license_info.test.tsx | 12 +- .../components/monitor/ml/ml_flyout.test.tsx | 31 +- .../availability_reporting.test.tsx.snap | 368 ---- .../location_status_tags.test.tsx.snap | 1060 --------- .../availability_reporting.test.tsx | 19 +- .../availability_reporting.tsx | 7 +- .../location_status_tags.test.tsx | 46 +- .../__snapshots__/monitor_list.test.tsx.snap | 1917 ----------------- .../monitor_list/monitor_list.test.tsx | 92 +- .../uptime/public/lib/helper/rtl_helpers.tsx | 11 +- .../__snapshots__/certificates.test.tsx.snap | 91 - .../pages/__snapshots__/monitor.test.tsx.snap | 91 - .../__snapshots__/not_found.test.tsx.snap | 91 - .../__snapshots__/overview.test.tsx.snap | 91 - .../uptime/public/pages/certificates.test.tsx | 13 +- .../uptime/public/pages/monitor.test.tsx | 15 +- .../uptime/public/pages/not_found.test.tsx | 10 +- .../uptime/public/pages/overview.test.tsx | 12 +- 24 files changed, 183 insertions(+), 4623 deletions(-) delete mode 100644 x-pack/plugins/uptime/public/components/certificates/__snapshots__/fingerprint_col.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/components/common/__snapshots__/uptime_date_picker.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/components/monitor/ml/__snapshots__/license_info.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/components/monitor/ml/__snapshots__/ml_flyout.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/availability_reporting.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/location_status_tags.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/components/overview/monitor_list/__snapshots__/monitor_list.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/pages/__snapshots__/certificates.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/pages/__snapshots__/monitor.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/pages/__snapshots__/not_found.test.tsx.snap delete mode 100644 x-pack/plugins/uptime/public/pages/__snapshots__/overview.test.tsx.snap diff --git a/x-pack/plugins/uptime/public/components/certificates/__snapshots__/fingerprint_col.test.tsx.snap b/x-pack/plugins/uptime/public/components/certificates/__snapshots__/fingerprint_col.test.tsx.snap deleted file mode 100644 index 33969b3d83bcb..0000000000000 --- a/x-pack/plugins/uptime/public/components/certificates/__snapshots__/fingerprint_col.test.tsx.snap +++ /dev/null @@ -1,202 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`FingerprintCol renders expected elements for valid props 1`] = ` -.c1 .euiButtonEmpty__content { - padding-right: 0px; -} - -.c0 { - margin-right: 8px; -} - - - - - - - - - - - - - - - - - - - -`; - -exports[`FingerprintCol shallow renders expected elements for valid props 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/components/certificates/fingerprint_col.test.tsx b/x-pack/plugins/uptime/public/components/certificates/fingerprint_col.test.tsx index 1affd1f990f90..f3f4e206f6e2f 100644 --- a/x-pack/plugins/uptime/public/components/certificates/fingerprint_col.test.tsx +++ b/x-pack/plugins/uptime/public/components/certificates/fingerprint_col.test.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; -import { renderWithRouter, shallowWithRouter } from '../../lib'; -import { FingerprintCol } from './fingerprint_col'; import moment from 'moment'; +import { FingerprintCol } from './fingerprint_col'; +import { render } from '../../lib/helper/rtl_helpers'; describe('FingerprintCol', () => { const cert = { @@ -16,18 +16,19 @@ describe('FingerprintCol', () => { not_after: '2020-05-08T00:00:00.000Z', not_before: '2018-05-08T00:00:00.000Z', issuer: 'DigiCert SHA2 Extended Validation Server CA', - sha1: 'ca06f56b258b7a0d4f2b05470939478651151984', - sha256: '3111500c4a66012cdae333ec3fca1c9dde45c954440e7ee413716bff3663c074', + sha1: 'ca06f56b258b7a0d4f2b05470939478651151984'.toUpperCase(), + sha256: '3111500c4a66012cdae333ec3fca1c9dde45c954440e7ee413716bff3663c074'.toUpperCase(), common_name: 'github.com', }; - it('shallow renders expected elements for valid props', () => { - expect(shallowWithRouter()).toMatchSnapshot(); - }); - - it('renders expected elements for valid props', () => { + it('renders expected elements for valid props', async () => { cert.not_after = moment().add('4', 'months').toISOString(); + const { findByText, findByTestId } = render(); + + expect(await findByText('SHA 1')).toBeInTheDocument(); + expect(await findByText('SHA 256')).toBeInTheDocument(); - expect(renderWithRouter()).toMatchSnapshot(); + expect(await findByTestId(cert.sha1)).toBeInTheDocument(); + expect(await findByTestId(cert.sha256)).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/components/common/__snapshots__/uptime_date_picker.test.tsx.snap b/x-pack/plugins/uptime/public/components/common/__snapshots__/uptime_date_picker.test.tsx.snap deleted file mode 100644 index d513c0212da75..0000000000000 --- a/x-pack/plugins/uptime/public/components/common/__snapshots__/uptime_date_picker.test.tsx.snap +++ /dev/null @@ -1,184 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`UptimeDatePicker component renders properly with mock data 1`] = ` -

    -
    -
    -
    -
    - -
    -
    -
    -
    - -
    -
    -
    -
    -
    - - - -
    -
    -`; - -exports[`UptimeDatePicker component validates props with shallow render 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/components/common/uptime_date_picker.test.tsx b/x-pack/plugins/uptime/public/components/common/uptime_date_picker.test.tsx index f1b37d0c98f46..997831442faa2 100644 --- a/x-pack/plugins/uptime/public/components/common/uptime_date_picker.test.tsx +++ b/x-pack/plugins/uptime/public/components/common/uptime_date_picker.test.tsx @@ -7,52 +7,33 @@ import React from 'react'; import { UptimeDatePicker } from './uptime_date_picker'; -import { - renderWithRouter, - shallowWithRouter, - MountWithReduxProvider, - mountWithRouterRedux, -} from '../../lib'; -import { UptimeStartupPluginsContextProvider } from '../../contexts'; import { startPlugins } from '../../lib/__mocks__/uptime_plugin_start_mock'; -import { ClientPluginsStart } from '../../apps/plugin'; import { createMemoryHistory } from 'history'; +import { render } from '../../lib/helper/rtl_helpers'; +import { fireEvent } from '@testing-library/dom'; describe('UptimeDatePicker component', () => { - it('validates props with shallow render', () => { - const component = shallowWithRouter(); - expect(component).toMatchSnapshot(); + it('renders properly with mock data', async () => { + const { findByText } = render(); + expect(await findByText('Last 15 minutes')).toBeInTheDocument(); + expect(await findByText('Refresh')).toBeInTheDocument(); }); - it('renders properly with mock data', () => { - const component = renderWithRouter( - - - - ); - expect(component).toMatchSnapshot(); - }); + it('uses shared date range state when there is no url date range state', async () => { + const customHistory = createMemoryHistory({ + initialEntries: ['/?dateRangeStart=now-15m&dateRangeEnd=now'], + }); - it('uses shared date range state when there is no url date range state', () => { - const customHistory = createMemoryHistory(); jest.spyOn(customHistory, 'push'); - const component = mountWithRouterRedux( - )} - > - - , - { customHistory } - ); - - const startBtn = component.find('[data-test-subj="superDatePickerstartDatePopoverButton"]'); - - expect(startBtn.text()).toBe('~ 30 minutes ago'); + const { findByText } = render(, { + history: customHistory, + core: startPlugins, + }); - const endBtn = component.find('[data-test-subj="superDatePickerendDatePopoverButton"]'); + expect(await findByText('~ 15 minutes ago')).toBeInTheDocument(); - expect(endBtn.text()).toBe('~ 15 minutes ago'); + expect(await findByText('~ 30 minutes ago')).toBeInTheDocument(); expect(customHistory.push).toHaveBeenCalledWith({ pathname: '/', @@ -60,31 +41,60 @@ describe('UptimeDatePicker component', () => { }); }); - it('should use url date range even if shared date range is present', () => { + it('should use url date range even if shared date range is present', async () => { + const customHistory = createMemoryHistory({ + initialEntries: ['/?g=%22%22&dateRangeStart=now-10m&dateRangeEnd=now'], + }); + + jest.spyOn(customHistory, 'push'); + + const { findByText } = render(, { + history: customHistory, + core: startPlugins, + }); + + expect(await findByText('Last 10 minutes')).toBeInTheDocument(); + + // it should update shared state + + expect(startPlugins.data.query.timefilter.timefilter.setTime).toHaveBeenCalledWith({ + from: 'now-10m', + to: 'now', + }); + }); + + it('should handle on change', async () => { const customHistory = createMemoryHistory({ initialEntries: ['/?g=%22%22&dateRangeStart=now-10m&dateRangeEnd=now'], }); jest.spyOn(customHistory, 'push'); - const component = mountWithRouterRedux( - )} - > - - , - { customHistory } - ); + const { findByText, getByTestId, findByTestId } = render(, { + history: customHistory, + core: startPlugins, + }); + + expect(await findByText('Last 10 minutes')).toBeInTheDocument(); - const showDateBtn = component.find('[data-test-subj="superDatePickerShowDatesButton"]'); + fireEvent.click(getByTestId('superDatePickerToggleQuickMenuButton')); - expect(showDateBtn.childAt(0).text()).toBe('Last 10 minutes'); + fireEvent.click(await findByTestId('superDatePickerCommonlyUsed_Today')); + + expect(await findByText('Today')).toBeInTheDocument(); // it should update shared state + expect(startPlugins.data.query.timefilter.timefilter.setTime).toHaveBeenCalledTimes(3); + expect(startPlugins.data.query.timefilter.timefilter.setTime).toHaveBeenCalledWith({ from: 'now-10m', to: 'now', }); + + expect(startPlugins.data.query.timefilter.timefilter.setTime).toHaveBeenLastCalledWith({ + from: 'now/d', + to: 'now', + }); }); }); diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__snapshots__/license_info.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__snapshots__/license_info.test.tsx.snap deleted file mode 100644 index 98414f82bf197..0000000000000 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__snapshots__/license_info.test.tsx.snap +++ /dev/null @@ -1,78 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ShowLicenseInfo renders without errors 1`] = ` -Array [ -
    -
    -
    -
    -
    -

    - In order to access duration anomaly detection, you have to be subscribed to an Elastic Platinum license. -

    - - - - Start free 14-day trial - - - -
    -
    -
    , -
    , -] -`; - -exports[`ShowLicenseInfo shallow renders without errors 1`] = ` - - -

    - In order to access duration anomaly detection, you have to be subscribed to an Elastic Platinum license. -

    - - Start free 14-day trial - -
    - -
    -`; diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/__snapshots__/ml_flyout.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ml/__snapshots__/ml_flyout.test.tsx.snap deleted file mode 100644 index e4672338485fa..0000000000000 --- a/x-pack/plugins/uptime/public/components/monitor/ml/__snapshots__/ml_flyout.test.tsx.snap +++ /dev/null @@ -1,242 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ML Flyout component renders without errors 1`] = ` - - - -

    - Enable anomaly detection -

    -
    - -
    - - -

    - Here you can create a machine learning job to calculate anomaly scores on - response durations for Uptime Monitor. Once enabled, the monitor duration chart on the details page - will show the expected bounds and annotate the graph with anomalies. You can also potentially - identify periods of increased latency across geographical regions. -

    -

    - - Machine Learning jobs management page - , - } - } - /> -

    -

    - - Note: It might take a few minutes for the job to begin calculating results. - -

    -
    - -
    - - - - - Cancel - - - - - Create new job - - - - -
    -`; - -exports[`ML Flyout component shows license info if no ml available 1`] = ` -
    - -
    -
    - -
    -
    -
    -
    -`; diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/license_info.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/license_info.test.tsx index aa175715970c9..f8e0c44c2b8c9 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/license_info.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/license_info.test.tsx @@ -6,9 +6,9 @@ */ import React from 'react'; -import { renderWithIntl, shallowWithIntl } from '@kbn/test/jest'; import { ShowLicenseInfo } from './license_info'; import * as redux from 'react-redux'; +import { render } from '../../../lib/helper/rtl_helpers'; describe('ShowLicenseInfo', () => { beforeEach(() => { @@ -18,13 +18,9 @@ describe('ShowLicenseInfo', () => { const spy1 = jest.spyOn(redux, 'useSelector'); spy1.mockReturnValue(true); }); - it('shallow renders without errors', () => { - const wrapper = shallowWithIntl(); - expect(wrapper).toMatchSnapshot(); - }); - it('renders without errors', () => { - const wrapper = renderWithIntl(); - expect(wrapper).toMatchSnapshot(); + it('renders without errors', async () => { + const { findAllByText } = render(); + expect((await findAllByText('Start free 14-day trial'))[0]).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.test.tsx b/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.test.tsx index 200087976bc82..d066bf416e083 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ml/ml_flyout.test.tsx @@ -6,11 +6,12 @@ */ import React from 'react'; -import { renderWithIntl, shallowWithIntl } from '@kbn/test/jest'; import { MLFlyoutView } from './ml_flyout'; import { UptimeSettingsContext } from '../../../contexts'; import { CLIENT_DEFAULTS } from '../../../../common/constants'; import * as redux from 'react-redux'; +import { render } from '../../../lib/helper/rtl_helpers'; +import * as labels from './translations'; describe('ML Flyout component', () => { const createJob = () => {}; @@ -25,18 +26,7 @@ describe('ML Flyout component', () => { spy1.mockReturnValue(true); }); - it('renders without errors', () => { - const wrapper = shallowWithIntl( - - ); - expect(wrapper).toMatchSnapshot(); - }); - it('shows license info if no ml available', () => { + it('shows license info if no ml available', async () => { const spy1 = jest.spyOn(redux, 'useSelector'); // return false value for no license @@ -50,7 +40,7 @@ describe('ML Flyout component', () => { isInfraAvailable: true, isLogsAvailable: true, }; - const wrapper = renderWithIntl( + const { findByText, findAllByText } = render( { /> ); - const licenseComponent = wrapper.find('.license-info-trial'); - expect(licenseComponent.length).toBe(1); - expect(wrapper).toMatchSnapshot(); + + expect(await findByText(labels.ENABLE_ANOMALY_DETECTION)).toBeInTheDocument(); + expect(await findAllByText(labels.START_TRAIL)).toHaveLength(2); }); - it('able to create job if valid license is available', () => { + it('able to create job if valid license is available', async () => { const value = { basePath: '', dateRangeStart: DATE_RANGE_START, @@ -74,7 +64,7 @@ describe('ML Flyout component', () => { isInfraAvailable: true, isLogsAvailable: true, }; - const wrapper = renderWithIntl( + const { queryByText } = render( { ); - const licenseComponent = wrapper.find('.license-info-trial'); - expect(licenseComponent.length).toBe(0); + expect(queryByText(labels.START_TRAIL)).not.toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/availability_reporting.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/availability_reporting.test.tsx.snap deleted file mode 100644 index 5a660c7cb764f..0000000000000 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/availability_reporting.test.tsx.snap +++ /dev/null @@ -1,368 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`AvailabilityReporting component renders correctly against snapshot 1`] = ` -Array [ - @media (max-width:1042px) { - -} - -
    , - .c0 { - white-space: nowrap; - display: inline-block; -} - -@media (max-width:1042px) { - .c0 { - display: inline-block; - margin-right: 16px; - } -} - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - Location - - - - - - Availability - - - - - - Last check - - -
    -
    - Location -
    -
    -
    - - - - au-heartbeat - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - 36m ago - -
    -
    -
    - Location -
    -
    -
    - - - - nyc-heartbeat - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - 36m ago - -
    -
    -
    - Location -
    -
    -
    - - - - spa-heartbeat - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - 36m ago - -
    -
    -
    -
    , -] -`; - -exports[`AvailabilityReporting component shallow renders correctly against snapshot 1`] = ` - - - - -`; diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/location_status_tags.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/location_status_tags.test.tsx.snap deleted file mode 100644 index c30469eab3c3b..0000000000000 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/location_status_tags.test.tsx.snap +++ /dev/null @@ -1,1060 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`LocationStatusTags component renders properly against props 1`] = ` - - - - - -`; - -exports[`LocationStatusTags component renders when all locations are down 1`] = ` -.c1 { - white-space: nowrap; - display: inline-block; -} - -.c0 { - max-height: 246px; - overflow: hidden; -} - -@media (max-width:1042px) { - .c1 { - display: inline-block; - margin-right: 16px; - } -} - -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - -
    -
    - - - Location - - - - - - Availability - - - - - - Last check - - -
    -
    - Location -
    -
    -
    - - - - Berlin - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    - Location -
    -
    -
    - - - - Islamabad - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    -
    -
    -`; - -exports[`LocationStatusTags component renders when all locations are up 1`] = ` -.c1 { - white-space: nowrap; - display: inline-block; -} - -.c0 { - max-height: 246px; - overflow: hidden; -} - -@media (max-width:1042px) { - .c1 { - display: inline-block; - margin-right: 16px; - } -} - -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - -
    -
    - - - Location - - - - - - Availability - - - - - - Last check - - -
    -
    - Location -
    -
    -
    - - - - Berlin - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    - Location -
    -
    -
    - - - - Islamabad - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    -
    -
    -`; - -exports[`LocationStatusTags component renders when there are many location 1`] = ` -.c1 { - white-space: nowrap; - display: inline-block; -} - -.c0 { - max-height: 246px; - overflow: hidden; -} - -@media (max-width:1042px) { - .c1 { - display: inline-block; - margin-right: 16px; - } -} - -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - Location - - - - - - Availability - - - - - - Last check - - -
    -
    - Location -
    -
    -
    - - - - Berlin - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    - Location -
    -
    -
    - - - - Islamabad - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    - Location -
    -
    -
    - - - - New York - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    - Location -
    -
    -
    - - - - Paris - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    - Location -
    -
    -
    - - - - Sydney - - - -
    -
    -
    -
    - Availability -
    -
    - - 100.00 % - -
    -
    -
    - Last check -
    -
    - - Sept 4, 2020 9:31:38 AM - -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -`; diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/availability_reporting.test.tsx b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/availability_reporting.test.tsx index 3b1f15dc46f77..f62a308daa6d1 100644 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/availability_reporting.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/availability_reporting.test.tsx @@ -6,15 +6,9 @@ */ import React from 'react'; -import { renderWithIntl, shallowWithIntl } from '@kbn/test/jest'; import { AvailabilityReporting } from './availability_reporting'; import { StatusTag } from './location_status_tags'; - -jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => { - return { - htmlIdGenerator: () => () => `generated-id`, - }; -}); +import { render } from '../../../../lib/helper/rtl_helpers'; describe('AvailabilityReporting component', () => { let allLocations: StatusTag[]; @@ -45,13 +39,10 @@ describe('AvailabilityReporting component', () => { ]; }); - it('shallow renders correctly against snapshot', () => { - const component = shallowWithIntl(); - expect(component).toMatchSnapshot(); - }); + it('renders correctly against snapshot', async () => { + const { findByText } = render(); - it('renders correctly against snapshot', () => { - const component = renderWithIntl(); - expect(component).toMatchSnapshot(); + expect(await findByText('This table contains 3 rows.')).toBeInTheDocument(); + expect(await findByText('au-heartbeat')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/availability_reporting.tsx b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/availability_reporting.tsx index c17d2dd97d325..878752ef3ede5 100644 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/availability_reporting.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/availability_reporting.tsx @@ -6,9 +6,8 @@ */ import React, { useState } from 'react'; -import { EuiBasicTable, EuiSpacer } from '@elastic/eui'; +import { EuiBasicTable, EuiSpacer, Criteria, Pagination } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { Pagination } from '@elastic/eui/src/components/basic_table/pagination_bar'; import { StatusTag } from './location_status_tags'; import { TagLabel } from './tag_label'; import { AvailabilityLabel, LastCheckLabel, LocationLabel } from '../translations'; @@ -66,8 +65,8 @@ export const AvailabilityReporting: React.FC = ({ allLocations }) => { hidePerPageOptions: true, }; - const onTableChange = ({ page }: any) => { - setPageIndex(page.index); + const onTableChange = ({ page }: Criteria) => { + setPageIndex(page?.index ?? 0); }; const paginationProps = allLocations.length > pageSize ? { pagination } : {}; diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/location_status_tags.test.tsx b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/location_status_tags.test.tsx index 6b3cc23465833..3db2efd098082 100644 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/location_status_tags.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/location_status_tags.test.tsx @@ -6,10 +6,10 @@ */ import React from 'react'; -import { renderWithIntl, shallowWithIntl } from '@kbn/test/jest'; import { MonitorLocation } from '../../../../../common/runtime_types/monitor'; import { LocationStatusTags } from './index'; import { mockMoment } from '../../../../lib/helper/test_helpers'; +import { render } from '../../../../lib/helper/rtl_helpers'; mockMoment(); @@ -22,7 +22,7 @@ jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => { describe('LocationStatusTags component', () => { let monitorLocations: MonitorLocation[]; - it('renders properly against props', () => { + it('renders properly against props', async () => { monitorLocations = [ { summary: { up: 4, down: 0 }, @@ -36,21 +36,21 @@ describe('LocationStatusTags component', () => { geo: { name: 'Berlin', location: { lat: '52.487448', lon: ' 13.394798' } }, timestamp: 'Oct 26, 2020 7:49:20 AM', up_history: 4, - down_history: 0, + down_history: 2, }, { summary: { up: 0, down: 2 }, geo: { name: 'Berlin', location: { lat: '52.487448', lon: ' 13.394798' } }, timestamp: 'Oct 26, 2020 7:49:20 AM', up_history: 4, - down_history: 0, + down_history: 1, }, ]; - const component = shallowWithIntl(); - expect(component).toMatchSnapshot(); + const { findByText } = render(); + expect(await findByText('100.00 %')).toBeInTheDocument(); }); - it('renders when there are many location', () => { + it('renders when there are many location', async () => { monitorLocations = [ { summary: { up: 0, down: 1 }, @@ -64,28 +64,28 @@ describe('LocationStatusTags component', () => { geo: { name: 'Berlin', location: { lat: '52.487448', lon: ' 13.394798' } }, timestamp: 'Oct 26, 2020 7:49:20 AM', up_history: 4, - down_history: 0, + down_history: 3, }, { summary: { up: 0, down: 1 }, geo: { name: 'st-paul', location: { lat: '52.487448', lon: ' 13.394798' } }, timestamp: 'Oct 26, 2020 7:49:20 AM', up_history: 4, - down_history: 0, + down_history: 2, }, { summary: { up: 0, down: 1 }, geo: { name: 'Tokyo', location: { lat: '52.487448', lon: ' 13.394798' } }, timestamp: 'Oct 26, 2020 7:49:20 AM', up_history: 4, - down_history: 0, + down_history: 1, }, { summary: { up: 0, down: 1 }, geo: { name: 'New York', location: { lat: '52.487448', lon: ' 13.394798' } }, timestamp: 'Oct 26, 2020 7:49:20 AM', up_history: 4, - down_history: 0, + down_history: 4, }, { summary: { up: 0, down: 1 }, @@ -109,11 +109,11 @@ describe('LocationStatusTags component', () => { down_history: 0, }, ]; - const component = renderWithIntl(); - expect(component).toMatchSnapshot(); + const { findAllByText } = render(); + expect(await findAllByText('100.00 %')).toHaveLength(3); }); - it('renders when all locations are up', () => { + it('renders when all locations are up', async () => { monitorLocations = [ { summary: { up: 4, down: 0 }, @@ -130,28 +130,28 @@ describe('LocationStatusTags component', () => { down_history: 0, }, ]; - const component = renderWithIntl(); - expect(component).toMatchSnapshot(); + const { findAllByText } = render(); + expect(await findAllByText('100.00 %')).toHaveLength(2); }); - it('renders when all locations are down', () => { + it('renders when all locations are down', async () => { monitorLocations = [ { summary: { up: 0, down: 2 }, geo: { name: 'Islamabad', location: { lat: '52.487448', lon: ' 13.394798' } }, timestamp: 'Oct 26, 2020 7:49:20 AM', - up_history: 4, - down_history: 0, + up_history: 0, + down_history: 2, }, { summary: { up: 0, down: 2 }, geo: { name: 'Berlin', location: { lat: '52.487448', lon: ' 13.394798' } }, timestamp: 'Oct 26, 2020 7:49:20 AM', - up_history: 4, - down_history: 0, + up_history: 0, + down_history: 2, }, ]; - const component = renderWithIntl(); - expect(component).toMatchSnapshot(); + const { findAllByText } = render(); + expect(await findAllByText('0.00 %')).toHaveLength(2); }); }); diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/__snapshots__/monitor_list.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/monitor_list/__snapshots__/monitor_list.test.tsx.snap deleted file mode 100644 index e6e7250dd5533..0000000000000 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/__snapshots__/monitor_list.test.tsx.snap +++ /dev/null @@ -1,1917 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`MonitorList component MonitorListPagination component renders a no items message when no data is provided 1`] = ` - - - - - -`; - -exports[`MonitorList component MonitorListPagination component renders the pagination 1`] = ` - - - - - -`; - -exports[`MonitorList component renders a no items message when no data is provided 1`] = ` - - - - - -`; - -exports[`MonitorList component renders error list 1`] = ` - - - - - -`; - -exports[`MonitorList component renders loading state 1`] = ` - - - - - -`; - -exports[`MonitorList component renders the monitor list 1`] = ` -.c2 { - padding-right: 4px; -} - -.c3 { - margin-top: 12px; -} - -.c0 { - position: relative; -} - -@media (max-width:574px) { - .c1 { - min-width: 230px; - } -} - -
    -
    -
    -
    - Monitors -
    -
    -
    -
    - - - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - Status - - - - - - Name - - - - - - Url - - - - - - Tags - - - - - - TLS Certificate - - - - - - Downtime history - - - - - - Status alert - - - - - - -
    -
    - Status -
    -
    -
    -
    -
    - - - -
    -
    -
    -
    - -
    -
    - in 0/1 location, -
    -
    -
    - -
    -
    - Checked Sept 4, 2020 9:31:38 AM -
    -
    -
    -
    -
    -
    -
    -
    - Name -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - Url -
    -
    -
    -
    -
    - Tags -
    -
    -
    -
    - TLS Certificate -
    -
    - - -- - -
    -
    -
    - -
    -
    - -- -
    -
    -
    -
    -
    -
    - Status alert -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    - Status -
    -
    -
    -
    -
    - - - -
    -
    -
    -
    - -
    -
    - in 0/1 location, -
    -
    -
    - -
    -
    - Checked Sept 4, 2020 9:31:38 AM -
    -
    -
    -
    -
    -
    -
    -
    - Name -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - Url -
    -
    -
    -
    -
    - Tags -
    -
    -
    -
    - TLS Certificate -
    -
    - - -- - -
    -
    -
    - -
    -
    - -- -
    -
    -
    -
    -
    -
    - Status alert -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -`; - -exports[`MonitorList component shallow renders the monitor list 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.test.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.test.tsx index 3a32d8c943af6..703e2653ff0aa 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.test.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.test.tsx @@ -16,13 +16,12 @@ import { MonitorSummary, } from '../../../../common/runtime_types'; import { MonitorListComponent, noItemsMessage } from './monitor_list'; -import { renderWithRouter, shallowWithRouter } from '../../../lib'; import * as redux from 'react-redux'; import moment from 'moment'; import { IHttpFetchError } from '../../../../../../../src/core/public'; import { mockMoment } from '../../../lib/helper/test_helpers'; import { render } from '../../../lib/helper/rtl_helpers'; -import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common'; +import { NO_DATA_MESSAGE } from './translations'; jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => { return { @@ -150,20 +149,8 @@ describe('MonitorList component', () => { global.localStorage = localStorageMock; }); - it('shallow renders the monitor list', () => { - const component = shallowWithRouter( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('renders a no items message when no data is provided', () => { - const component = shallowWithRouter( + it('renders a no items message when no data is provided', async () => { + const { findByText } = render( { nextPagePagination: null, prevPagePagination: null, }, - loading: true, + loading: false, }} pageSize={10} setPageSize={jest.fn()} /> ); - expect(component).toMatchSnapshot(); - }); - - it('renders the monitor list', () => { - const component = renderWithRouter( - - - - ); - - expect(component).toMatchSnapshot(); + expect(await findByText(NO_DATA_MESSAGE)).toBeInTheDocument(); }); - it('renders error list', () => { - const component = shallowWithRouter( + it('renders the monitor list', async () => { + const { findByLabelText } = render( { /> ); - expect(component).toMatchSnapshot(); + expect( + await findByLabelText( + 'Monitor Status table with columns for Status, Name, URL, IP, Downtime History and Integrations. The table is currently displaying 2 items.' + ) + ).toBeInTheDocument(); }); - it('renders loading state', () => { - const component = shallowWithRouter( + it('renders error list', async () => { + const { findByText } = render( ); - expect(component).toMatchSnapshot(); + expect(await findByText('foo message')).toBeInTheDocument(); }); describe('MonitorListPagination component', () => { @@ -244,8 +221,8 @@ describe('MonitorList component', () => { }; }); - it('renders the pagination', () => { - const component = shallowWithRouter( + it('renders the pagination', async () => { + const { findByText, findByLabelText } = render( { /> ); - expect(component).toMatchSnapshot(); - }); - - it('renders a no items message when no data is provided', () => { - const component = shallowWithRouter( - - ); - - expect(component).toMatchSnapshot(); + expect(await findByText('Rows per page: 10')).toBeInTheDocument(); + expect(await findByLabelText('Prev page of results')).toBeInTheDocument(); + expect(await findByLabelText('Next page of results')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/lib/helper/rtl_helpers.tsx b/x-pack/plugins/uptime/public/lib/helper/rtl_helpers.tsx index 46f77b547779c..ac129bdb327d9 100644 --- a/x-pack/plugins/uptime/public/lib/helper/rtl_helpers.tsx +++ b/x-pack/plugins/uptime/public/lib/helper/rtl_helpers.tsx @@ -29,6 +29,7 @@ import { stringifyUrlParams } from './stringify_url_params'; import { ClientPluginsStart } from '../../apps/plugin'; import { triggersActionsUiMock } from '../../../../triggers_actions_ui/public/mocks'; import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; +import { UptimeRefreshContextProvider, UptimeStartupPluginsContextProvider } from '../../contexts'; interface KibanaProps { services?: KibanaServices; @@ -129,9 +130,13 @@ export function MockKibanaProvider({ }; return ( - - {children} - + + + + {children} + + + ); } diff --git a/x-pack/plugins/uptime/public/pages/__snapshots__/certificates.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__snapshots__/certificates.test.tsx.snap deleted file mode 100644 index e1009236ef4b8..0000000000000 --- a/x-pack/plugins/uptime/public/pages/__snapshots__/certificates.test.tsx.snap +++ /dev/null @@ -1,91 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CertificatesPage shallow renders expected elements for valid props 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/pages/__snapshots__/monitor.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__snapshots__/monitor.test.tsx.snap deleted file mode 100644 index cd92334cf72f5..0000000000000 --- a/x-pack/plugins/uptime/public/pages/__snapshots__/monitor.test.tsx.snap +++ /dev/null @@ -1,91 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`MonitorPage shallow renders expected elements for valid props 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/pages/__snapshots__/not_found.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__snapshots__/not_found.test.tsx.snap deleted file mode 100644 index df67e320d7aac..0000000000000 --- a/x-pack/plugins/uptime/public/pages/__snapshots__/not_found.test.tsx.snap +++ /dev/null @@ -1,91 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`NotFoundPage render component for valid props 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/pages/__snapshots__/overview.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__snapshots__/overview.test.tsx.snap deleted file mode 100644 index 3e532d0d8e78d..0000000000000 --- a/x-pack/plugins/uptime/public/pages/__snapshots__/overview.test.tsx.snap +++ /dev/null @@ -1,91 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`MonitorPage shallow renders expected elements for valid props 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/uptime/public/pages/certificates.test.tsx b/x-pack/plugins/uptime/public/pages/certificates.test.tsx index ff5f1afcaa290..d61fde13663a7 100644 --- a/x-pack/plugins/uptime/public/pages/certificates.test.tsx +++ b/x-pack/plugins/uptime/public/pages/certificates.test.tsx @@ -6,11 +6,18 @@ */ import React from 'react'; -import { shallowWithRouter } from '../lib'; import { CertificatesPage } from './certificates'; +import { render } from '../lib/helper/rtl_helpers'; describe('CertificatesPage', () => { - it('shallow renders expected elements for valid props', () => { - expect(shallowWithRouter()).toMatchSnapshot(); + it('renders expected elements for valid props', async () => { + const { findByText } = render(); + + expect(await findByText('This table contains 0 rows; Page 1 of 0.')).toBeInTheDocument(); + expect( + await findByText( + 'No Certificates found. Note: Certificates are only visible for Heartbeat 7.8+' + ) + ).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/pages/monitor.test.tsx b/x-pack/plugins/uptime/public/pages/monitor.test.tsx index 80fcfcc271964..053121d505de5 100644 --- a/x-pack/plugins/uptime/public/pages/monitor.test.tsx +++ b/x-pack/plugins/uptime/public/pages/monitor.test.tsx @@ -7,10 +7,19 @@ import React from 'react'; import { MonitorPage } from './monitor'; -import { shallowWithRouter } from '../lib'; +import { render } from '../lib/helper/rtl_helpers'; describe('MonitorPage', () => { - it('shallow renders expected elements for valid props', () => { - expect(shallowWithRouter()).toMatchSnapshot(); + it('renders', async () => { + const { findByText } = render(); + + expect(await findByText('Up in 0 location')).toBeInTheDocument(); + expect(await findByText('Overall availability')).toBeInTheDocument(); + expect(await findByText('0.00 %')).toBeInTheDocument(); + expect(await findByText('Url')).toBeInTheDocument(); + expect(await findByText('Monitor ID')).toBeInTheDocument(); + expect(await findByText('Tags')).toBeInTheDocument(); + expect(await findByText('Set tags')).toBeInTheDocument(); + expect(await findByText('Monitoring from')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/pages/not_found.test.tsx b/x-pack/plugins/uptime/public/pages/not_found.test.tsx index 8d5b20e45303d..23f753478417c 100644 --- a/x-pack/plugins/uptime/public/pages/not_found.test.tsx +++ b/x-pack/plugins/uptime/public/pages/not_found.test.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; -import { shallowWithRouter } from '../lib'; import { NotFoundPage } from './not_found'; +import { render } from '../lib/helper/rtl_helpers'; describe('NotFoundPage', () => { - it('render component for valid props', () => { - const component = shallowWithRouter(); - expect(component).toMatchSnapshot(); + it('render component', async () => { + const { findByText } = render(); + + expect(await findByText('Page not found')).toBeInTheDocument(); + expect(await findByText('Back to home')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/uptime/public/pages/overview.test.tsx b/x-pack/plugins/uptime/public/pages/overview.test.tsx index f827cf66b0347..b3aa4714fa664 100644 --- a/x-pack/plugins/uptime/public/pages/overview.test.tsx +++ b/x-pack/plugins/uptime/public/pages/overview.test.tsx @@ -7,10 +7,16 @@ import React from 'react'; import { OverviewPageComponent } from './overview'; -import { shallowWithRouter } from '../lib'; +import { render } from '../lib/helper/rtl_helpers'; describe('MonitorPage', () => { - it('shallow renders expected elements for valid props', () => { - expect(shallowWithRouter()).toMatchSnapshot(); + it('renders expected elements for valid props', async () => { + const { findByText, findByPlaceholderText } = render(); + + expect(await findByText('No uptime monitors found')).toBeInTheDocument(); + + expect( + await findByPlaceholderText('Search by monitor ID, name, or url (E.g. http:// )') + ).toBeInTheDocument(); }); }); From 257e33a50ef14156427a0cfd16d0a1f834d52074 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Mon, 4 Oct 2021 12:11:05 -0700 Subject: [PATCH 65/98] Partial forward-port of dacf0c2a6cabf088b0f17f4eca57e01c466286c0. (#113672) - Add Authorization type to ES UI shared. - Add convertPrivilegesToArray, patch to also accept privileges that might contain dots in its name, and add tests. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/authorization_provider.tsx | 2 +- .../authorization/components/index.ts | 1 + .../components/with_privileges.test.ts | 28 +++++++++++++++++ .../components/with_privileges.tsx | 31 ++++++++++++------- .../authorization/index.ts | 1 + src/plugins/es_ui_shared/common/index.ts | 2 +- .../public/authorization/index.ts | 1 + src/plugins/es_ui_shared/public/index.ts | 1 + 8 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/with_privileges.test.ts diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/authorization_provider.tsx b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/authorization_provider.tsx index be49a7697afca..7d8d00156e541 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/authorization_provider.tsx +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/authorization_provider.tsx @@ -13,7 +13,7 @@ import { useRequest } from '../../../public/request'; import { Privileges, Error as CustomError } from '../types'; -interface Authorization { +export interface Authorization { isLoading: boolean; apiError: CustomError | null; privileges: Privileges; diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/index.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/index.ts index f8eb7e3c7c0c8..75d79a204f141 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/index.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/index.ts @@ -10,6 +10,7 @@ export { AuthorizationProvider, AuthorizationContext, useAuthorizationContext, + Authorization, } from './authorization_provider'; export { WithPrivileges } from './with_privileges'; diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/with_privileges.test.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/with_privileges.test.ts new file mode 100644 index 0000000000000..243bfdb995f5d --- /dev/null +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/with_privileges.test.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { convertPrivilegesToArray } from './with_privileges'; + +describe('convertPrivilegesToArray', () => { + test('extracts section and privilege', () => { + expect(convertPrivilegesToArray('index.index_name')).toEqual([['index', 'index_name']]); + expect(convertPrivilegesToArray(['index.index_name', 'cluster.management'])).toEqual([ + ['index', 'index_name'], + ['cluster', 'management'], + ]); + expect(convertPrivilegesToArray('index.index_name.with-many.dots')).toEqual([ + ['index', 'index_name.with-many.dots'], + ]); + }); + + test('throws when it cannot extract section and privilege', () => { + expect(() => { + convertPrivilegesToArray('bad_privilege_string'); + }).toThrow('Required privilege must have the format "section.privilege"'); + }); +}); diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/with_privileges.tsx b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/with_privileges.tsx index c0e675877c562..6485bd7f45e55 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/with_privileges.tsx +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/components/with_privileges.tsx @@ -10,13 +10,14 @@ import { MissingPrivileges } from '../types'; import { useAuthorizationContext } from './authorization_provider'; +type Privileges = string | string[]; interface Props { /** * Each required privilege must have the format "section.privilege". * To indicate that *all* privileges from a section are required, we can use the asterix * e.g. "index.*" */ - privileges: string | string[]; + privileges: Privileges; children: (childrenProps: { isLoading: boolean; hasPrivileges: boolean; @@ -26,24 +27,30 @@ interface Props { type Privilege = [string, string]; -const toArray = (value: string | string[]): string[] => +const toArray = (value: Privileges): string[] => Array.isArray(value) ? (value as string[]) : ([value] as string[]); -export const WithPrivileges = ({ privileges: requiredPrivileges, children }: Props) => { - const { isLoading, privileges } = useAuthorizationContext(); - - const privilegesToArray: Privilege[] = toArray(requiredPrivileges).map((p) => { - const [section, privilege] = p.split('.'); - if (!privilege) { - // Oh! we forgot to use the dot "." notation. +export const convertPrivilegesToArray = (privileges: Privileges): Privilege[] => { + return toArray(privileges).map((p) => { + // Since an privilege can contain a dot in its name: + // * `section` needs to be extracted from the beginning of the string until the first dot + // * `privilege` should be everything after the dot + const indexOfFirstPeriod = p.indexOf('.'); + if (indexOfFirstPeriod === -1) { throw new Error('Required privilege must have the format "section.privilege"'); } - return [section, privilege]; + + return [p.slice(0, indexOfFirstPeriod), p.slice(indexOfFirstPeriod + 1)]; }); +}; + +export const WithPrivileges = ({ privileges: requiredPrivileges, children }: Props) => { + const { isLoading, privileges } = useAuthorizationContext(); + const privilegesArray = convertPrivilegesToArray(requiredPrivileges); const hasPrivileges = isLoading ? false - : privilegesToArray.every((privilege) => { + : privilegesArray.every((privilege) => { const [section, requiredPrivilege] = privilege; if (!privileges.missingPrivileges[section]) { // if the section does not exist in our missingPriviledges, everything is OK @@ -61,7 +68,7 @@ export const WithPrivileges = ({ privileges: requiredPrivileges, children }: Pro return !privileges.missingPrivileges[section]!.includes(requiredPrivilege); }); - const privilegesMissing = privilegesToArray.reduce((acc, [section, privilege]) => { + const privilegesMissing = privilegesArray.reduce((acc, [section, privilege]) => { if (privilege === '*') { acc[section] = privileges.missingPrivileges[section] || []; } else if ( diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/index.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/index.ts index e63d98512a2cd..9ccbc5a5cd3df 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/index.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/authorization/index.ts @@ -14,6 +14,7 @@ export { SectionError, PageError, useAuthorizationContext, + Authorization, } from './components'; export { Privileges, MissingPrivileges, Error } from './types'; diff --git a/src/plugins/es_ui_shared/common/index.ts b/src/plugins/es_ui_shared/common/index.ts index b8cfe0ae48585..1c2955b8e5e28 100644 --- a/src/plugins/es_ui_shared/common/index.ts +++ b/src/plugins/es_ui_shared/common/index.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export { Privileges, MissingPrivileges } from '../__packages_do_not_import__/authorization'; +export { Privileges, MissingPrivileges } from '../__packages_do_not_import__/authorization/types'; diff --git a/src/plugins/es_ui_shared/public/authorization/index.ts b/src/plugins/es_ui_shared/public/authorization/index.ts index f68ad3da2a4b5..b8fb2f45794ee 100644 --- a/src/plugins/es_ui_shared/public/authorization/index.ts +++ b/src/plugins/es_ui_shared/public/authorization/index.ts @@ -17,4 +17,5 @@ export { PageError, useAuthorizationContext, WithPrivileges, + Authorization, } from '../../__packages_do_not_import__/authorization'; diff --git a/src/plugins/es_ui_shared/public/index.ts b/src/plugins/es_ui_shared/public/index.ts index 9db00bc4be8df..2dc50536ca631 100644 --- a/src/plugins/es_ui_shared/public/index.ts +++ b/src/plugins/es_ui_shared/public/index.ts @@ -45,6 +45,7 @@ export { PageError, Error, useAuthorizationContext, + Authorization, } from './authorization'; export { Forms, ace, GlobalFlyout, XJson }; From 2dac93cb4cb6148978e6a1cb1ad479af90abcfe7 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Mon, 4 Oct 2021 15:15:49 -0400 Subject: [PATCH 66/98] [App Search] Wired up Suggestion detail data (#113796) --- .../curation_result_panel.test.tsx | 23 ++ .../curation_result_panel.tsx | 16 +- .../curation_suggestion.test.tsx | 95 +++++++- .../curation_suggestion.tsx | 72 +++++- .../curation_suggestion_logic.test.ts | 226 ++++++++++++++++++ .../curation_suggestion_logic.ts | 131 ++++++++++ .../search_relevance_suggestions.test.ts | 24 ++ .../search_relevance_suggestions.ts | 25 ++ 8 files changed, 587 insertions(+), 25 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.test.tsx index fad4e54721bb3..80d5a874c8102 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.test.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import { setMockValues } from '../../../../../__mocks__/kea_logic'; + import React from 'react'; import { shallow } from 'enzyme'; @@ -14,6 +16,13 @@ import { Result } from '../../../result'; import { CurationResultPanel } from './curation_result_panel'; describe('CurationResultPanel', () => { + const values = { + isMetaEngine: true, + engine: { + schema: {}, + }, + }; + const results = [ { id: { raw: 'foo' }, @@ -25,6 +34,10 @@ describe('CurationResultPanel', () => { }, ]; + beforeAll(() => { + setMockValues(values); + }); + beforeEach(() => { jest.clearAllMocks(); }); @@ -33,6 +46,11 @@ describe('CurationResultPanel', () => { const wrapper = shallow(); expect(wrapper.find('[data-test-subj="suggestedText"]').exists()).toBe(false); expect(wrapper.find(Result).length).toBe(2); + expect(wrapper.find(Result).at(0).props()).toEqual({ + result: results[0], + isMetaEngine: true, + schemaForTypeHighlights: values.engine.schema, + }); }); it('renders a no results message when there are no results', () => { @@ -41,6 +59,11 @@ describe('CurationResultPanel', () => { expect(wrapper.find(Result).length).toBe(0); }); + it('renders the correct count', () => { + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="curationCount"]').prop('children')).toBe(2); + }); + it('shows text about automation when variant is "suggested"', () => { const wrapper = shallow(); expect(wrapper.find('[data-test-subj="suggestedText"]').exists()).toBe(true); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.tsx index 12bbf07f97bb3..b61355d0b8555 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_result_panel.tsx @@ -7,6 +7,8 @@ import React from 'react'; +import { useValues } from 'kea'; + import { EuiFlexGroup, EuiFlexItem, @@ -17,6 +19,8 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { EngineLogic } from '../../../engine'; + import { Result } from '../../../result'; import { Result as ResultType } from '../../../result/types'; import './curation_result_panel.scss'; @@ -27,14 +31,14 @@ interface Props { } export const CurationResultPanel: React.FC = ({ variant, results }) => { - // TODO wire up - const count = 3; + const { isMetaEngine, engine } = useValues(EngineLogic); + const count = results.length; return ( <> - {count} + {count} @@ -70,7 +74,11 @@ export const CurationResultPanel: React.FC = ({ variant, results }) => { {results.length > 0 ? ( results.map((result) => ( - + )) ) : ( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx index 9bfc12dfe7cc2..2dcefa7273c72 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; +import '../../../../../__mocks__/shallow_useeffect.mock'; import { mockUseParams } from '../../../../../__mocks__/react_router'; import '../../../../__mocks__/engine_logic.mock'; @@ -14,12 +16,65 @@ import { shallow } from 'enzyme'; import { AppSearchPageTemplate } from '../../../layout'; +import { Result } from '../../../result'; + +import { CurationResultPanel } from './curation_result_panel'; import { CurationSuggestion } from './curation_suggestion'; describe('CurationSuggestion', () => { + const values = { + suggestion: { + query: 'foo', + updated_at: '2021-07-08T14:35:50Z', + promoted: ['1', '2', '3'], + }, + suggestedPromotedDocuments: [ + { + id: { + raw: '1', + }, + _meta: { + id: '1', + engine: 'some-engine', + }, + }, + { + id: { + raw: '2', + }, + _meta: { + id: '2', + engine: 'some-engine', + }, + }, + { + id: { + raw: '3', + }, + _meta: { + id: '3', + engine: 'some-engine', + }, + }, + ], + isMetaEngine: true, + engine: { + schema: {}, + }, + }; + + const actions = { + loadSuggestion: jest.fn(), + }; + + beforeAll(() => { + setMockValues(values); + setMockActions(actions); + }); + beforeEach(() => { jest.clearAllMocks(); - mockUseParams.mockReturnValue({ query: 'some%20query' }); + mockUseParams.mockReturnValue({ query: 'foo' }); }); it('renders', () => { @@ -28,19 +83,21 @@ describe('CurationSuggestion', () => { expect(wrapper.is(AppSearchPageTemplate)).toBe(true); }); - it('displays the decoded query in the title', () => { - const wrapper = shallow(); - - expect(wrapper.prop('pageHeader').pageTitle).toEqual('some query'); + it('loads data on initialization', () => { + shallow(); + expect(actions.loadSuggestion).toHaveBeenCalled(); }); - // TODO This will need to come from somewhere else when wired up - it('displays an empty query if "" is encoded in as the qery', () => { - mockUseParams.mockReturnValue({ query: '%22%22' }); + it('shows suggested promoted documents', () => { + const wrapper = shallow(); + const suggestedResultsPanel = wrapper.find(CurationResultPanel).at(1); + expect(suggestedResultsPanel.prop('results')).toEqual(values.suggestedPromotedDocuments); + }); + it('displays the query in the title', () => { const wrapper = shallow(); - expect(wrapper.prop('pageHeader').pageTitle).toEqual('""'); + expect(wrapper.prop('pageHeader').pageTitle).toEqual('foo'); }); it('displays has a button to display organic results', () => { @@ -52,4 +109,24 @@ describe('CurationSuggestion', () => { wrapper.find('[data-test-subj="showOrganicResults"]').simulate('click'); expect(wrapper.find('[data-test-subj="organicResults"]').exists()).toBe(false); }); + + it('displays proposed organic results', () => { + const wrapper = shallow(); + wrapper.find('[data-test-subj="showOrganicResults"]').simulate('click'); + expect(wrapper.find('[data-test-subj="proposedOrganicResults"]').find(Result).length).toBe(4); + expect(wrapper.find(Result).at(0).prop('isMetaEngine')).toEqual(true); + expect(wrapper.find(Result).at(0).prop('schemaForTypeHighlights')).toEqual( + values.engine.schema + ); + }); + + it('displays current organic results', () => { + const wrapper = shallow(); + wrapper.find('[data-test-subj="showOrganicResults"]').simulate('click'); + expect(wrapper.find('[data-test-subj="currentOrganicResults"]').find(Result).length).toBe(4); + expect(wrapper.find(Result).at(0).prop('isMetaEngine')).toEqual(true); + expect(wrapper.find(Result).at(0).prop('schemaForTypeHighlights')).toEqual( + values.engine.schema + ); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.tsx index 4fab9db47af90..ade78e4914e84 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.tsx @@ -5,7 +5,9 @@ * 2.0. */ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; + +import { useActions, useValues } from 'kea'; import { EuiButtonEmpty, @@ -19,6 +21,7 @@ import { import { i18n } from '@kbn/i18n'; import { useDecodedParams } from '../../../../utils/encode_path_params'; +import { EngineLogic } from '../../../engine'; import { AppSearchPageTemplate } from '../../../layout'; import { Result } from '../../../result'; import { Result as ResultType } from '../../../result/types'; @@ -27,26 +30,37 @@ import { getCurationsBreadcrumbs } from '../../utils'; import { CurationActionBar } from './curation_action_bar'; import { CurationResultPanel } from './curation_result_panel'; +import { CurationSuggestionLogic } from './curation_suggestion_logic'; import { DATA } from './temp_data'; export const CurationSuggestion: React.FC = () => { const { query } = useDecodedParams(); + const curationSuggestionLogic = CurationSuggestionLogic({ query }); + const { loadSuggestion } = useActions(curationSuggestionLogic); + const { engine, isMetaEngine } = useValues(EngineLogic); + const { suggestion, suggestedPromotedDocuments, dataLoading } = + useValues(curationSuggestionLogic); const [showOrganicResults, setShowOrganicResults] = useState(false); const currentOrganicResults = [...DATA].splice(5, 4); const proposedOrganicResults = [...DATA].splice(2, 4); - const queryTitle = query === '""' ? query : `${query}`; + const suggestionQuery = suggestion?.query || ''; + + useEffect(() => { + loadSuggestion(); + }, []); return ( { -

    Current

    +

    + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.currentTitle', + { defaultMessage: 'Current' } + )} +

    -

    Suggested

    +

    + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.suggestionTitle', + { defaultMessage: 'Suggested' } + )} +

    - +
    @@ -81,7 +105,15 @@ export const CurationSuggestion: React.FC = () => { onClick={() => setShowOrganicResults(!showOrganicResults)} data-test-subj="showOrganicResults" > - {showOrganicResults ? 'Collapse' : 'Expand'} organic search results + {showOrganicResults + ? i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.collapseButtonLabel', + { defaultMessage: 'Collapse organic search results' } + ) + : i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.expandButtonLabel', + { defaultMessage: 'Expand organic search results' } + )} {showOrganicResults && ( <> @@ -90,10 +122,18 @@ export const CurationSuggestion: React.FC = () => { {currentOrganicResults.length > 0 && ( - + {currentOrganicResults.map((result: ResultType) => ( - + ))} @@ -101,10 +141,18 @@ export const CurationSuggestion: React.FC = () => { {proposedOrganicResults.length > 0 && ( - + {proposedOrganicResults.map((result: ResultType) => ( - + ))} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.test.ts new file mode 100644 index 0000000000000..6e616dcd9452c --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.test.ts @@ -0,0 +1,226 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + LogicMounter, + mockFlashMessageHelpers, + mockHttpValues, +} from '../../../../../__mocks__/kea_logic'; + +import '../../../../__mocks__/engine_logic.mock'; + +import { nextTick } from '@kbn/test/jest'; + +import { CurationSuggestionLogic } from './curation_suggestion_logic'; + +const DEFAULT_VALUES = { + dataLoading: true, + suggestion: null, + suggestedPromotedDocuments: [], +}; + +const suggestion = { + query: 'foo', + updated_at: '2021-07-08T14:35:50Z', + promoted: ['1', '2', '3'], +}; + +const suggestedPromotedDocuments = [ + { + id: { + raw: '1', + }, + _meta: { + id: '1', + engine: 'some-engine', + }, + }, + { + id: { + raw: '2', + }, + _meta: { + id: '2', + engine: 'some-engine', + }, + }, + { + id: { + raw: '3', + }, + _meta: { + id: '3', + engine: 'some-engine', + }, + }, +]; + +const MOCK_RESPONSE = { + meta: { + page: { + current: 1, + size: 10, + total_results: 1, + total_pages: 1, + }, + }, + results: [suggestion], +}; + +const MOCK_DOCUMENTS_RESPONSE = { + results: [ + { + id: { + raw: '2', + }, + _meta: { + id: '2', + engine: 'some-engine', + }, + }, + { + id: { + raw: '1', + }, + _meta: { + id: '1', + engine: 'some-engine', + }, + }, + ], +}; + +describe('CurationSuggestionLogic', () => { + const { mount } = new LogicMounter(CurationSuggestionLogic); + const { flashAPIErrors } = mockFlashMessageHelpers; + const mountLogic = (props: object = {}) => { + mount(props, { query: 'foo-query' }); + }; + + const { http } = mockHttpValues; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('has expected default values', () => { + mountLogic(); + expect(CurationSuggestionLogic.values).toEqual(DEFAULT_VALUES); + }); + + describe('actions', () => { + describe('onSuggestionLoaded', () => { + it('should save the loaded suggestion and promoted documents associated with that suggestion and set dataLoading to false', () => { + mountLogic(); + CurationSuggestionLogic.actions.onSuggestionLoaded({ + suggestion, + suggestedPromotedDocuments, + }); + expect(CurationSuggestionLogic.values).toEqual({ + ...DEFAULT_VALUES, + suggestion, + suggestedPromotedDocuments, + dataLoading: false, + }); + }); + }); + }); + + describe('listeners', () => { + describe('loadSuggestion', () => { + it('should set dataLoading state', () => { + mountLogic({ dataLoading: false }); + + CurationSuggestionLogic.actions.loadSuggestion(); + + expect(CurationSuggestionLogic.values).toEqual({ + ...DEFAULT_VALUES, + dataLoading: true, + }); + }); + + it('should make an API call and trigger onSuggestionLoaded', async () => { + http.post.mockReturnValueOnce(Promise.resolve(MOCK_RESPONSE)); + http.post.mockReturnValueOnce(Promise.resolve(MOCK_DOCUMENTS_RESPONSE)); + mountLogic(); + jest.spyOn(CurationSuggestionLogic.actions, 'onSuggestionLoaded'); + + CurationSuggestionLogic.actions.loadSuggestion(); + await nextTick(); + + expect(http.post).toHaveBeenCalledWith( + '/internal/app_search/engines/some-engine/search_relevance_suggestions/foo-query', + { + body: JSON.stringify({ + page: { + current: 1, + size: 1, + }, + filters: { + status: ['pending'], + type: 'curation', + }, + }), + } + ); + + expect(http.post).toHaveBeenCalledWith('/internal/app_search/engines/some-engine/search', { + query: { query: '' }, + body: JSON.stringify({ + page: { + size: 100, + }, + filters: { + // The results of the first API call are used to make the second http call for document details + id: MOCK_RESPONSE.results[0].promoted, + }, + }), + }); + + expect(CurationSuggestionLogic.actions.onSuggestionLoaded).toHaveBeenCalledWith({ + suggestion: { + query: 'foo', + updated_at: '2021-07-08T14:35:50Z', + promoted: ['1', '2', '3'], + }, + // Note that these were re-ordered to match the 'promoted' list above, and since document + // 3 was not found it is not included in this list + suggestedPromotedDocuments: [ + { + id: { + raw: '1', + }, + _meta: { + id: '1', + engine: 'some-engine', + }, + }, + { + id: { + raw: '2', + }, + _meta: { + id: '2', + engine: 'some-engine', + }, + }, + ], + }); + }); + + it('handles errors', async () => { + http.post.mockReturnValueOnce(Promise.reject('error')); + mount(); + + CurationSuggestionLogic.actions.loadSuggestion(); + await nextTick(); + + expect(flashAPIErrors).toHaveBeenCalledWith('error'); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts new file mode 100644 index 0000000000000..d3f27be122060 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kea, MakeLogicType } from 'kea'; + +import { flashAPIErrors } from '../../../../../shared/flash_messages'; +import { HttpLogic } from '../../../../../shared/http'; +import { EngineLogic } from '../../../engine'; +import { Result } from '../../../result/types'; +import { CurationSuggestion } from '../../types'; + +interface CurationSuggestionValues { + dataLoading: boolean; + suggestion: CurationSuggestion | null; + suggestedPromotedDocuments: Result[]; +} + +interface CurationSuggestionActions { + loadSuggestion(): void; + onSuggestionLoaded({ + suggestion, + suggestedPromotedDocuments, + }: { + suggestion: CurationSuggestion; + suggestedPromotedDocuments: Result[]; + }): { + suggestion: CurationSuggestion; + suggestedPromotedDocuments: Result[]; + }; +} + +interface CurationSuggestionProps { + query: CurationSuggestion['query']; +} + +export const CurationSuggestionLogic = kea< + MakeLogicType +>({ + path: ['enterprise_search', 'app_search', 'curations', 'suggestion_logic'], + actions: () => ({ + loadSuggestion: true, + onSuggestionLoaded: ({ suggestion, suggestedPromotedDocuments }) => ({ + suggestion, + suggestedPromotedDocuments, + }), + }), + reducers: () => ({ + dataLoading: [ + true, + { + loadSuggestion: () => true, + onSuggestionLoaded: () => false, + }, + ], + suggestion: [ + null, + { + onSuggestionLoaded: (_, { suggestion }) => suggestion, + }, + ], + suggestedPromotedDocuments: [ + [], + { + onSuggestionLoaded: (_, { suggestedPromotedDocuments }) => suggestedPromotedDocuments, + }, + ], + }), + listeners: ({ actions, props }) => ({ + loadSuggestion: async () => { + const { http } = HttpLogic.values; + const { engineName } = EngineLogic.values; + + try { + const response = await http.post( + `/internal/app_search/engines/${engineName}/search_relevance_suggestions/${props.query}`, + { + body: JSON.stringify({ + page: { + current: 1, + size: 1, + }, + filters: { + status: ['pending'], + type: 'curation', + }, + }), + } + ); + + const suggestion = response.results[0]; + + const searchResponse = await http.post( + `/internal/app_search/engines/${engineName}/search`, + { + query: { query: '' }, + body: JSON.stringify({ + page: { + size: 100, + }, + filters: { + id: suggestion.promoted, + }, + }), + } + ); + + // Filter out docs that were not found and maintain promoted order + const promotedIds: string[] = suggestion.promoted; + const documentDetails = searchResponse.results; + const suggestedPromotedDocuments = promotedIds.reduce((acc: Result[], id: string) => { + const found = documentDetails.find( + (documentDetail: Result) => documentDetail.id.raw === id + ); + if (!found) return acc; + return [...acc, found]; + }, []); + + actions.onSuggestionLoaded({ + suggestion: suggestion as CurationSuggestion, + suggestedPromotedDocuments, + }); + } catch (e) { + flashAPIErrors(e); + } + }, + }), +}); diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts index d6f741526b29b..e6bfaa4a9cca2 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts @@ -86,4 +86,28 @@ describe('search relevance insights routes', () => { }); }); }); + + describe('POST /internal/app_search/engines/{name}/search_relevance_suggestions/{query}', () => { + const mockRouter = new MockRouter({ + method: 'post', + path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/{query}', + }); + + beforeEach(() => { + registerSearchRelevanceSuggestionsRoutes({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request to enterprise search', () => { + mockRouter.callRoute({ + params: { engineName: 'some-engine', query: 'foo' }, + }); + + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/api/as/v0/engines/:engineName/search_relevance_suggestions/:query', + }); + }); + }); }); diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts index 861d8c52b537f..c6fa108a5629e 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts @@ -66,4 +66,29 @@ export function registerSearchRelevanceSuggestionsRoutes({ path: '/api/as/v0/engines/:engineName/search_relevance_suggestions/settings', }) ); + + router.post( + { + path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/{query}', + validate: { + params: schema.object({ + engineName: schema.string(), + query: schema.string(), + }), + body: schema.object({ + page: schema.object({ + current: schema.number(), + size: schema.number(), + }), + filters: schema.object({ + status: schema.arrayOf(schema.string()), + type: schema.string(), + }), + }), + }, + }, + enterpriseSearchRequestHandler.createRequest({ + path: '/api/as/v0/engines/:engineName/search_relevance_suggestions/:query', + }) + ); } From 2fad6e92c6e2786b08fe555c24c48244aee827fe Mon Sep 17 00:00:00 2001 From: Caroline Horn <549577+cchaos@users.noreply.github.com> Date: Mon, 4 Oct 2021 15:25:24 -0400 Subject: [PATCH 67/98] =?UTF-8?q?[Getting=20Started]=20Added=20=E2=80=9CAd?= =?UTF-8?q?d=20data=E2=80=9D=20button=20to=20Global=20Nav=20Drawer=20(#113?= =?UTF-8?q?648)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adding EUI as code-owners to KibanaPageTemplate --- .github/CODEOWNERS | 3 +- .../collapsible_nav.test.tsx.snap | 2 + .../chrome/ui/header/collapsible_nav.tsx | 57 +++++++++++++++++-- src/core/public/chrome/ui/header/nav_link.tsx | 25 +++++++- 4 files changed, 79 insertions(+), 8 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9aa308c0dc58d..149f5cd74d8c0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -448,4 +448,5 @@ /docs/setup/configuring-reporting.asciidoc @elastic/kibana-reporting-services @elastic/kibana-app-services #CC# /x-pack/plugins/reporting/ @elastic/kibana-reporting-services - +# EUI design +/src/plugins/kibana_react/public/page_template/ @elastic/eui-design @elastic/kibana-app-services diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 6e33e39b148c4..6987b779d5d45 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -565,6 +565,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` "data-test-subj": "homeLink", "href": "/", "iconType": "home", + "isActive": false, "label": "Home", "onClick": [Function], }, @@ -587,6 +588,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` data-test-subj="homeLink" href="/" iconType="home" + isActive={false} key="title-0" label="Home" onClick={[Function]} diff --git a/src/core/public/chrome/ui/header/collapsible_nav.tsx b/src/core/public/chrome/ui/header/collapsible_nav.tsx index 1bf5c5e2f65c0..ad590865b9e14 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav.tsx @@ -16,10 +16,11 @@ import { EuiListGroupItem, EuiShowFor, EuiCollapsibleNavProps, + EuiButton, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { groupBy, sortBy } from 'lodash'; -import React, { Fragment, useRef } from 'react'; +import React, { Fragment, useMemo, useRef } from 'react'; import useObservable from 'react-use/lib/useObservable'; import * as Rx from 'rxjs'; import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../..'; @@ -27,8 +28,12 @@ import { AppCategory } from '../../../../types'; import { InternalApplicationStart } from '../../../application/types'; import { HttpStart } from '../../../http'; import { OnIsLockedUpdate } from './'; -import { createEuiListItem, createRecentNavLink, isModifiedOrPrevented } from './nav_link'; - +import { + createEuiListItem, + createRecentNavLink, + isModifiedOrPrevented, + createEuiButtonItem, +} from './nav_link'; function getAllCategories(allCategorizedLinks: Record) { const allCategories = {} as Record; @@ -95,12 +100,28 @@ export function CollapsibleNav({ button, ...observables }: Props) { - const navLinks = useObservable(observables.navLinks$, []).filter((link) => !link.hidden); + const allLinks = useObservable(observables.navLinks$, []); + const allowedLinks = useMemo( + () => + allLinks.filter( + // Filterting out hidden links and the integrations one in favor of a specific Add Data button at the bottom + (link) => !link.hidden && link.id !== 'integrations' + ), + [allLinks] + ); + const integrationsLink = useMemo( + () => + allLinks.find( + // Find just the integrations link + (link) => link.id === 'integrations' + ), + [allLinks] + ); const recentlyAccessed = useObservable(observables.recentlyAccessed$, []); const customNavLink = useObservable(observables.customNavLink$, undefined); const appId = useObservable(observables.appId$, ''); const lockRef = useRef(null); - const groupedNavLinks = groupBy(navLinks, (link) => link?.category?.id); + const groupedNavLinks = groupBy(allowedLinks, (link) => link?.category?.id); const { undefined: unknowns = [], ...allCategorizedLinks } = groupedNavLinks; const categoryDictionary = getAllCategories(allCategorizedLinks); const orderedCategories = getOrderedCategories(allCategorizedLinks, categoryDictionary); @@ -176,6 +197,7 @@ export function CollapsibleNav({ iconType: 'home', href: homeHref, 'data-test-subj': 'homeLink', + isActive: appId === 'home', onClick: (event) => { if (isModifiedOrPrevented(event)) { return; @@ -217,7 +239,7 @@ export function CollapsibleNav({ // Can remove icon from recent links completely const { iconType, onClick, ...hydratedLink } = createRecentNavLink( link, - navLinks, + allowedLinks, basePath, navigateToUrl ); @@ -323,6 +345,29 @@ export function CollapsibleNav({ + {integrationsLink && ( + + {/* Span fakes the nav group into not being the first item and therefore adding a top border */} + + + + {i18n.translate('core.ui.primaryNav.addData', { + defaultMessage: 'Add data', + })} + + + + )} ); } diff --git a/src/core/public/chrome/ui/header/nav_link.tsx b/src/core/public/chrome/ui/header/nav_link.tsx index b0ebf7cc5f8e5..b6d8be8a3c786 100644 --- a/src/core/public/chrome/ui/header/nav_link.tsx +++ b/src/core/public/chrome/ui/header/nav_link.tsx @@ -14,7 +14,7 @@ import { HttpStart } from '../../../http'; import { InternalApplicationStart } from '../../../application/types'; import { relativeToAbsolute } from '../../nav_links/to_nav_link'; -export const isModifiedOrPrevented = (event: React.MouseEvent) => +export const isModifiedOrPrevented = (event: React.MouseEvent) => event.metaKey || event.altKey || event.ctrlKey || event.shiftKey || event.defaultPrevented; interface Props { @@ -71,6 +71,29 @@ export function createEuiListItem({ }; } +export function createEuiButtonItem({ + link, + onClick = () => {}, + navigateToUrl, + dataTestSubj, +}: Omit) { + const { href, disabled, url } = link; + + return { + href, + /* Use href and onClick to support "open in new tab" and SPA navigation in the same link */ + onClick(event: React.MouseEvent) { + if (!isModifiedOrPrevented(event)) { + onClick(); + } + event.preventDefault(); + navigateToUrl(url); + }, + isDisabled: disabled, + 'data-test-subj': dataTestSubj, + }; +} + export interface RecentNavLink { href: string; label: string; From 6f2757dfea1ad3975800a8603843cc6240b6dbd3 Mon Sep 17 00:00:00 2001 From: Sandra G Date: Mon, 4 Oct 2021 15:28:17 -0400 Subject: [PATCH 68/98] [Stack Monitoring] Node Advanced View (#113628) * add template navigation * implement advanced node view * fix I18N titles --- .../monitoring/public/application/index.tsx | 8 ++ .../elasticsearch/node_advanced_page.tsx | 79 +++++++++++++++++++ .../pages/elasticsearch/node_page.tsx | 2 +- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_advanced_page.tsx diff --git a/x-pack/plugins/monitoring/public/application/index.tsx b/x-pack/plugins/monitoring/public/application/index.tsx index a958e6061215d..088891621923c 100644 --- a/x-pack/plugins/monitoring/public/application/index.tsx +++ b/x-pack/plugins/monitoring/public/application/index.tsx @@ -30,6 +30,7 @@ import { ElasticsearchIndicesPage } from './pages/elasticsearch/indices_page'; import { ElasticsearchIndexPage } from './pages/elasticsearch/index_page'; import { ElasticsearchIndexAdvancedPage } from './pages/elasticsearch/index_advanced_page'; import { ElasticsearchNodePage } from './pages/elasticsearch/node_page'; +import { ElasticsearchNodeAdvancedPage } from './pages/elasticsearch/node_advanced_page'; import { MonitoringTimeContainer } from './hooks/use_monitoring_time'; import { BreadcrumbContainer } from './hooks/use_breadcrumbs'; @@ -108,6 +109,13 @@ const MonitoringApp: React.FC<{ fetchAllClusters={false} /> + + = ({ clusters }) => { + const globalState = useContext(GlobalStateContext); + const { zoomInfo, onBrush } = useCharts(); + + const { node }: { node: string } = useParams(); + const { services } = useKibana<{ data: any }>(); + + const clusterUuid = globalState.cluster_uuid; + const ccs = globalState.ccs; + const [data, setData] = useState({} as any); + + const title = i18n.translate('xpack.monitoring.elasticsearch.node.advanced.title', { + defaultMessage: 'Elasticsearch - Nodes - {nodeName} - Advanced', + values: { + nodeName: data?.nodeSummary?.name, + }, + }); + + const pageTitle = i18n.translate('xpack.monitoring.elasticsearch.node.advanced.pageTitle', { + defaultMessage: 'Elasticsearch node: {nodeName}', + values: { + nodeName: data?.nodeSummary?.name, + }, + }); + + const getPageData = useCallback(async () => { + const bounds = services.data?.query.timefilter.timefilter.getBounds(); + const url = `../api/monitoring/v1/clusters/${clusterUuid}/elasticsearch/nodes/${node}`; + + const response = await services.http?.fetch(url, { + method: 'POST', + body: JSON.stringify({ + ccs, + timeRange: { + min: bounds.min.toISOString(), + max: bounds.max.toISOString(), + }, + is_advanced: true, + }), + }); + + setData(response); + }, [ccs, clusterUuid, services.data?.query.timefilter.timefilter, services.http, node]); + + return ( + + + + ); +}; diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx index 9b3a67f612e5c..a8825f377eada 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/node_page.tsx @@ -42,7 +42,7 @@ export const ElasticsearchNodePage: React.FC = ({ clusters }) => const [data, setData] = useState({} as any); const [nodesByIndicesData, setNodesByIndicesData] = useState([]); - const title = i18n.translate('xpack.monitoring.elasticsearch.node.overview.routeTitle', { + const title = i18n.translate('xpack.monitoring.elasticsearch.node.overview.title', { defaultMessage: 'Elasticsearch - Nodes - {nodeName} - Overview', values: { nodeName: data?.nodeSummary?.name, From 432a8492c80dc7031f8a2b58c1029ac6517bde75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Mon, 4 Oct 2021 15:41:03 -0400 Subject: [PATCH 69/98] [APM] Fleet: Update "switch to datastreams" wording for apm migration (#113574) * removing data stream in favor of Elastic agent * fixing i18n * addressing pr changes * capitalization Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../Settings/schema/confirm_switch_modal.tsx | 6 +- .../schema/migration_in_progress_panel.tsx | 2 +- .../app/Settings/schema/schema_overview.tsx | 64 ++++--------------- .../translations/translations/ja-JP.json | 7 -- .../translations/translations/zh-CN.json | 7 -- 5 files changed, 16 insertions(+), 70 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/Settings/schema/confirm_switch_modal.tsx b/x-pack/plugins/apm/public/components/app/Settings/schema/confirm_switch_modal.tsx index 5bb93c251777f..a13f31e8a6566 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/schema/confirm_switch_modal.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/schema/confirm_switch_modal.tsx @@ -46,7 +46,7 @@ export function ConfirmSwitchModal({ confirmButtonText={i18n.translate( 'xpack.apm.settings.schema.confirm.switchButtonText', { - defaultMessage: 'Switch to data streams', + defaultMessage: 'Switch to Elastic Agent', } )} defaultFocusedButton="confirm" @@ -78,7 +78,7 @@ export function ConfirmSwitchModal({ title={i18n.translate( 'xpack.apm.settings.schema.confirm.irreversibleWarning.title', { - defaultMessage: `Switching to data streams is an irreversible action`, + defaultMessage: `Switching to Elastic Agent is an irreversible action`, } )} color="warning" @@ -132,7 +132,7 @@ export function ConfirmSwitchModal({ label={i18n.translate( 'xpack.apm.settings.schema.confirm.checkboxLabel', { - defaultMessage: `I confirm that I wish to switch to data streams`, + defaultMessage: `I confirm that I wish to switch to Elastic Agent`, } )} checked={isConfirmChecked} diff --git a/x-pack/plugins/apm/public/components/app/Settings/schema/migration_in_progress_panel.tsx b/x-pack/plugins/apm/public/components/app/Settings/schema/migration_in_progress_panel.tsx index 854d1dd823d23..ec9ee5633c17d 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/schema/migration_in_progress_panel.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/schema/migration_in_progress_panel.tsx @@ -20,7 +20,7 @@ export function MigrationInProgressPanel() { icon={} title={i18n.translate( 'xpack.apm.settings.schema.migrationInProgressPanelTitle', - { defaultMessage: 'Switching to data streams...' } + { defaultMessage: 'Switching to Elastic Agent...' } )} description={i18n.translate( 'xpack.apm.settings.schema.migrationInProgressPanelDescription', diff --git a/x-pack/plugins/apm/public/components/app/Settings/schema/schema_overview.tsx b/x-pack/plugins/apm/public/components/app/Settings/schema/schema_overview.tsx index ad6f315185cf3..00e03484dc736 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/schema/schema_overview.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/schema/schema_overview.tsx @@ -7,7 +7,6 @@ import { EuiButton, - EuiCallOut, EuiCard, EuiFlexGroup, EuiFlexItem, @@ -86,7 +85,7 @@ export function SchemaOverview({ /> } title={i18n.translate('xpack.apm.settings.schema.success.title', { - defaultMessage: 'Data streams successfully setup!', + defaultMessage: 'Elastic Agent successfully setup!', })} description={i18n.translate( 'xpack.apm.settings.schema.success.description', @@ -139,17 +138,17 @@ export function SchemaOverview({ } + icon={} title={i18n.translate( 'xpack.apm.settings.schema.migrate.classicIndices.title', - { defaultMessage: 'Classic APM indices' } + { defaultMessage: 'APM Server binary' } )} display="subdued" description={i18n.translate( 'xpack.apm.settings.schema.migrate.classicIndices.description', { defaultMessage: - 'You are currently using classic APM indices for your data. This data schema is going away and is being replaced by data streams in Elastic Stack version 8.0.', + 'You are currently using APM Server binary. This legacy option is deprecated since version 7.16 and is being replaced by a manages APM Server in Elastic Agent from version 8.0.', } )} footer={ @@ -168,21 +167,6 @@ export function SchemaOverview({ rocket launch @@ -190,13 +174,13 @@ export function SchemaOverview({ } title={i18n.translate( 'xpack.apm.settings.schema.migrate.dataStreams.title', - { defaultMessage: 'Data streams' } + { defaultMessage: 'Elastic Agent' } )} description={i18n.translate( 'xpack.apm.settings.schema.migrate.dataStreams.description', { defaultMessage: - 'Going forward, any newly ingested data gets stored in data streams. Previously ingested data remains in classic APM indices. The APM and UX apps will continue to support both indices.', + 'Your APM Server will need to be managed by Elastic Agent from version 8.0 and onwards. You can run Elastic Agent on Cloud, ECE or self-managed and install the Elastic APM integration in order to continue ingesting APM data.', } )} footer={ @@ -216,7 +200,7 @@ export function SchemaOverview({ > {i18n.translate( 'xpack.apm.settings.schema.migrate.dataStreams.buttonText', - { defaultMessage: 'Switch to data streams' } + { defaultMessage: 'Switch to Elastic Agent' } )} @@ -238,7 +222,7 @@ export function SchemaOverviewHeading() { @@ -256,15 +240,15 @@ export function SchemaOverviewHeading() { )} ), - dataStreamsDocLink: ( + elasticAgentDocLink: ( {i18n.translate( - 'xpack.apm.settings.schema.descriptionText.dataStreamsDocLinkText', - { defaultMessage: 'data streams' } + 'xpack.apm.settings.schema.descriptionText.elasticAgentDocLinkText', + { defaultMessage: 'Elastic Agent' } )} ), @@ -272,30 +256,6 @@ export function SchemaOverviewHeading() { /> - - - - - {i18n.translate( - 'xpack.apm.settings.schema.descriptionText.betaCalloutMessage', - { - defaultMessage: - 'This functionality is in beta and is subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.', - } - )} - - - - - ); } @@ -338,7 +298,7 @@ function getDisabledReason({ return ( diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b1bcc0b67eecb..dcbb8ce26ee4a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6762,10 +6762,6 @@ "xpack.apm.settings.schema.confirm.title": "選択内容を確認してください", "xpack.apm.settings.schema.confirm.unsupportedConfigs.descriptionText": "互換性のあるカスタムapm-server.ymlユーザー設定がFleetサーバー設定に移動されます。削除する前に互換性のない設定について通知されます。", "xpack.apm.settings.schema.confirm.unsupportedConfigs.title": "次のapm-server.ymlユーザー設定は互換性がないため削除されます", - "xpack.apm.settings.schema.descriptionText": "クラシックAPMインデックスから切り替え、新しいデータストリーム機能をすぐに活用するためのシンプルでシームレスなプロセスを構築しました。このアクションは{irreversibleEmphasis}。また、Fleetへのアクセス権が付与された{superuserEmphasis}のみが実行できます。{dataStreamsDocLink}の詳細を参照してください。", - "xpack.apm.settings.schema.descriptionText.betaCalloutMessage": "この機能はベータ段階で、変更される可能性があります。デザインとコードはオフィシャルGA機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", - "xpack.apm.settings.schema.descriptionText.betaCalloutTitle": "APMのデータストリームはベータです", - "xpack.apm.settings.schema.descriptionText.dataStreamsDocLinkText": "データストリーム", "xpack.apm.settings.schema.descriptionText.irreversibleEmphasisText": "元に戻せません", "xpack.apm.settings.schema.descriptionText.superuserEmphasisText": "スーパーユーザー", "xpack.apm.settings.schema.disabledReason": "データストリームへの切り替えを使用できません: {reasons}", @@ -6775,9 +6771,6 @@ "xpack.apm.settings.schema.migrate.classicIndices.currentSetup": "現在の設定", "xpack.apm.settings.schema.migrate.classicIndices.description": "現在、データのクラシックAPMインデックスを使用しています。このデータスキーマは廃止予定であり、Elastic Stackバージョン8.0でデータストリームに置換されます。", "xpack.apm.settings.schema.migrate.classicIndices.title": "クラシックAPMインデックス", - "xpack.apm.settings.schema.migrate.dataStreams.betaBadge.description": "データストリームへの切り替えはGAではありません。不具合が発生したら報告してください。", - "xpack.apm.settings.schema.migrate.dataStreams.betaBadge.label": "ベータ", - "xpack.apm.settings.schema.migrate.dataStreams.betaBadge.title": "データストリーム", "xpack.apm.settings.schema.migrate.dataStreams.buttonText": "データストリームに切り替える", "xpack.apm.settings.schema.migrate.dataStreams.description": "今後、新しく取り込まれたデータはすべてデータストリームに格納されます。以前に取り込まれたデータはクラシックAPMインデックスに残ります。APMおよびUXアプリは引き続き両方のインデックスをサポートします。", "xpack.apm.settings.schema.migrate.dataStreams.title": "データストリーム", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d8bd9774551d8..87c96d1efe48d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6815,10 +6815,6 @@ "xpack.apm.settings.schema.confirm.title": "请确认您的选择", "xpack.apm.settings.schema.confirm.unsupportedConfigs.descriptionText": "系统会替您将兼容的定制 apm-server.yml 用户设置移到 Fleet 服务器设置。我们将会让您了解哪些设置不兼容后,才会移除它们。", "xpack.apm.settings.schema.confirm.unsupportedConfigs.title": "以下 apm-server.yml 用户设置不兼容,将会被移除", - "xpack.apm.settings.schema.descriptionText": "从经典 APM 索引切换是简单且无缝的过程,让您可以立即利用新的数据流功能。注意,此操作{irreversibleEmphasis},且只能由对 Fleet 具有访问权限的{superuserEmphasis}执行。详细了解{dataStreamsDocLink}。", - "xpack.apm.settings.schema.descriptionText.betaCalloutMessage": "此功能为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", - "xpack.apm.settings.schema.descriptionText.betaCalloutTitle": "数据流在 APM 中为公测版", - "xpack.apm.settings.schema.descriptionText.dataStreamsDocLinkText": "数据流", "xpack.apm.settings.schema.descriptionText.irreversibleEmphasisText": "不可逆", "xpack.apm.settings.schema.descriptionText.superuserEmphasisText": "超级用户", "xpack.apm.settings.schema.disabledReason": "无法切换到数据流:{reasons}", @@ -6828,9 +6824,6 @@ "xpack.apm.settings.schema.migrate.classicIndices.currentSetup": "当前设置", "xpack.apm.settings.schema.migrate.classicIndices.description": "您当前正将经典 APM 索引用于您的数据。此数据架构将退役,将在 Elastic Stack 版本 8.0 中由数据流替代。", "xpack.apm.settings.schema.migrate.classicIndices.title": "经典 APM 索引", - "xpack.apm.settings.schema.migrate.dataStreams.betaBadge.description": "切换到数据流尚未正式发布。请通过报告错误来帮助我们。", - "xpack.apm.settings.schema.migrate.dataStreams.betaBadge.label": "公测版", - "xpack.apm.settings.schema.migrate.dataStreams.betaBadge.title": "数据流", "xpack.apm.settings.schema.migrate.dataStreams.buttonText": "切换到数据流", "xpack.apm.settings.schema.migrate.dataStreams.description": "将来,任何新采集的数据都将存储在数据流中。之前采集的数据仍在经典 APM 索引中。APM 和 UX 应用将继续支持这两种索引。", "xpack.apm.settings.schema.migrate.dataStreams.title": "数据流", From 240716d2ee824bf3df584300c475d32800829468 Mon Sep 17 00:00:00 2001 From: Tre Date: Mon, 4 Oct 2021 16:02:51 -0400 Subject: [PATCH 70/98] [QA][SO INFO SVC] Drop in-test jq filtering (#113655) --- package.json | 1 - .../services/saved_object_info/index.ts | 2 +- .../saved_object_info/saved_object_info.ts | 17 +- .../saved_objects_info_svc.md | 35 + .../{README.md => use_with_jq.md} | 68 +- .../services/saved_object_info/utils.ts | 2 +- yarn.lock | 618 +----------------- 7 files changed, 55 insertions(+), 688 deletions(-) create mode 100644 test/common/services/saved_object_info/saved_objects_info_svc.md rename test/common/services/saved_object_info/{README.md => use_with_jq.md} (53%) diff --git a/package.json b/package.json index f436a13a057e9..f04a8423196fd 100644 --- a/package.json +++ b/package.json @@ -767,7 +767,6 @@ "multimatch": "^4.0.0", "mutation-observer": "^1.0.3", "ncp": "^2.0.0", - "node-jq": "2.0.0", "node-sass": "^6.0.1", "null-loader": "^3.0.0", "nyc": "^15.0.1", diff --git a/test/common/services/saved_object_info/index.ts b/test/common/services/saved_object_info/index.ts index 799c9964fde7f..41367694373f3 100644 --- a/test/common/services/saved_object_info/index.ts +++ b/test/common/services/saved_object_info/index.ts @@ -33,7 +33,7 @@ Show information pertaining to the saved objects in the .kibana index Examples: -See 'README.md' +See 'saved_objects_info_svc.md' `, flags: expectedFlags(), diff --git a/test/common/services/saved_object_info/saved_object_info.ts b/test/common/services/saved_object_info/saved_object_info.ts index a75dfd8f3b5aa..61472ea98d879 100644 --- a/test/common/services/saved_object_info/saved_object_info.ts +++ b/test/common/services/saved_object_info/saved_object_info.ts @@ -13,7 +13,6 @@ import { flow, pipe } from 'fp-ts/function'; import * as TE from 'fp-ts/lib/TaskEither'; import * as T from 'fp-ts/lib/Task'; import { ToolingLog } from '@kbn/dev-utils'; -import { run as jq } from 'node-jq'; import { FtrService } from '../../ftr_provider_context'; import { print } from './utils'; @@ -61,22 +60,8 @@ export const types = export class SavedObjectInfoService extends FtrService { private readonly config = this.ctx.getService('config'); - private readonly typesF = async () => - await types(url.format(this.config.get('servers.elasticsearch')))(); - public async logSoTypes(log: ToolingLog, msg: string | null = null) { // @ts-ignore - pipe(await this.typesF(), print(log)(msg)); - } - - /** - * See test/common/services/saved_object_info/README.md for "jq filtering" ideas. - */ - public async filterSoTypes(log: ToolingLog, jqFilter: string, title: string | null = null) { - pipe(await this.typesF(), filterAndLog); - - async function filterAndLog(payload: any) { - log.info(`${title ? title + '\n' : ''}${await jq(jqFilter, payload, { input: 'json' })}`); - } + pipe(await types(url.format(this.config.get('servers.elasticsearch'))), print(log)(msg)); } } diff --git a/test/common/services/saved_object_info/saved_objects_info_svc.md b/test/common/services/saved_object_info/saved_objects_info_svc.md new file mode 100644 index 0000000000000..2d623129e2906 --- /dev/null +++ b/test/common/services/saved_object_info/saved_objects_info_svc.md @@ -0,0 +1,35 @@ +# Saved Objects Info Svc w/ CLI + +## Used via the cli + +Run the cli +> the **--esUrl** arg is required; tells the svc which elastic search endpoint to use + +```shell + λ node scripts/saved_objs_info.js --esUrl http://elastic:changeme@localhost:9220 --soTypes +``` + +Result + +```shell + ### types: + + [ + { + doc_count: 5, + key: 'canvas-workpad-template' + }, + { + doc_count: 1, + key: 'apm-telemetry' + }, + { + doc_count: 1, + key: 'config' + }, + { + doc_count: 1, + key: 'space' + } + ] +``` diff --git a/test/common/services/saved_object_info/README.md b/test/common/services/saved_object_info/use_with_jq.md similarity index 53% rename from test/common/services/saved_object_info/README.md rename to test/common/services/saved_object_info/use_with_jq.md index c5e36f2596ddc..5f081e48e2639 100644 --- a/test/common/services/saved_object_info/README.md +++ b/test/common/services/saved_object_info/use_with_jq.md @@ -1,70 +1,6 @@ -# Tips for using the SO INFO SVC +# Tips for using the SO INFO SVC CLI with JQ -## From an FTR test -``` - ... - const soInfo = getService('savedObjectInfo'); - const log = getService('log'); - - describe('some test suite', function () { - ... - - after(async () => { - // "Normal" logging, without JQ - await soInfo.logSoTypes(log); - // Without a title, using JQ - await soInfo.filterSoTypes(log, '.[] | .key'); - // With a title, using JQ - await soInfo.filterSoTypes( - log, - 'reduce .[].doc_count as $item (0; . + $item)', - 'TOTAL count of ALL Saved Object types' - ); - // With a title, using JQ - await soInfo.filterSoTypes( - log, - '.[] | select(.key =="canvas-workpad-template") | .doc_count', - 'TOTAL count of canvas-workpad-template' - ); - }); -``` - -## From the CLI - -Run the cli -> the **--esUrl** arg is required; tells the svc which elastic search endpoint to use - -```shell - λ node scripts/saved_objs_info.js --esUrl http://elastic:changeme@localhost:9220 --soTypes -``` - -Result - -```shell - ### types: - - [ - { - doc_count: 5, - key: 'canvas-workpad-template' - }, - { - doc_count: 1, - key: 'apm-telemetry' - }, - { - doc_count: 1, - key: 'config' - }, - { - doc_count: 1, - key: 'space' - } - ] -``` - - -### Myriad ways to use JQ to discern discrete info from the svc +## Myriad ways to use jq to discern discrete info from the svc Below, I will leave out the so types call, which is: `node scripts/saved_objs_info.js --esUrl http://elastic:changeme@localhost:9220 --soTypes --json` diff --git a/test/common/services/saved_object_info/utils.ts b/test/common/services/saved_object_info/utils.ts index 64b39e5ebeede..f007710f2b14b 100644 --- a/test/common/services/saved_object_info/utils.ts +++ b/test/common/services/saved_object_info/utils.ts @@ -43,7 +43,7 @@ export const expectedFlags = () => ({ string: ['esUrl'], boolean: ['soTypes', 'json'], help: ` ---esUrl Required, tells the app which url to point to +--esUrl Required, tells the svc which url to point to --soTypes Not Required, tells the svc to show the types within the .kibana index --json Not Required, tells the svc to show the types, with only json output. Useful for piping into jq `, diff --git a/yarn.lock b/yarn.lock index 83c0691646817..416d9c6b8ba5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4722,11 +4722,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== -"@sindresorhus/is@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" - integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== - "@sindresorhus/is@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4" @@ -8097,13 +8092,6 @@ arch@^2.2.0: resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== -archive-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" - integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= - dependencies: - file-type "^4.2.0" - archiver-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2" @@ -9302,17 +9290,6 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bin-build@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861" - integrity sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA== - dependencies: - decompress "^4.0.0" - download "^6.2.2" - execa "^0.7.0" - p-map-series "^1.0.0" - tempfile "^2.0.0" - binary-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" @@ -9323,14 +9300,6 @@ binary-search@^1.3.3: resolved "https://registry.yarnpkg.com/binary-search/-/binary-search-1.3.6.tgz#e32426016a0c5092f0f3598836a1c7da3560565c" integrity sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA== -bl@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - bl@^4.0.1, bl@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" @@ -9793,19 +9762,6 @@ btoa-lite@^1.0.0: resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -9826,11 +9782,6 @@ buffer-equal@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= - buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -9968,19 +9919,6 @@ cacheable-lookup@^5.0.3: resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz#049fdc59dffdd4fc285e8f4f82936591bd59fec3" integrity sha512-W+JBqF9SWe18A72XFzN/V/CULFzPm7sBXzzR6ekkE+3tLG72wFZrBiBZhrZuDoYexop4PHJVdFAKb/Nj9+tm9w== -cacheable-request@^2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" - integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0= - dependencies: - clone-response "1.0.2" - get-stream "3.0.0" - http-cache-semantics "3.8.1" - keyv "3.0.0" - lowercase-keys "1.0.0" - normalize-url "2.0.1" - responselike "1.0.2" - cacheable-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" @@ -10179,16 +10117,6 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -caw@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" - integrity sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA== - dependencies: - get-proxy "^2.0.0" - isurl "^1.0.0-alpha5" - tunnel-agent "^0.6.0" - url-to-options "^1.0.1" - ccount@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17" @@ -10642,7 +10570,7 @@ clone-regexp@^2.1.0: dependencies: is-regexp "^2.0.0" -clone-response@1.0.2, clone-response@^1.0.2: +clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= @@ -10927,13 +10855,6 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= - dependencies: - graceful-readlink ">= 1.0.0" - common-tags@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -11044,7 +10965,7 @@ concaveman@*: robust-predicates "^2.0.4" tinyqueue "^2.0.3" -config-chain@^1.1.11, config-chain@^1.1.12: +config-chain@^1.1.12: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== @@ -11125,7 +11046,7 @@ container-info@^1.0.1: resolved "https://registry.yarnpkg.com/container-info/-/container-info-1.0.1.tgz#6b383cb5e197c8d921e88983388facb04124b56b" integrity sha512-wk/+uJvPHOFG+JSwQS+fw6H6yw3Oyc8Kw9L4O2MN817uA90OqJ59nlZbbLPqDudsjJ7Tetee3pwExdKpd2ahjQ== -content-disposition@0.5.3, content-disposition@^0.5.2: +content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== @@ -11456,15 +11377,6 @@ cross-spawn@7.0.3, cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -12423,7 +12335,7 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -decompress-response@^3.2.0, decompress-response@^3.3.0: +decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= @@ -12444,59 +12356,6 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.0.0, decompress@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" - integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -13173,40 +13032,6 @@ dotignore@^0.1.2: dependencies: minimatch "^3.0.4" -download@^6.2.2: - version "6.2.5" - resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" - integrity sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA== - dependencies: - caw "^2.0.0" - content-disposition "^0.5.2" - decompress "^4.0.0" - ext-name "^5.0.0" - file-type "5.2.0" - filenamify "^2.0.0" - get-stream "^3.0.0" - got "^7.0.0" - make-dir "^1.0.0" - p-event "^1.0.0" - pify "^3.0.0" - -download@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/download/-/download-8.0.0.tgz#afc0b309730811731aae9f5371c9f46be73e51b1" - integrity sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA== - dependencies: - archive-type "^4.0.0" - content-disposition "^0.5.2" - decompress "^4.2.1" - ext-name "^5.0.0" - file-type "^11.1.0" - filenamify "^3.0.0" - get-stream "^4.1.0" - got "^8.3.1" - make-dir "^2.1.0" - p-event "^2.1.0" - pify "^4.0.1" - downshift@^3.2.10: version "3.4.8" resolved "https://registry.yarnpkg.com/downshift/-/downshift-3.4.8.tgz#06b7ad9e9c423a58e8a9049b2a00a5d19c7ef954" @@ -14347,19 +14172,6 @@ execa@4.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -14529,21 +14341,6 @@ express@^4.16.3, express@^4.17.0, express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" -ext-list@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" - integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA== - dependencies: - mime-db "^1.28.0" - -ext-name@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" - integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== - dependencies: - ext-list "^2.0.0" - sort-keys-length "^1.0.0" - extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -14889,36 +14686,11 @@ file-system-cache@^1.0.5: fs-extra "^0.30.0" ramda "^0.21.0" -file-type@5.2.0, file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= - file-type@^10.9.0: version "10.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.9.0.tgz#f6c12c7cb9e6b8aeefd6917555fd4f9eadf31891" integrity sha512-9C5qtGR/fNibHC5gzuMmmgnjH3QDDLKMa8lYe9CiZVmAnI4aUaoMh40QyUPzzs0RYo837SOBKh7TYwle4G8E4w== -file-type@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-11.1.0.tgz#93780f3fed98b599755d846b99a1617a2ad063b8" - integrity sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g== - -file-type@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= - -file-type@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" - integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== - file-type@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18" @@ -14931,29 +14703,6 @@ filelist@^1.0.1: dependencies: minimatch "^3.0.4" -filename-reserved-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" - integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= - -filenamify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.0.0.tgz#bd162262c0b6e94bfbcdcf19a3bbb3764f785695" - integrity sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU= - dependencies: - filename-reserved-regex "^2.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - -filenamify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-3.0.0.tgz#9603eb688179f8c5d40d828626dcbb92c3a4672c" - integrity sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g== - dependencies: - filename-reserved-regex "^2.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - filesize@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" @@ -15323,7 +15072,7 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -from2@^2.1.0, from2@^2.1.1: +from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= @@ -15591,13 +15340,6 @@ get-port@^5.0.0: resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== -get-proxy@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" - integrity sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw== - dependencies: - npm-conf "^1.1.0" - get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -15613,19 +15355,6 @@ get-stdin@^8.0.0: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== -get-stream@3.0.0, get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -16029,49 +15758,6 @@ got@^3.2.0: read-all-stream "^3.0.0" timed-out "^2.0.0" -got@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -got@^8.3.1: - version "8.3.2" - resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" - integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== - dependencies: - "@sindresorhus/is" "^0.7.0" - cacheable-request "^2.1.1" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - into-stream "^3.1.0" - is-retry-allowed "^1.1.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - mimic-response "^1.0.0" - p-cancelable "^0.4.0" - p-timeout "^2.0.1" - pify "^3.0.0" - safe-buffer "^5.1.1" - timed-out "^4.0.1" - url-parse-lax "^3.0.0" - url-to-options "^1.0.1" - got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -16094,16 +15780,11 @@ graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, g resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -graceful-fs@^4.1.10, graceful-fs@^4.2.3, graceful-fs@^4.2.6: +graceful-fs@^4.2.3, graceful-fs@^4.2.6: version "4.2.6" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - graphlib@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" @@ -16342,23 +16023,11 @@ has-glob@^1.0.0: dependencies: is-glob "^3.0.0" -has-symbol-support-x@^1.4.1: - version "1.4.2" - 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, has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" @@ -16817,11 +16486,6 @@ htmlparser2@~3.3.0: domutils "1.1" readable-stream "1.0" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" @@ -17305,14 +16969,6 @@ intl@^1.2.5: resolved "https://registry.yarnpkg.com/intl/-/intl-1.2.5.tgz#82244a2190c4e419f8371f5aa34daa3420e2abde" integrity sha1-giRKIZDE5Bn4Nx9ao02qNCDiq94= -into-stream@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" - integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY= - dependencies: - from2 "^2.1.1" - p-is-promise "^1.1.0" - invariant@2.2.4, invariant@^2.1.0, invariant@^2.1.1, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -17669,13 +17325,6 @@ is-interactive@^1.0.0: resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== -is-invalid-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-invalid-path/-/is-invalid-path-0.1.0.tgz#307a855b3cf1a938b44ea70d2c61106053714f34" - integrity sha1-MHqFWzzxqTi0TqcNLGEQYFNxTzQ= - dependencies: - is-glob "^2.0.0" - is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" @@ -17694,11 +17343,6 @@ is-native@^1.0.1: is-nil "^1.0.0" to-source-code "^1.0.0" -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= - is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" @@ -17873,11 +17517,6 @@ is-resolvable@^1.0.0: resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== -is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - is-root@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" @@ -17954,13 +17593,6 @@ is-valid-glob@^1.0.0: resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= -is-valid-path@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-valid-path/-/is-valid-path-0.1.1.tgz#110f9ff74c37f663e1ec7915eb451f2db93ac9df" - integrity sha1-EQ+f90w39mPh7HkV60UfLbk6yd8= - dependencies: - is-invalid-path "^0.1.0" - is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -18166,14 +17798,6 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" - iterate-iterator@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.1.tgz#1693a768c1ddd79c969051459453f082fe82e9f6" @@ -19270,7 +18894,7 @@ kea@^2.4.2: resolved "https://registry.yarnpkg.com/kea/-/kea-2.4.2.tgz#53af42702f2c8962422e456e5dd943391bad26e9" integrity sha512-cdGds/gsJsbo/KbVAMk5/tTr229eDibVT1wmPPxPO/10zYb8GFoP3udBIQb+Hop5qGEu2wIHVdXwJvXqSS8JAg== -keyv@3.0.0, keyv@^3.0.0: +keyv@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" integrity sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA== @@ -20041,11 +19665,6 @@ lower-case@^2.0.1: dependencies: tslib "^1.10.0" -lowercase-keys@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" - integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= - lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -20064,7 +19683,7 @@ lowlight@^1.14.0: fault "^1.0.0" highlight.js "~10.4.0" -lru-cache@^4.0.0, lru-cache@^4.0.1, lru-cache@^4.1.5: +lru-cache@^4.0.0, lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -20110,13 +19729,6 @@ magic-string@0.25.1: dependencies: sourcemap-codec "^1.4.1" -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -20637,11 +20249,6 @@ mime-db@1.44.0, mime-db@1.x.x, "mime-db@>= 1.40.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -mime-db@^1.28.0: - version "1.49.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== - mime-types@^2.0.1, mime-types@^2.1.12, mime-types@^2.1.26, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" @@ -21483,19 +21090,6 @@ node-jose@1.1.0: node-forge "^0.7.6" uuid "^3.3.2" -node-jq@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-jq/-/node-jq-2.0.0.tgz#f0777ee2be6f6bfcf0ef58cc44689c422def6d97" - integrity sha512-gp8Xkr5RlZrXVK+VuUaF0JKtsGrElHb1hOjugdJFiCMHUup1OqsSBXZyeuwPkpty3P9taFHJmw4uzjQFIMFv4g== - dependencies: - bin-build "^3.0.0" - download "^8.0.0" - is-valid-path "^0.1.1" - joi "^17.4.0" - strip-eof "^2.0.0" - strip-final-newline "^2.0.0" - tempfile "^3.0.0" - node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" @@ -21677,15 +21271,6 @@ normalize-selector@^0.2.0: resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= -normalize-url@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" - integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== - dependencies: - prepend-http "^2.0.0" - query-string "^5.0.1" - sort-keys "^2.0.0" - normalize-url@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" @@ -21703,14 +21288,6 @@ now-and-later@^2.0.0: dependencies: once "^1.3.2" -npm-conf@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" - integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== - dependencies: - config-chain "^1.1.11" - pify "^3.0.0" - npm-normalize-package-bin@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" @@ -22226,16 +21803,6 @@ p-all@^2.1.0: dependencies: p-map "^2.0.0" -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== - -p-cancelable@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" - integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== - p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -22251,20 +21818,6 @@ p-each-series@^2.1.0: resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== -p-event@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" - integrity sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU= - dependencies: - p-timeout "^1.1.1" - -p-event@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" - integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== - dependencies: - p-timeout "^2.0.1" - p-event@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.1.0.tgz#e92bb866d7e8e5b732293b1c8269d38e9982bf8e" @@ -22284,11 +21837,6 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-is-promise@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= - p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -22338,13 +21886,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-map-series@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" - integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco= - dependencies: - p-reduce "^1.0.0" - p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -22364,11 +21905,6 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-reduce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" - integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= - p-retry@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" @@ -22384,13 +21920,6 @@ p-retry@^4.2.0: "@types/retry" "^0.12.0" retry "^0.12.0" -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= - dependencies: - p-finally "^1.0.0" - p-timeout@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" @@ -22876,7 +22405,7 @@ picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== -pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: +pify@^2.0.0, pify@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -23545,7 +23074,7 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prepend-http@^1.0.0, prepend-http@^1.0.1: +prepend-http@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= @@ -23988,15 +23517,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - query-string@^6.13.2: version "6.13.2" resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.2.tgz#3585aa9412c957cbd358fd5eaca7466f05586dda" @@ -25009,7 +24529,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -"readable-stream@1 || 2", "readable-stream@2 || 3", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.3, readable-stream@~2.3.6: +"readable-stream@1 || 2", "readable-stream@2 || 3", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.3, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -25807,7 +25327,7 @@ resolve@~1.10.1: dependencies: path-parse "^1.0.6" -responselike@1.0.2, responselike@^1.0.2: +responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= @@ -26214,13 +25734,6 @@ seedrandom@^3.0.5: resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7" integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg== -seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= - dependencies: - commander "~2.8.1" - select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -26780,20 +26293,6 @@ sonic-boom@^2.1.0: dependencies: atomic-sleep "^1.0.0" -sort-keys-length@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" - integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= - dependencies: - sort-keys "^1.0.0" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" - sort-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" @@ -27342,11 +26841,6 @@ stream-to-async-iterator@^0.2.0: resolved "https://registry.yarnpkg.com/stream-to-async-iterator/-/stream-to-async-iterator-0.2.0.tgz#bef5c885e9524f98b2fa5effecc357bd58483780" integrity sha1-vvXIhelST5iy+l7/7MNXvVhIN4A= -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -27566,23 +27060,11 @@ strip-bom@^4.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== - dependencies: - is-natural-number "^4.0.1" - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= -strip-eof@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-2.0.0.tgz#2e3f3c5145d02de826eafb23e65b2faf675448b4" - integrity sha512-zLsJC+5P5hGu4Zmoq6I4uo6bTf1Nx6Z/vnZedxwnrcfkc38Vz6UiuqGOtS9bewFaoTCDErpqkV7v02htp9KEow== - strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -27605,13 +27087,6 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -strip-outer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.0.tgz#aac0ba60d2e90c5d4f275fd8869fd9a2d310ffb8" - integrity sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g= - dependencies: - escape-string-regexp "^1.0.2" - strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -28049,19 +27524,6 @@ tar-fs@^2.1.0: pump "^3.0.0" tar-stream "^2.0.0" -tar-stream@^1.5.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - tar-stream@^2.0.0: version "2.1.3" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41" @@ -28161,27 +27623,6 @@ temp-dir@^1.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= -temp-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" - integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== - -tempfile@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" - integrity sha1-awRGhWqbERTRhW/8vlCczLCXcmU= - dependencies: - temp-dir "^1.0.0" - uuid "^3.0.1" - -tempfile@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-3.0.0.tgz#5376a3492de7c54150d0cc0612c3f00e2cdaf76c" - integrity sha512-uNFCg478XovRi85iD42egu+eSFUmmka750Jy7L5tfHI5hQKKtbPnxaSaXAbBqCDYrw3wx4tXjKwci4/QmsZJxw== - dependencies: - temp-dir "^2.0.0" - uuid "^3.3.2" - tempy@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.3.0.tgz#6f6c5b295695a16130996ad5ab01a8bd726e8bf8" @@ -28387,11 +27828,6 @@ timed-out@^2.0.0: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" integrity sha1-84sK6B03R9YoAB9B2vxlKs5nHAo= -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - timers-browserify@^1.0.1: version "1.4.2" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" @@ -28504,11 +27940,6 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - to-camel-case@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-camel-case/-/to-camel-case-1.0.0.tgz#1a56054b2f9d696298ce66a60897322b6f423e46" @@ -28694,13 +28125,6 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== -trim-repeated@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" - integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= - dependencies: - escape-string-regexp "^1.0.2" - trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -29052,7 +28476,7 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" -unbzip2-stream@^1.0.9, unbzip2-stream@^1.3.3: +unbzip2-stream@^1.3.3: version "1.4.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== @@ -29542,13 +28966,6 @@ url-loader@^4.0.0: mime-types "^2.1.26" schema-utils "^2.6.5" -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -29569,11 +28986,6 @@ url-template@^2.0.8: resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" integrity sha1-/FZaPMy/93MMd19WQflVV5FDnyE= -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= - url@^0.11.0, url@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" @@ -29726,7 +29138,7 @@ uuid@^2.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" integrity sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho= -uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0: +uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -31198,7 +30610,7 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" -yauzl@^2.10.0, yauzl@^2.4.2: +yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= From d038f1e2146f6f767798e4579df8d317fe8640a3 Mon Sep 17 00:00:00 2001 From: Lee Drengenberg Date: Mon, 4 Oct 2021 15:07:04 -0500 Subject: [PATCH 71/98] don't wait for nav:not(.ng-hide) on status page (#113674) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- test/functional/page_objects/common_page.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts index 8fe2e4139e6ca..64fb184f40e48 100644 --- a/test/functional/page_objects/common_page.ts +++ b/test/functional/page_objects/common_page.ts @@ -67,10 +67,14 @@ export class CommonPageObject extends FtrService { await this.loginPage.login('test_user', 'changeme'); } - await this.find.byCssSelector( - '[data-test-subj="kibanaChrome"] nav:not(.ng-hide)', - 6 * this.defaultFindTimeout - ); + if (appUrl.includes('/status')) { + await this.testSubjects.find('statusPageRoot'); + } else { + await this.find.byCssSelector( + '[data-test-subj="kibanaChrome"] nav:not(.ng-hide)', + 6 * this.defaultFindTimeout + ); + } await this.browser.get(appUrl, insertTimestamp); currentUrl = await this.browser.getCurrentUrl(); this.log.debug(`Finished login process currentUrl = ${currentUrl}`); From 3efad94646299b5bcb71c4f2ddfb5edb8b804e2b Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 4 Oct 2021 16:34:05 -0400 Subject: [PATCH 72/98] [Fleet] Fix integration category redirect after loading categories (#113812) --- .../integrations/sections/epm/screens/home/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/index.tsx index 27e2d11769ef8..edb79b1f2c17b 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/index.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/index.tsx @@ -343,7 +343,7 @@ const AvailablePackages: React.FC = memo(() => { isLoadingCategories, ]); - if (!categoryExists(selectedCategory, categories)) { + if (!isLoadingCategories && !categoryExists(selectedCategory, categories)) { history.replace(pagePathGetters.integrations_all({ category: '', searchTerm: searchParam })[1]); return null; } From a565fa02f3aa6e3ffce4efa59e67257f59479864 Mon Sep 17 00:00:00 2001 From: Pete Hampton Date: Mon, 4 Oct 2021 22:00:21 +0100 Subject: [PATCH 73/98] Fix issue with incorrect policy response attachment. (#113430) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../security_solution/server/lib/telemetry/receiver.ts | 2 +- .../server/lib/telemetry/tasks/endpoint.ts | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts index 8b715b8e8d585..038b7687784f4 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts @@ -84,7 +84,7 @@ export class TelemetryReceiver { policy_responses: { terms: { size: this.max_records, - field: 'Endpoint.policy.applied.id', + field: 'agent.id', }, aggs: { latest_response: { diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/tasks/endpoint.ts b/x-pack/plugins/security_solution/server/lib/telemetry/tasks/endpoint.ts index 2cebbc0af69c1..0c066deea17d9 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/tasks/endpoint.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/tasks/endpoint.ts @@ -190,13 +190,11 @@ export class TelemetryEndpointTask { * * As the policy id + policy version does not exist on the Endpoint Metrics document * we need to fetch information about the Fleet Agent and sync the metrics document - * with the Fleet agent's policy data. + * with the Agent's policy data. * - * 7.14 ~ An issue was created with the Endpoint agent team to add the policy id + - * policy version to the metrics document to circumvent and refactor away from - * this expensive join operation. */ const agentsResponse = endpointData.fleetAgentsResponse; + if (agentsResponse === undefined) { this.logger.debug('no fleet agent information available'); return 0; @@ -286,7 +284,7 @@ export class TelemetryEndpointTask { policyConfig = endpointPolicyCache.get(policyInformation) || null; if (policyConfig) { - failedPolicy = policyResponses.get(policyConfig?.id); + failedPolicy = policyResponses.get(endpointAgentId); } } @@ -294,7 +292,6 @@ export class TelemetryEndpointTask { return { '@timestamp': executeTo, - agent_id: fleetAgentId, endpoint_id: endpointAgentId, endpoint_version: endpoint.endpoint_version, endpoint_package_version: policyConfig?.package?.version || null, From 6f665004cb3b731ed6b2c9bb0ba66073e774759e Mon Sep 17 00:00:00 2001 From: Kellen <9484709+goodroot@users.noreply.github.com> Date: Mon, 4 Oct 2021 14:19:30 -0700 Subject: [PATCH 74/98] correct relativity in images (#113834) --- dev_docs/contributing/best_practices.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev_docs/contributing/best_practices.mdx b/dev_docs/contributing/best_practices.mdx index 27983d92ed121..284baababfc66 100644 --- a/dev_docs/contributing/best_practices.mdx +++ b/dev_docs/contributing/best_practices.mdx @@ -111,7 +111,7 @@ export getSearchService: (searchSpec: { username: string; password: string }) => In the former, there will be a link to the `SearchSpec` interface with documentation for the `username` and `password` properties. In the latter the object will render inline, without comments: -![prefer interfaces documentation](./assets/dev_docs_nested_object.png) +![prefer interfaces documentation](../assets/dev_docs_nested_object.png) #### Export every type used in a public API @@ -135,7 +135,7 @@ export type foo: string | AnInterface; `Pick` not only ends up being unhelpful in our documentation system, but it's also of limited help in your IDE. For that reason, avoid `Pick` and other similarly complex types on your public API items. Using these semantics internally is fine. -![pick api documentation](./assets/api_doc_pick.png) +![pick api documentation](../assets/api_doc_pick.png) ### Example plugins @@ -210,7 +210,7 @@ your large change right _after_ feature freeze. If you are worried about missing When possible, build features with incrementals sets of small and focused PRs, but don't check in unused code, and don't expose any feature on master that you would not be comfortable releasing. -![product_stages](./assets/product_stages.png) +![product_stages](../assets/product_stages.png) If your feature cannot be broken down into smaller components, or multiple engineers will be contributing, you have a few other options to consider. From 5ca923772dbc98f35d34d5a291112935a7f52e54 Mon Sep 17 00:00:00 2001 From: Clint Andrew Hall Date: Mon, 4 Oct 2021 16:49:44 -0500 Subject: [PATCH 75/98] [fleet] Add component story smoke test (#113634) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/fleet/jest.config.js | 3 +++ .../components/package_list_grid.stories.tsx | 27 ++++++++++++------- .../epm/screens/detail/overview/details.tsx | 4 +-- .../fleet/public/components/header.tsx | 4 +-- .../public/hooks/use_package_icon_type.ts | 3 ++- .../plugins/fleet/storybook/context/index.tsx | 6 +++++ x-pack/plugins/fleet/storybook/smoke.test.tsx | 22 +++++++++++++++ 7 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 x-pack/plugins/fleet/storybook/smoke.test.tsx diff --git a/x-pack/plugins/fleet/jest.config.js b/x-pack/plugins/fleet/jest.config.js index 5443318d52c8d..0841e48e59468 100644 --- a/x-pack/plugins/fleet/jest.config.js +++ b/x-pack/plugins/fleet/jest.config.js @@ -9,6 +9,9 @@ module.exports = { preset: '@kbn/test', rootDir: '../../..', roots: ['/x-pack/plugins/fleet'], + transform: { + '^.+\\.stories\\.tsx?$': '@storybook/addon-storyshots/injectFileName', + }, coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/fleet', coverageReporters: ['text', 'html'], collectCoverageFrom: ['/x-pack/plugins/fleet/{common,public,server}/**/*.{ts,tsx}'], diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.stories.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.stories.tsx index 737a83d5f5da8..f3bf7106fabcf 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.stories.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.stories.tsx @@ -66,7 +66,7 @@ export const List = (props: Args) => ( description: 'Not Installed Description', name: 'beats', release: 'ga', - id: 'id', + id: 'package_one', version: '1.0.0', uiInternalPath: '/', path: 'path', @@ -77,7 +77,7 @@ export const List = (props: Args) => ( description: 'Not Installed Description', name: 'aws', release: 'beta', - id: 'id', + id: 'package_two', version: '1.0.0', uiInternalPath: '/', path: 'path', @@ -88,7 +88,7 @@ export const List = (props: Args) => ( description: 'Not Installed Description', name: 'azure', release: 'experimental', - id: 'id', + id: 'package_three', version: '1.0.0', uiInternalPath: '/', path: 'path', @@ -99,36 +99,45 @@ export const List = (props: Args) => ( description: 'Installed Description', name: 'elastic', release: 'ga', - id: 'id', + id: 'package_four', version: '1.0.0', uiInternalPath: '/', path: 'path', status: 'installed', - savedObject, + savedObject: { + ...savedObject, + id: 'package_four', + }, }, { title: 'Package Five', description: 'Installed Description', name: 'unknown', release: 'beta', - id: 'id', + id: 'package_five', version: '1.0.0', uiInternalPath: '/', path: 'path', status: 'installed', - savedObject, + savedObject: { + ...savedObject, + id: 'package_five', + }, }, { title: 'Package Six', description: 'Installed Description', name: 'kibana', release: 'experimental', - id: 'id', + id: 'package_six', version: '1.0.0', uiInternalPath: '/', path: 'path', status: 'installed', - savedObject, + savedObject: { + ...savedObject, + id: 'package_six', + }, }, ] as unknown as IntegrationCardItem[] } diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx index 0a601d2128bba..467dae12fa583 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx @@ -97,10 +97,10 @@ export const Details: React.FC = memo(({ packageInfo }) => { ), description: ( - {entries(filteredTypes).map(([_type, parts]) => { + {entries(filteredTypes).map(([_type, parts], index) => { const type = _type as KibanaAssetType; return ( - + {AssetTitleMap[type]} diff --git a/x-pack/plugins/fleet/public/components/header.tsx b/x-pack/plugins/fleet/public/components/header.tsx index d2f713cc76680..80cebe3b0b304 100644 --- a/x-pack/plugins/fleet/public/components/header.tsx +++ b/x-pack/plugins/fleet/public/components/header.tsx @@ -78,8 +78,8 @@ export const Header: React.FC = ({ - {tabs.map((props) => ( - + {tabs.map((props, index) => ( + {props.name} ))} diff --git a/x-pack/plugins/fleet/public/hooks/use_package_icon_type.ts b/x-pack/plugins/fleet/public/hooks/use_package_icon_type.ts index a86c68c00c646..1b21b7bfd78eb 100644 --- a/x-pack/plugins/fleet/public/hooks/use_package_icon_type.ts +++ b/x-pack/plugins/fleet/public/hooks/use_package_icon_type.ts @@ -11,7 +11,8 @@ import { ICON_TYPES } from '@elastic/eui'; import type { PackageInfo, PackageListItem } from '../types'; // TODO: Determine whether this can be relocated -import { useLinks as useEPMLinks } from '../applications/integrations/hooks'; +// Import the specific hook to avoid a circular dependency in Babel +import { useLinks as useEPMLinks } from '../applications/integrations/hooks/use_links'; import { sendGetPackageInfoByKey } from './index'; diff --git a/x-pack/plugins/fleet/storybook/context/index.tsx b/x-pack/plugins/fleet/storybook/context/index.tsx index cf28d4ff54018..6c6b2e479d234 100644 --- a/x-pack/plugins/fleet/storybook/context/index.tsx +++ b/x-pack/plugins/fleet/storybook/context/index.tsx @@ -19,6 +19,8 @@ import type { FleetConfigType, FleetStartServices } from '../../public/plugin'; // TODO: This is a contract leak, and should be on the context, rather than a setter. import { setHttpClient } from '../../public/hooks/use_request'; +import { setCustomIntegrations } from '../../public/services/custom_integrations'; + import { getApplication } from './application'; import { getChrome } from './chrome'; import { getHttp } from './http'; @@ -58,6 +60,10 @@ export const StorybookContext: React.FC<{ storyContext?: StoryContext }> = ({ }; setHttpClient(startServices.http); + setCustomIntegrations({ + getAppendCustomIntegrations: async () => [], + getReplacementCustomIntegrations: async () => [], + }); const config = { enabled: true, diff --git a/x-pack/plugins/fleet/storybook/smoke.test.tsx b/x-pack/plugins/fleet/storybook/smoke.test.tsx new file mode 100644 index 0000000000000..e7bdc2e9d82a2 --- /dev/null +++ b/x-pack/plugins/fleet/storybook/smoke.test.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mount } from 'enzyme'; +import { createElement } from 'react'; +import { act } from 'react-dom/test-utils'; +import initStoryshots from '@storybook/addon-storyshots'; + +initStoryshots({ + configPath: __dirname, + framework: 'react', + test: async ({ story }) => { + const renderer = mount(createElement(story.render)); + // wait until the element will perform all renders and resolve all promises (lazy loading, especially) + await act(() => new Promise((resolve) => setTimeout(resolve, 0))); + expect(renderer.html()).not.toContain('euiErrorBoundary'); + }, +}); From 4d2a9c59a49d68cb49a2ae25ab8b3c35e357852a Mon Sep 17 00:00:00 2001 From: Byron Hulcher Date: Mon, 4 Oct 2021 17:57:18 -0400 Subject: [PATCH 76/98] [App Search] Detail Page for Automated Curations (#113550) --- .../components/suggestions_logic.test.tsx | 5 +- .../components/suggestions_logic.tsx | 2 +- .../components/curations/constants.ts | 17 +++ .../curation/automated_curation.test.tsx | 105 ++++++++++++++++++ .../curations/curation/automated_curation.tsx | 65 +++++++++++ .../curations/curation/curation.test.tsx | 73 +++--------- .../curations/curation/curation.tsx | 56 +--------- .../curations/curation/curation_logic.test.ts | 54 +++++++++ .../curations/curation/curation_logic.ts | 30 +++++ .../documents/organic_documents.test.tsx | 36 +++++- .../curation/documents/organic_documents.tsx | 53 +++++---- .../documents/promoted_documents.test.tsx | 55 ++++++++- .../curation/documents/promoted_documents.tsx | 71 ++++++++---- .../curation/manual_curation.test.tsx | 94 ++++++++++++++++ .../curations/curation/manual_curation.tsx | 68 ++++++++++++ .../results/add_result_button.test.tsx | 29 +++-- .../curation/results/add_result_button.tsx | 7 +- .../app_search/components/curations/types.ts | 3 + .../components/result/result_actions.tsx | 3 +- .../app_search/components/result/types.ts | 1 + .../search_relevance_suggestions.test.ts | 29 +++++ .../search_relevance_suggestions.ts | 14 +++ .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 24 files changed, 697 insertions(+), 177 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx index 5afbce3661da3..bf64101527fd2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx @@ -16,7 +16,7 @@ import { nextTick } from '@kbn/test/jest'; import { DEFAULT_META } from '../../../../shared/constants'; -import { SuggestionsLogic } from './suggestions_logic'; +import { SuggestionsAPIResponse, SuggestionsLogic } from './suggestions_logic'; const DEFAULT_VALUES = { dataLoading: true, @@ -30,7 +30,7 @@ const DEFAULT_VALUES = { }, }; -const MOCK_RESPONSE = { +const MOCK_RESPONSE: SuggestionsAPIResponse = { meta: { page: { current: 1, @@ -44,6 +44,7 @@ const MOCK_RESPONSE = { query: 'foo', updated_at: '2021-07-08T14:35:50Z', promoted: ['1', '2'], + status: 'applied', }, ], }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx index 9352bdab51edd..074d2114ee8cb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx @@ -15,7 +15,7 @@ import { updateMetaPageIndex } from '../../../../shared/table_pagination'; import { EngineLogic } from '../../engine'; import { CurationSuggestion } from '../types'; -interface SuggestionsAPIResponse { +export interface SuggestionsAPIResponse { results: CurationSuggestion[]; meta: Meta; } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts index f8c3e3efdbc1d..01ca80776ae85 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts @@ -50,6 +50,13 @@ export const RESTORE_CONFIRMATION = i18n.translate( } ); +export const CONVERT_TO_MANUAL_CONFIRMATION = i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.convertToManualCurationConfirmation', + { + defaultMessage: 'Are you sure you want to convert this to a manual curation?', + } +); + export const RESULT_ACTIONS_DIRECTIONS = i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.curations.resultActionsDescription', { defaultMessage: 'Promote results by clicking the star, hide them by clicking the eye.' } @@ -82,3 +89,13 @@ export const SHOW_DOCUMENT_ACTION = { iconType: 'eye', iconColor: 'primary' as EuiButtonIconColor, }; + +export const AUTOMATED_LABEL = i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curation.automatedLabel', + { defaultMessage: 'Automated' } +); + +export const COVERT_TO_MANUAL_BUTTON_LABEL = i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curation.convertToManualCurationButtonLabel', + { defaultMessage: 'Convert to manual curation' } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx new file mode 100644 index 0000000000000..3139d62863729 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../../__mocks__/shallow_useeffect.mock'; +import { setMockActions, setMockValues } from '../../../../__mocks__/kea_logic'; +import { mockUseParams } from '../../../../__mocks__/react_router'; +import '../../../__mocks__/engine_logic.mock'; + +import React from 'react'; + +import { shallow, ShallowWrapper } from 'enzyme'; + +import { EuiBadge } from '@elastic/eui'; + +import { getPageHeaderActions, getPageTitle } from '../../../../test_helpers'; + +jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() })); + +import { AppSearchPageTemplate } from '../../layout'; + +import { AutomatedCuration } from './automated_curation'; +import { CurationLogic } from './curation_logic'; + +import { PromotedDocuments, OrganicDocuments } from './documents'; + +describe('AutomatedCuration', () => { + const values = { + dataLoading: false, + queries: ['query A', 'query B'], + isFlyoutOpen: false, + curation: { + suggestion: { + status: 'applied', + }, + }, + activeQuery: 'query A', + isAutomated: true, + }; + + const actions = { + convertToManual: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + setMockValues(values); + setMockActions(actions); + mockUseParams.mockReturnValue({ curationId: 'test' }); + }); + + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.is(AppSearchPageTemplate)); + expect(wrapper.find(PromotedDocuments)).toHaveLength(1); + expect(wrapper.find(OrganicDocuments)).toHaveLength(1); + }); + + it('initializes CurationLogic with a curationId prop from URL param', () => { + mockUseParams.mockReturnValueOnce({ curationId: 'hello-world' }); + shallow(); + + expect(CurationLogic).toHaveBeenCalledWith({ curationId: 'hello-world' }); + }); + + it('displays the query in the title with a badge', () => { + const wrapper = shallow(); + const pageTitle = shallow(
    {getPageTitle(wrapper)}
    ); + + expect(pageTitle.text()).toContain('query A'); + expect(pageTitle.find(EuiBadge)).toHaveLength(1); + }); + + describe('convert to manual button', () => { + let convertToManualButton: ShallowWrapper; + let confirmSpy: jest.SpyInstance; + + beforeAll(() => { + const wrapper = shallow(); + convertToManualButton = getPageHeaderActions(wrapper).childAt(0); + + confirmSpy = jest.spyOn(window, 'confirm'); + }); + + afterAll(() => { + confirmSpy.mockRestore(); + }); + + it('converts the curation upon user confirmation', () => { + confirmSpy.mockReturnValueOnce(true); + convertToManualButton.simulate('click'); + expect(actions.convertToManual).toHaveBeenCalled(); + }); + + it('does not convert the curation if the user cancels', () => { + confirmSpy.mockReturnValueOnce(false); + convertToManualButton.simulate('click'); + expect(actions.convertToManual).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx new file mode 100644 index 0000000000000..1415537e42d6e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { useParams } from 'react-router-dom'; + +import { useValues, useActions } from 'kea'; + +import { EuiSpacer, EuiButton, EuiBadge } from '@elastic/eui'; + +import { AppSearchPageTemplate } from '../../layout'; +import { AutomatedIcon } from '../components/automated_icon'; +import { + AUTOMATED_LABEL, + COVERT_TO_MANUAL_BUTTON_LABEL, + CONVERT_TO_MANUAL_CONFIRMATION, +} from '../constants'; +import { getCurationsBreadcrumbs } from '../utils'; + +import { CurationLogic } from './curation_logic'; +import { PromotedDocuments, OrganicDocuments } from './documents'; + +export const AutomatedCuration: React.FC = () => { + const { curationId } = useParams<{ curationId: string }>(); + const logic = CurationLogic({ curationId }); + const { convertToManual } = useActions(logic); + const { activeQuery, dataLoading, queries } = useValues(logic); + + return ( + + {activeQuery}{' '} + + {AUTOMATED_LABEL} + + + ), + rightSideItems: [ + { + if (window.confirm(CONVERT_TO_MANUAL_CONFIRMATION)) convertToManual(); + }} + > + {COVERT_TO_MANUAL_BUTTON_LABEL} + , + ], + }} + isLoading={dataLoading} + > + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx index 2efe1f2ffe86f..62c3a6c7d4578 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx @@ -12,26 +12,25 @@ import '../../../__mocks__/engine_logic.mock'; import React from 'react'; -import { shallow, ShallowWrapper } from 'enzyme'; +import { shallow } from 'enzyme'; -import { rerender, getPageTitle, getPageHeaderActions } from '../../../../test_helpers'; +import { rerender } from '../../../../test_helpers'; jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() })); -import { CurationLogic } from './curation_logic'; -import { AddResultFlyout } from './results'; +import { AutomatedCuration } from './automated_curation'; + +import { ManualCuration } from './manual_curation'; import { Curation } from './'; describe('Curation', () => { const values = { - dataLoading: false, - queries: ['query A', 'query B'], - isFlyoutOpen: false, + isAutomated: true, }; + const actions = { loadCuration: jest.fn(), - resetCuration: jest.fn(), }; beforeEach(() => { @@ -40,32 +39,6 @@ describe('Curation', () => { setMockActions(actions); }); - it('renders', () => { - const wrapper = shallow(); - - expect(getPageTitle(wrapper)).toEqual('Manage curation'); - expect(wrapper.prop('pageChrome')).toEqual([ - 'Engines', - 'some-engine', - 'Curations', - 'query A, query B', - ]); - }); - - it('renders the add result flyout when open', () => { - setMockValues({ ...values, isFlyoutOpen: true }); - const wrapper = shallow(); - - expect(wrapper.find(AddResultFlyout)).toHaveLength(1); - }); - - it('initializes CurationLogic with a curationId prop from URL param', () => { - mockUseParams.mockReturnValueOnce({ curationId: 'hello-world' }); - shallow(); - - expect(CurationLogic).toHaveBeenCalledWith({ curationId: 'hello-world' }); - }); - it('calls loadCuration on page load & whenever the curationId URL param changes', () => { mockUseParams.mockReturnValueOnce({ curationId: 'cur-123456789' }); const wrapper = shallow(); @@ -76,31 +49,17 @@ describe('Curation', () => { expect(actions.loadCuration).toHaveBeenCalledTimes(2); }); - describe('restore defaults button', () => { - let restoreDefaultsButton: ShallowWrapper; - let confirmSpy: jest.SpyInstance; - - beforeAll(() => { - const wrapper = shallow(); - restoreDefaultsButton = getPageHeaderActions(wrapper).childAt(0); - - confirmSpy = jest.spyOn(window, 'confirm'); - }); + it('renders a view for automated curations', () => { + setMockValues({ isAutomated: true }); + const wrapper = shallow(); - afterAll(() => { - confirmSpy.mockRestore(); - }); + expect(wrapper.is(AutomatedCuration)).toBe(true); + }); - it('resets the curation upon user confirmation', () => { - confirmSpy.mockReturnValueOnce(true); - restoreDefaultsButton.simulate('click'); - expect(actions.resetCuration).toHaveBeenCalled(); - }); + it('renders a view for manual curations', () => { + setMockValues({ isAutomated: false }); + const wrapper = shallow(); - it('does not reset the curation if the user cancels', () => { - confirmSpy.mockReturnValueOnce(false); - restoreDefaultsButton.simulate('click'); - expect(actions.resetCuration).not.toHaveBeenCalled(); - }); + expect(wrapper.is(ManualCuration)).toBe(true); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx index 2a01c0db049ab..19b6542e96c4b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx @@ -10,64 +10,18 @@ import { useParams } from 'react-router-dom'; import { useValues, useActions } from 'kea'; -import { EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; - -import { RESTORE_DEFAULTS_BUTTON_LABEL } from '../../../constants'; -import { AppSearchPageTemplate } from '../../layout'; -import { MANAGE_CURATION_TITLE, RESTORE_CONFIRMATION } from '../constants'; -import { getCurationsBreadcrumbs } from '../utils'; - +import { AutomatedCuration } from './automated_curation'; import { CurationLogic } from './curation_logic'; -import { PromotedDocuments, OrganicDocuments, HiddenDocuments } from './documents'; -import { ActiveQuerySelect, ManageQueriesModal } from './queries'; -import { AddResultLogic, AddResultFlyout } from './results'; +import { ManualCuration } from './manual_curation'; export const Curation: React.FC = () => { const { curationId } = useParams() as { curationId: string }; - const { loadCuration, resetCuration } = useActions(CurationLogic({ curationId })); - const { dataLoading, queries } = useValues(CurationLogic({ curationId })); - const { isFlyoutOpen } = useValues(AddResultLogic); + const { loadCuration } = useActions(CurationLogic({ curationId })); + const { isAutomated } = useValues(CurationLogic({ curationId })); useEffect(() => { loadCuration(); }, [curationId]); - return ( - { - if (window.confirm(RESTORE_CONFIRMATION)) resetCuration(); - }} - > - {RESTORE_DEFAULTS_BUTTON_LABEL} - , - ], - }} - isLoading={dataLoading} - > - - - - - - - - - - - - - - - - - - {isFlyoutOpen && } - - ); + return isAutomated ? : ; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts index 8fa57e52a26a1..941fd0bf28f96 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts @@ -55,6 +55,7 @@ describe('CurationLogic', () => { promotedDocumentsLoading: false, hiddenIds: [], hiddenDocumentsLoading: false, + isAutomated: false, }; beforeEach(() => { @@ -265,7 +266,60 @@ describe('CurationLogic', () => { }); }); + describe('selectors', () => { + describe('isAutomated', () => { + it('is true when suggestion status is automated', () => { + mount({ curation: { suggestion: { status: 'automated' } } }); + + expect(CurationLogic.values.isAutomated).toBe(true); + }); + + it('is false when suggestion status is not automated', () => { + for (status of ['pending', 'applied', 'rejected', 'disabled']) { + mount({ curation: { suggestion: { status } } }); + + expect(CurationLogic.values.isAutomated).toBe(false); + } + }); + }); + }); + describe('listeners', () => { + describe('convertToManual', () => { + it('should make an API call and re-load the curation on success', async () => { + http.put.mockReturnValueOnce(Promise.resolve()); + mount({ activeQuery: 'some query' }); + jest.spyOn(CurationLogic.actions, 'loadCuration'); + + CurationLogic.actions.convertToManual(); + await nextTick(); + + expect(http.put).toHaveBeenCalledWith( + '/internal/app_search/engines/some-engine/search_relevance_suggestions', + { + body: JSON.stringify([ + { + query: 'some query', + type: 'curation', + status: 'applied', + }, + ]), + } + ); + expect(CurationLogic.actions.loadCuration).toHaveBeenCalled(); + }); + + it('flashes any error messages', async () => { + http.put.mockReturnValueOnce(Promise.reject('error')); + mount({ activeQuery: 'some query' }); + + CurationLogic.actions.convertToManual(); + await nextTick(); + + expect(flashAPIErrors).toHaveBeenCalledWith('error'); + }); + }); + describe('loadCuration', () => { it('should set dataLoading state', () => { mount({ dataLoading: false }, { curationId: 'cur-123456789' }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts index c49fc76d06874..a9fa5ab8c1048 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts @@ -27,9 +27,11 @@ interface CurationValues { promotedDocumentsLoading: boolean; hiddenIds: string[]; hiddenDocumentsLoading: boolean; + isAutomated: boolean; } interface CurationActions { + convertToManual(): void; loadCuration(): void; onCurationLoad(curation: Curation): { curation: Curation }; updateCuration(): void; @@ -53,6 +55,7 @@ interface CurationProps { export const CurationLogic = kea>({ path: ['enterprise_search', 'app_search', 'curation_logic'], actions: () => ({ + convertToManual: true, loadCuration: true, onCurationLoad: (curation) => ({ curation }), updateCuration: true, @@ -162,7 +165,34 @@ export const CurationLogic = kea ({ + isAutomated: [ + () => [selectors.curation], + (curation: CurationValues['curation']) => { + return curation.suggestion?.status === 'automated'; + }, + ], + }), listeners: ({ actions, values, props }) => ({ + convertToManual: async () => { + const { http } = HttpLogic.values; + const { engineName } = EngineLogic.values; + + try { + await http.put(`/internal/app_search/engines/${engineName}/search_relevance_suggestions`, { + body: JSON.stringify([ + { + query: values.activeQuery, + type: 'curation', + status: 'applied', + }, + ]), + }); + actions.loadCuration(); + } catch (e) { + flashAPIErrors(e); + } + }, loadCuration: async () => { const { http } = HttpLogic.values; const { engineName } = EngineLogic.values; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.test.tsx index 0624d0063e57d..b7955cf514079 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.test.tsx @@ -13,6 +13,8 @@ import { shallow } from 'enzyme'; import { EuiLoadingContent, EuiEmptyPrompt } from '@elastic/eui'; +import { mountWithIntl } from '../../../../../test_helpers'; + import { DataPanel } from '../../../data_panel'; import { CurationResult } from '../results'; @@ -30,6 +32,7 @@ describe('OrganicDocuments', () => { }, activeQuery: 'world', organicDocumentsLoading: false, + isAutomated: false, }; const actions = { addPromotedId: jest.fn(), @@ -56,6 +59,13 @@ describe('OrganicDocuments', () => { expect(titleText).toEqual('Top organic documents for "world"'); }); + it('shows a title when the curation is manual', () => { + setMockValues({ ...values, isAutomated: false }); + const wrapper = shallow(); + + expect(wrapper.find(DataPanel).prop('subtitle')).toContain('Promote results'); + }); + it('renders a loading state', () => { setMockValues({ ...values, organicDocumentsLoading: true }); const wrapper = shallow(); @@ -63,11 +73,21 @@ describe('OrganicDocuments', () => { expect(wrapper.find(EuiLoadingContent)).toHaveLength(1); }); - it('renders an empty state', () => { - setMockValues({ ...values, curation: { organic: [] } }); - const wrapper = shallow(); + describe('empty state', () => { + it('renders', () => { + setMockValues({ ...values, curation: { organic: [] } }); + const wrapper = shallow(); + + expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); + }); - expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); + it('tells the user to modify the query if the curation is manual', () => { + setMockValues({ ...values, curation: { organic: [] }, isAutomated: false }); + const wrapper = shallow(); + const emptyPromptBody = mountWithIntl(<>{wrapper.find(EuiEmptyPrompt).prop('body')}); + + expect(emptyPromptBody.text()).toContain('Add or change'); + }); }); describe('actions', () => { @@ -86,5 +106,13 @@ describe('OrganicDocuments', () => { expect(actions.addHiddenId).toHaveBeenCalledWith('mock-document-3'); }); + + it('hides actions when the curation is automated', () => { + setMockValues({ ...values, isAutomated: true }); + const wrapper = shallow(); + const result = wrapper.find(CurationResult).first(); + + expect(result.prop('actions')).toEqual([]); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.tsx index a3a761feefcd2..7314376a4a7ab 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.tsx @@ -11,6 +11,7 @@ import { useValues, useActions } from 'kea'; import { EuiLoadingContent, EuiEmptyPrompt } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { DataPanel } from '../../../data_panel'; import { Result } from '../../../result/types'; @@ -25,7 +26,7 @@ import { CurationResult } from '../results'; export const OrganicDocuments: React.FC = () => { const { addPromotedId, addHiddenId } = useActions(CurationLogic); - const { curation, activeQuery, organicDocumentsLoading } = useValues(CurationLogic); + const { curation, activeQuery, isAutomated, organicDocumentsLoading } = useValues(CurationLogic); const documents = curation.organic; const hasDocuments = documents.length > 0 && !organicDocumentsLoading; @@ -46,36 +47,50 @@ export const OrganicDocuments: React.FC = () => { )}

    } - subtitle={RESULT_ACTIONS_DIRECTIONS} + subtitle={!isAutomated && RESULT_ACTIONS_DIRECTIONS} > {hasDocuments ? ( documents.map((document: Result) => ( addHiddenId(document.id.raw), - }, - { - ...PROMOTE_DOCUMENT_ACTION, - onClick: () => addPromotedId(document.id.raw), - }, - ]} + actions={ + isAutomated + ? [] + : [ + { + ...HIDE_DOCUMENT_ACTION, + onClick: () => addHiddenId(document.id.raw), + }, + { + ...PROMOTE_DOCUMENT_ACTION, + onClick: () => addPromotedId(document.id.raw), + }, + ] + } /> )) ) : organicDocumentsLoading ? ( ) : ( + {' '} + + + ), + }} + /> + } /> )} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.test.tsx index e0c6de973666c..a66b33a47f35c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.test.tsx @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { setMockValues, setMockActions } from '../../../../../__mocks__/kea_logic'; import React from 'react'; @@ -13,6 +12,7 @@ import { shallow } from 'enzyme'; import { EuiDragDropContext, EuiDraggable, EuiEmptyPrompt, EuiButtonEmpty } from '@elastic/eui'; +import { mountWithIntl } from '../../../../../test_helpers'; import { DataPanel } from '../../../data_panel'; import { CurationResult } from '../results'; @@ -57,11 +57,50 @@ describe('PromotedDocuments', () => { }); }); - it('renders an empty state & hides the panel actions when empty', () => { + it('informs the user documents can be re-ordered if the curation is manual', () => { + setMockValues({ ...values, isAutomated: false }); + const wrapper = shallow(); + const subtitle = mountWithIntl(wrapper.prop('subtitle')); + + expect(subtitle.text()).toContain('Documents can be re-ordered'); + }); + + it('informs the user the curation is managed if the curation is automated', () => { + setMockValues({ ...values, isAutomated: true }); + const wrapper = shallow(); + const subtitle = mountWithIntl(wrapper.prop('subtitle')); + + expect(subtitle.text()).toContain('managed by App Search'); + }); + + describe('empty state', () => { + it('renders', () => { + setMockValues({ ...values, curation: { promoted: [] } }); + const wrapper = shallow(); + + expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); + }); + + it('hide information about starring documents if the curation is automated', () => { + setMockValues({ ...values, curation: { promoted: [] }, isAutomated: true }); + const wrapper = shallow(); + const emptyPromptBody = mountWithIntl(<>{wrapper.find(EuiEmptyPrompt).prop('body')}); + + expect(emptyPromptBody.text()).not.toContain('Star documents'); + }); + }); + + it('hides the panel actions when empty', () => { setMockValues({ ...values, curation: { promoted: [] } }); const wrapper = shallow(); - expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); + expect(wrapper.find(DataPanel).prop('action')).toBe(false); + }); + + it('hides the panel actions when the curation is automated', () => { + setMockValues({ ...values, isAutomated: true }); + const wrapper = shallow(); + expect(wrapper.find(DataPanel).prop('action')).toBe(false); }); @@ -81,6 +120,14 @@ describe('PromotedDocuments', () => { expect(actions.removePromotedId).toHaveBeenCalledWith('mock-document-4'); }); + it('hides demote button for results when the curation is automated', () => { + setMockValues({ ...values, isAutomated: true }); + const wrapper = shallow(); + const result = getDraggableChildren(wrapper.find(EuiDraggable).last()); + + expect(result.prop('actions')).toEqual([]); + }); + it('renders a demote all button that demotes all hidden results', () => { const wrapper = shallow(); const panelActions = shallow(wrapper.find(DataPanel).prop('action') as React.ReactElement); @@ -89,7 +136,7 @@ describe('PromotedDocuments', () => { expect(actions.clearPromotedIds).toHaveBeenCalled(); }); - describe('draggging', () => { + describe('dragging', () => { it('calls setPromotedIds with the reordered list when users are done dragging', () => { const wrapper = shallow(); wrapper.find(EuiDragDropContext).simulate('dragEnd', { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.tsx index 6b0a02aa2af58..e9d9136a45ac6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.tsx @@ -21,6 +21,7 @@ import { euiDragDropReorder, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { DataPanel } from '../../../data_panel'; @@ -29,7 +30,7 @@ import { CurationLogic } from '../curation_logic'; import { AddResultButton, CurationResult, convertToResultFormat } from '../results'; export const PromotedDocuments: React.FC = () => { - const { curation, promotedIds, promotedDocumentsLoading } = useValues(CurationLogic); + const { curation, isAutomated, promotedIds, promotedDocumentsLoading } = useValues(CurationLogic); const documents = curation.promoted; const hasDocuments = documents.length > 0; @@ -53,21 +54,33 @@ export const PromotedDocuments: React.FC = () => { )} } - subtitle={i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.description', - { - defaultMessage: - 'Promoted results appear before organic results. Documents can be re-ordered.', - } - )} + subtitle={ + isAutomated ? ( + + ) : ( + + ) + } action={ + !isAutomated && hasDocuments && ( - + {i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.removeAllButtonLabel', { defaultMessage: 'Demote all' } @@ -89,17 +102,22 @@ export const PromotedDocuments: React.FC = () => { draggableId={document.id} customDragHandle spacing="none" + isDragDisabled={isAutomated} > {(provided) => ( removePromotedId(document.id), - }, - ]} + actions={ + isAutomated + ? [] + : [ + { + ...DEMOTE_DOCUMENT_ACTION, + onClick: () => removePromotedId(document.id), + }, + ] + } dragHandleProps={provided.dragHandleProps} /> )} @@ -109,13 +127,22 @@ export const PromotedDocuments: React.FC = () => { ) : ( } /> )} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx new file mode 100644 index 0000000000000..ad9f3bcd64e3e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../../__mocks__/shallow_useeffect.mock'; +import { setMockActions, setMockValues } from '../../../../__mocks__/kea_logic'; +import { mockUseParams } from '../../../../__mocks__/react_router'; +import '../../../__mocks__/engine_logic.mock'; + +import React from 'react'; + +import { shallow, ShallowWrapper } from 'enzyme'; + +import { getPageTitle, getPageHeaderActions } from '../../../../test_helpers'; + +jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() })); +import { CurationLogic } from './curation_logic'; + +import { ManualCuration } from './manual_curation'; +import { AddResultFlyout } from './results'; + +describe('ManualCuration', () => { + const values = { + dataLoading: false, + queries: ['query A', 'query B'], + isFlyoutOpen: false, + }; + const actions = { + resetCuration: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + setMockValues(values); + setMockActions(actions); + }); + + it('renders', () => { + const wrapper = shallow(); + + expect(getPageTitle(wrapper)).toEqual('Manage curation'); + expect(wrapper.prop('pageChrome')).toEqual([ + 'Engines', + 'some-engine', + 'Curations', + 'query A, query B', + ]); + }); + + it('renders the add result flyout when open', () => { + setMockValues({ ...values, isFlyoutOpen: true }); + const wrapper = shallow(); + + expect(wrapper.find(AddResultFlyout)).toHaveLength(1); + }); + + it('initializes CurationLogic with a curationId prop from URL param', () => { + mockUseParams.mockReturnValueOnce({ curationId: 'hello-world' }); + shallow(); + + expect(CurationLogic).toHaveBeenCalledWith({ curationId: 'hello-world' }); + }); + + describe('restore defaults button', () => { + let restoreDefaultsButton: ShallowWrapper; + let confirmSpy: jest.SpyInstance; + + beforeAll(() => { + const wrapper = shallow(); + restoreDefaultsButton = getPageHeaderActions(wrapper).childAt(0); + + confirmSpy = jest.spyOn(window, 'confirm'); + }); + + afterAll(() => { + confirmSpy.mockRestore(); + }); + + it('resets the curation upon user confirmation', () => { + confirmSpy.mockReturnValueOnce(true); + restoreDefaultsButton.simulate('click'); + expect(actions.resetCuration).toHaveBeenCalled(); + }); + + it('does not reset the curation if the user cancels', () => { + confirmSpy.mockReturnValueOnce(false); + restoreDefaultsButton.simulate('click'); + expect(actions.resetCuration).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx new file mode 100644 index 0000000000000..d50575535bf21 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { useParams } from 'react-router-dom'; + +import { useValues, useActions } from 'kea'; + +import { EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; + +import { RESTORE_DEFAULTS_BUTTON_LABEL } from '../../../constants'; +import { AppSearchPageTemplate } from '../../layout'; +import { MANAGE_CURATION_TITLE, RESTORE_CONFIRMATION } from '../constants'; +import { getCurationsBreadcrumbs } from '../utils'; + +import { CurationLogic } from './curation_logic'; +import { PromotedDocuments, OrganicDocuments, HiddenDocuments } from './documents'; +import { ActiveQuerySelect, ManageQueriesModal } from './queries'; +import { AddResultLogic, AddResultFlyout } from './results'; + +export const ManualCuration: React.FC = () => { + const { curationId } = useParams() as { curationId: string }; + const { resetCuration } = useActions(CurationLogic({ curationId })); + const { dataLoading, queries } = useValues(CurationLogic({ curationId })); + const { isFlyoutOpen } = useValues(AddResultLogic); + + return ( + { + if (window.confirm(RESTORE_CONFIRMATION)) resetCuration(); + }} + > + {RESTORE_DEFAULTS_BUTTON_LABEL} +
    , + ], + }} + isLoading={dataLoading} + > + + + + + + + + + + + + + + + + + {isFlyoutOpen && } + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.test.tsx index 53cefdd00c670..5b5c814a24c5b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.test.tsx @@ -5,34 +5,43 @@ * 2.0. */ -import { setMockActions } from '../../../../../__mocks__/kea_logic'; +import { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; import React from 'react'; -import { shallow, ShallowWrapper } from 'enzyme'; +import { shallow } from 'enzyme'; import { EuiButton } from '@elastic/eui'; import { AddResultButton } from './'; describe('AddResultButton', () => { + const values = { + isAutomated: false, + }; + const actions = { openFlyout: jest.fn(), }; - let wrapper: ShallowWrapper; - - beforeAll(() => { - setMockActions(actions); - wrapper = shallow(); - }); - it('renders', () => { - expect(wrapper.find(EuiButton)).toHaveLength(1); + const wrapper = shallow(); + + expect(wrapper.is(EuiButton)).toBe(true); }); it('opens the add result flyout on click', () => { + setMockActions(actions); + const wrapper = shallow(); + wrapper.find(EuiButton).simulate('click'); expect(actions.openFlyout).toHaveBeenCalled(); }); + + it('is disbled when the curation is automated', () => { + setMockValues({ ...values, isAutomated: true }); + const wrapper = shallow(); + + expect(wrapper.find(EuiButton).prop('disabled')).toBe(true); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.tsx index 025dda65f4fb8..f2285064da307 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.tsx @@ -7,18 +7,21 @@ import React from 'react'; -import { useActions } from 'kea'; +import { useActions, useValues } from 'kea'; import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { CurationLogic } from '..'; + import { AddResultLogic } from './'; export const AddResultButton: React.FC = () => { const { openFlyout } = useActions(AddResultLogic); + const { isAutomated } = useValues(CurationLogic); return ( - + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.addResult.buttonLabel', { defaultMessage: 'Add result manually', })} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts index 866bf6490ebe8..09c8a487b1b9b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts @@ -12,7 +12,9 @@ export interface CurationSuggestion { query: string; updated_at: string; promoted: string[]; + status: 'pending' | 'applied' | 'automated' | 'rejected' | 'disabled'; } + export interface Curation { id: string; last_updated: string; @@ -20,6 +22,7 @@ export interface Curation { promoted: CurationResult[]; hidden: CurationResult[]; organic: Result[]; + suggestion?: CurationSuggestion; } export interface CurationsAPIResponse { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_actions.tsx index 52fbee90fe31a..5eac38b88937c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_actions.tsx @@ -18,7 +18,7 @@ interface Props { export const ResultActions: React.FC = ({ actions }) => { return ( - {actions.map(({ onClick, title, iconType, iconColor }) => ( + {actions.map(({ onClick, title, iconType, iconColor, disabled }) => ( = ({ actions }) => { color={iconColor ? iconColor : 'primary'} aria-label={title} title={title} + disabled={disabled} /> ))} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts index 4be3eb137177b..d9f1bb394778e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts @@ -41,4 +41,5 @@ export interface ResultAction { title: string; iconType: string; iconColor?: EuiButtonIconColor; + disabled?: boolean; } diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts index e6bfaa4a9cca2..2bdcfb9fe9d58 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts @@ -38,6 +38,35 @@ describe('search relevance insights routes', () => { }); }); + describe('PUT /internal/app_search/engines/{name}/search_relevance_suggestions', () => { + const mockRouter = new MockRouter({ + method: 'put', + path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions', + }); + + beforeEach(() => { + registerSearchRelevanceSuggestionsRoutes({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request to enterprise search', () => { + mockRouter.callRoute({ + params: { engineName: 'some-engine' }, + body: { + query: 'some query', + type: 'curation', + status: 'applied', + }, + }); + + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/api/as/v0/engines/:engineName/search_relevance_suggestions', + }); + }); + }); + describe('GET /internal/app_search/engines/{name}/search_relevance_suggestions/settings', () => { const mockRouter = new MockRouter({ method: 'get', diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts index c6fa108a5629e..8b3b204c24d70 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts @@ -39,6 +39,20 @@ export function registerSearchRelevanceSuggestionsRoutes({ }) ); + router.put( + skipBodyValidation({ + path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions', + validate: { + params: schema.object({ + engineName: schema.string(), + }), + }, + }), + enterpriseSearchRequestHandler.createRequest({ + path: '/api/as/v0/engines/:engineName/search_relevance_suggestions', + }) + ); + router.get( { path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/settings', diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index dcbb8ce26ee4a..62e35bf2aae5f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9346,11 +9346,9 @@ "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryButtonLabel": "クエリを管理", "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryDescription": "このキュレーションのクエリを編集、追加、削除します。", "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryTitle": "クエリを管理", - "xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.emptyDescription": "表示するオーガニック結果はありません。上記のアクティブなクエリを追加または変更します。", "xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.title": "\"{currentQuery}\"の上位のオーガニックドキュメント", "xpack.enterpriseSearch.appSearch.engine.curations.overview.title": "キュレーションされた結果", "xpack.enterpriseSearch.appSearch.engine.curations.promoteButtonLabel": "この結果を昇格", - "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.description": "昇格された結果はオーガニック結果の前に表示されます。ドキュメントを並べ替えることができます。", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.emptyDescription": "以下のオーガニック結果からドキュメントにスターを付けるか、手動で結果を検索して昇格します。", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.removeAllButtonLabel": "すべて降格", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.title": "昇格されたドキュメント", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 87c96d1efe48d..2f58cf9c10abf 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9438,11 +9438,9 @@ "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryButtonLabel": "管理查询", "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryDescription": "编辑、添加或移除此策展的查询。", "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryTitle": "管理查询", - "xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.emptyDescription": "没有要显示的有机结果。在上面添加或更改活动查询。", "xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.title": "“{currentQuery}”的排名靠前有机文档", "xpack.enterpriseSearch.appSearch.engine.curations.overview.title": "已策展结果", "xpack.enterpriseSearch.appSearch.engine.curations.promoteButtonLabel": "提升此结果", - "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.description": "提升结果显示在有机结果之前。可以重新排列文档。", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.emptyDescription": "使用星号标记来自下面有机结果的文档或手动搜索或提升结果。", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.removeAllButtonLabel": "全部降低", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.title": "提升文档", From 73f232f5b3151c60cc6c8baf10082dd41ab13ac9 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Mon, 4 Oct 2021 15:20:11 -0700 Subject: [PATCH 77/98] [Alerting][Docs] Elasticsearch setting `search.allow_expensive_queries` should be set as true. (#113062) * [Alerting][Docs] Elasticsearch setting search.allow_expensive_queries should be set to true. * fixed text * fixed text * fixed due to comments * Update alerting-setup.asciidoc --- docs/user/alerting/alerting-setup.asciidoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/user/alerting/alerting-setup.asciidoc b/docs/user/alerting/alerting-setup.asciidoc index 3f12925bbef07..3b9868178fa8d 100644 --- a/docs/user/alerting/alerting-setup.asciidoc +++ b/docs/user/alerting/alerting-setup.asciidoc @@ -1,6 +1,6 @@ [role="xpack"] [[alerting-setup]] -== Alerting Set up +== Alerting set up ++++ Set up ++++ @@ -20,6 +20,8 @@ If you are using an *on-premises* Elastic Stack deployment with <>. {kib} alerting uses <> to secure background rule checks and actions, and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. A proxy will not suffice. * If you have enabled TLS and are still unable to access Alerting, ensure that you have not {ref}/security-settings.html#api-key-service-settings[explicitly disabled API keys]. +The Alerting framework uses queries that require the `search.allow_expensive_queries` setting to be `true`. See the scripts {ref}/query-dsl-script-query.html#_allow_expensive_queries_4[documentation]. + [float] [[alerting-setup-production]] === Production considerations and scaling guidance From 55bd942a1f12190cb4e816236bd99c74c3b8d55c Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Mon, 4 Oct 2021 15:47:10 -0700 Subject: [PATCH 78/98] Update schema_overview.tsx (#113848) --- .../public/components/app/Settings/schema/schema_overview.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/Settings/schema/schema_overview.tsx b/x-pack/plugins/apm/public/components/app/Settings/schema/schema_overview.tsx index 00e03484dc736..0031c102e8ae5 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/schema/schema_overview.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/schema/schema_overview.tsx @@ -148,7 +148,7 @@ export function SchemaOverview({ 'xpack.apm.settings.schema.migrate.classicIndices.description', { defaultMessage: - 'You are currently using APM Server binary. This legacy option is deprecated since version 7.16 and is being replaced by a manages APM Server in Elastic Agent from version 8.0.', + 'You are currently using APM Server binary. This legacy option is deprecated since version 7.16 and is being replaced by a managed APM Server in Elastic Agent from version 8.0.', } )} footer={ @@ -180,7 +180,7 @@ export function SchemaOverview({ 'xpack.apm.settings.schema.migrate.dataStreams.description', { defaultMessage: - 'Your APM Server will need to be managed by Elastic Agent from version 8.0 and onwards. You can run Elastic Agent on Cloud, ECE or self-managed and install the Elastic APM integration in order to continue ingesting APM data.', + 'Starting in version 8.0, Elastic Agent must manage APM Server. Elastic Agent can run on our hosted Elasticsearch Service, ECE, or be self-managed. Then, add the Elastic APM integration to continue ingesting APM data.', } )} footer={ From fc89528c40e09cfcc5ecef3ac43fedd08e6d1a7f Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Mon, 4 Oct 2021 19:29:43 -0400 Subject: [PATCH 79/98] [buildkite] Fix off-by-one problem for test failure annotations (#113852) --- .../failed_tests_reporter/report_failures_to_file.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/kbn-test/src/failed_tests_reporter/report_failures_to_file.ts b/packages/kbn-test/src/failed_tests_reporter/report_failures_to_file.ts index aca2e6838faec..f075f6ef0b75b 100644 --- a/packages/kbn-test/src/failed_tests_reporter/report_failures_to_file.ts +++ b/packages/kbn-test/src/failed_tests_reporter/report_failures_to_file.ts @@ -76,6 +76,12 @@ export function reportFailuresToFile(log: ToolingLog, failures: TestFailure[]) { .flat() .join('\n'); + // Buildkite steps that use `parallelism` need a numerical suffix added to identify them + // We should also increment the number by one, since it's 0-based + const jobNumberSuffix = process.env.BUILDKITE_PARALLEL_JOB + ? ` #${parseInt(process.env.BUILDKITE_PARALLEL_JOB, 10) + 1}` + : ''; + const failureJSON = JSON.stringify( { ...failure, @@ -84,9 +90,7 @@ export function reportFailuresToFile(log: ToolingLog, failures: TestFailure[]) { jobId: process.env.BUILDKITE_JOB_ID || '', url: process.env.BUILDKITE_BUILD_URL || '', jobName: process.env.BUILDKITE_LABEL - ? `${process.env.BUILDKITE_LABEL}${ - process.env.BUILDKITE_PARALLEL_JOB ? ` #${process.env.BUILDKITE_PARALLEL_JOB}` : '' - }` + ? `${process.env.BUILDKITE_LABEL}${jobNumberSuffix}` : '', }, null, From 7ad30eda158c5b31e489341a052c67b164e91961 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Mon, 4 Oct 2021 21:02:49 -0400 Subject: [PATCH 80/98] Revert "[App Search] Detail Page for Automated Curations (#113550)" This reverts commit 4d2a9c59a49d68cb49a2ae25ab8b3c35e357852a. --- .../components/suggestions_logic.test.tsx | 5 +- .../components/suggestions_logic.tsx | 2 +- .../components/curations/constants.ts | 17 --- .../curation/automated_curation.test.tsx | 105 ------------------ .../curations/curation/automated_curation.tsx | 65 ----------- .../curations/curation/curation.test.tsx | 73 +++++++++--- .../curations/curation/curation.tsx | 56 +++++++++- .../curations/curation/curation_logic.test.ts | 54 --------- .../curations/curation/curation_logic.ts | 30 ----- .../documents/organic_documents.test.tsx | 36 +----- .../curation/documents/organic_documents.tsx | 53 ++++----- .../documents/promoted_documents.test.tsx | 55 +-------- .../curation/documents/promoted_documents.tsx | 71 ++++-------- .../curation/manual_curation.test.tsx | 94 ---------------- .../curations/curation/manual_curation.tsx | 68 ------------ .../results/add_result_button.test.tsx | 29 ++--- .../curation/results/add_result_button.tsx | 7 +- .../app_search/components/curations/types.ts | 3 - .../components/result/result_actions.tsx | 3 +- .../app_search/components/result/types.ts | 1 - .../search_relevance_suggestions.test.ts | 29 ----- .../search_relevance_suggestions.ts | 14 --- .../translations/translations/ja-JP.json | 2 + .../translations/translations/zh-CN.json | 2 + 24 files changed, 177 insertions(+), 697 deletions(-) delete mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx index bf64101527fd2..5afbce3661da3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.test.tsx @@ -16,7 +16,7 @@ import { nextTick } from '@kbn/test/jest'; import { DEFAULT_META } from '../../../../shared/constants'; -import { SuggestionsAPIResponse, SuggestionsLogic } from './suggestions_logic'; +import { SuggestionsLogic } from './suggestions_logic'; const DEFAULT_VALUES = { dataLoading: true, @@ -30,7 +30,7 @@ const DEFAULT_VALUES = { }, }; -const MOCK_RESPONSE: SuggestionsAPIResponse = { +const MOCK_RESPONSE = { meta: { page: { current: 1, @@ -44,7 +44,6 @@ const MOCK_RESPONSE: SuggestionsAPIResponse = { query: 'foo', updated_at: '2021-07-08T14:35:50Z', promoted: ['1', '2'], - status: 'applied', }, ], }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx index 074d2114ee8cb..9352bdab51edd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/suggestions_logic.tsx @@ -15,7 +15,7 @@ import { updateMetaPageIndex } from '../../../../shared/table_pagination'; import { EngineLogic } from '../../engine'; import { CurationSuggestion } from '../types'; -export interface SuggestionsAPIResponse { +interface SuggestionsAPIResponse { results: CurationSuggestion[]; meta: Meta; } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts index 01ca80776ae85..f8c3e3efdbc1d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/constants.ts @@ -50,13 +50,6 @@ export const RESTORE_CONFIRMATION = i18n.translate( } ); -export const CONVERT_TO_MANUAL_CONFIRMATION = i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.curations.convertToManualCurationConfirmation', - { - defaultMessage: 'Are you sure you want to convert this to a manual curation?', - } -); - export const RESULT_ACTIONS_DIRECTIONS = i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.curations.resultActionsDescription', { defaultMessage: 'Promote results by clicking the star, hide them by clicking the eye.' } @@ -89,13 +82,3 @@ export const SHOW_DOCUMENT_ACTION = { iconType: 'eye', iconColor: 'primary' as EuiButtonIconColor, }; - -export const AUTOMATED_LABEL = i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.curation.automatedLabel', - { defaultMessage: 'Automated' } -); - -export const COVERT_TO_MANUAL_BUTTON_LABEL = i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.curation.convertToManualCurationButtonLabel', - { defaultMessage: 'Convert to manual curation' } -); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx deleted file mode 100644 index 3139d62863729..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx +++ /dev/null @@ -1,105 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import '../../../../__mocks__/shallow_useeffect.mock'; -import { setMockActions, setMockValues } from '../../../../__mocks__/kea_logic'; -import { mockUseParams } from '../../../../__mocks__/react_router'; -import '../../../__mocks__/engine_logic.mock'; - -import React from 'react'; - -import { shallow, ShallowWrapper } from 'enzyme'; - -import { EuiBadge } from '@elastic/eui'; - -import { getPageHeaderActions, getPageTitle } from '../../../../test_helpers'; - -jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() })); - -import { AppSearchPageTemplate } from '../../layout'; - -import { AutomatedCuration } from './automated_curation'; -import { CurationLogic } from './curation_logic'; - -import { PromotedDocuments, OrganicDocuments } from './documents'; - -describe('AutomatedCuration', () => { - const values = { - dataLoading: false, - queries: ['query A', 'query B'], - isFlyoutOpen: false, - curation: { - suggestion: { - status: 'applied', - }, - }, - activeQuery: 'query A', - isAutomated: true, - }; - - const actions = { - convertToManual: jest.fn(), - }; - - beforeEach(() => { - jest.clearAllMocks(); - setMockValues(values); - setMockActions(actions); - mockUseParams.mockReturnValue({ curationId: 'test' }); - }); - - it('renders', () => { - const wrapper = shallow(); - - expect(wrapper.is(AppSearchPageTemplate)); - expect(wrapper.find(PromotedDocuments)).toHaveLength(1); - expect(wrapper.find(OrganicDocuments)).toHaveLength(1); - }); - - it('initializes CurationLogic with a curationId prop from URL param', () => { - mockUseParams.mockReturnValueOnce({ curationId: 'hello-world' }); - shallow(); - - expect(CurationLogic).toHaveBeenCalledWith({ curationId: 'hello-world' }); - }); - - it('displays the query in the title with a badge', () => { - const wrapper = shallow(); - const pageTitle = shallow(
    {getPageTitle(wrapper)}
    ); - - expect(pageTitle.text()).toContain('query A'); - expect(pageTitle.find(EuiBadge)).toHaveLength(1); - }); - - describe('convert to manual button', () => { - let convertToManualButton: ShallowWrapper; - let confirmSpy: jest.SpyInstance; - - beforeAll(() => { - const wrapper = shallow(); - convertToManualButton = getPageHeaderActions(wrapper).childAt(0); - - confirmSpy = jest.spyOn(window, 'confirm'); - }); - - afterAll(() => { - confirmSpy.mockRestore(); - }); - - it('converts the curation upon user confirmation', () => { - confirmSpy.mockReturnValueOnce(true); - convertToManualButton.simulate('click'); - expect(actions.convertToManual).toHaveBeenCalled(); - }); - - it('does not convert the curation if the user cancels', () => { - confirmSpy.mockReturnValueOnce(false); - convertToManualButton.simulate('click'); - expect(actions.convertToManual).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx deleted file mode 100644 index 1415537e42d6e..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx +++ /dev/null @@ -1,65 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { useParams } from 'react-router-dom'; - -import { useValues, useActions } from 'kea'; - -import { EuiSpacer, EuiButton, EuiBadge } from '@elastic/eui'; - -import { AppSearchPageTemplate } from '../../layout'; -import { AutomatedIcon } from '../components/automated_icon'; -import { - AUTOMATED_LABEL, - COVERT_TO_MANUAL_BUTTON_LABEL, - CONVERT_TO_MANUAL_CONFIRMATION, -} from '../constants'; -import { getCurationsBreadcrumbs } from '../utils'; - -import { CurationLogic } from './curation_logic'; -import { PromotedDocuments, OrganicDocuments } from './documents'; - -export const AutomatedCuration: React.FC = () => { - const { curationId } = useParams<{ curationId: string }>(); - const logic = CurationLogic({ curationId }); - const { convertToManual } = useActions(logic); - const { activeQuery, dataLoading, queries } = useValues(logic); - - return ( - - {activeQuery}{' '} - - {AUTOMATED_LABEL} - - - ), - rightSideItems: [ - { - if (window.confirm(CONVERT_TO_MANUAL_CONFIRMATION)) convertToManual(); - }} - > - {COVERT_TO_MANUAL_BUTTON_LABEL} - , - ], - }} - isLoading={dataLoading} - > - - - - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx index 62c3a6c7d4578..2efe1f2ffe86f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.test.tsx @@ -12,25 +12,26 @@ import '../../../__mocks__/engine_logic.mock'; import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, ShallowWrapper } from 'enzyme'; -import { rerender } from '../../../../test_helpers'; +import { rerender, getPageTitle, getPageHeaderActions } from '../../../../test_helpers'; jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() })); +import { CurationLogic } from './curation_logic'; -import { AutomatedCuration } from './automated_curation'; - -import { ManualCuration } from './manual_curation'; +import { AddResultFlyout } from './results'; import { Curation } from './'; describe('Curation', () => { const values = { - isAutomated: true, + dataLoading: false, + queries: ['query A', 'query B'], + isFlyoutOpen: false, }; - const actions = { loadCuration: jest.fn(), + resetCuration: jest.fn(), }; beforeEach(() => { @@ -39,6 +40,32 @@ describe('Curation', () => { setMockActions(actions); }); + it('renders', () => { + const wrapper = shallow(); + + expect(getPageTitle(wrapper)).toEqual('Manage curation'); + expect(wrapper.prop('pageChrome')).toEqual([ + 'Engines', + 'some-engine', + 'Curations', + 'query A, query B', + ]); + }); + + it('renders the add result flyout when open', () => { + setMockValues({ ...values, isFlyoutOpen: true }); + const wrapper = shallow(); + + expect(wrapper.find(AddResultFlyout)).toHaveLength(1); + }); + + it('initializes CurationLogic with a curationId prop from URL param', () => { + mockUseParams.mockReturnValueOnce({ curationId: 'hello-world' }); + shallow(); + + expect(CurationLogic).toHaveBeenCalledWith({ curationId: 'hello-world' }); + }); + it('calls loadCuration on page load & whenever the curationId URL param changes', () => { mockUseParams.mockReturnValueOnce({ curationId: 'cur-123456789' }); const wrapper = shallow(); @@ -49,17 +76,31 @@ describe('Curation', () => { expect(actions.loadCuration).toHaveBeenCalledTimes(2); }); - it('renders a view for automated curations', () => { - setMockValues({ isAutomated: true }); - const wrapper = shallow(); + describe('restore defaults button', () => { + let restoreDefaultsButton: ShallowWrapper; + let confirmSpy: jest.SpyInstance; - expect(wrapper.is(AutomatedCuration)).toBe(true); - }); + beforeAll(() => { + const wrapper = shallow(); + restoreDefaultsButton = getPageHeaderActions(wrapper).childAt(0); - it('renders a view for manual curations', () => { - setMockValues({ isAutomated: false }); - const wrapper = shallow(); + confirmSpy = jest.spyOn(window, 'confirm'); + }); + + afterAll(() => { + confirmSpy.mockRestore(); + }); + + it('resets the curation upon user confirmation', () => { + confirmSpy.mockReturnValueOnce(true); + restoreDefaultsButton.simulate('click'); + expect(actions.resetCuration).toHaveBeenCalled(); + }); - expect(wrapper.is(ManualCuration)).toBe(true); + it('does not reset the curation if the user cancels', () => { + confirmSpy.mockReturnValueOnce(false); + restoreDefaultsButton.simulate('click'); + expect(actions.resetCuration).not.toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx index 19b6542e96c4b..2a01c0db049ab 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation.tsx @@ -10,18 +10,64 @@ import { useParams } from 'react-router-dom'; import { useValues, useActions } from 'kea'; -import { AutomatedCuration } from './automated_curation'; +import { EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; + +import { RESTORE_DEFAULTS_BUTTON_LABEL } from '../../../constants'; +import { AppSearchPageTemplate } from '../../layout'; +import { MANAGE_CURATION_TITLE, RESTORE_CONFIRMATION } from '../constants'; +import { getCurationsBreadcrumbs } from '../utils'; + import { CurationLogic } from './curation_logic'; -import { ManualCuration } from './manual_curation'; +import { PromotedDocuments, OrganicDocuments, HiddenDocuments } from './documents'; +import { ActiveQuerySelect, ManageQueriesModal } from './queries'; +import { AddResultLogic, AddResultFlyout } from './results'; export const Curation: React.FC = () => { const { curationId } = useParams() as { curationId: string }; - const { loadCuration } = useActions(CurationLogic({ curationId })); - const { isAutomated } = useValues(CurationLogic({ curationId })); + const { loadCuration, resetCuration } = useActions(CurationLogic({ curationId })); + const { dataLoading, queries } = useValues(CurationLogic({ curationId })); + const { isFlyoutOpen } = useValues(AddResultLogic); useEffect(() => { loadCuration(); }, [curationId]); - return isAutomated ? : ; + return ( + { + if (window.confirm(RESTORE_CONFIRMATION)) resetCuration(); + }} + > + {RESTORE_DEFAULTS_BUTTON_LABEL} +
    , + ], + }} + isLoading={dataLoading} + > + + + + + + + + + + + + + + + + + + {isFlyoutOpen && } + + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts index 941fd0bf28f96..8fa57e52a26a1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts @@ -55,7 +55,6 @@ describe('CurationLogic', () => { promotedDocumentsLoading: false, hiddenIds: [], hiddenDocumentsLoading: false, - isAutomated: false, }; beforeEach(() => { @@ -266,60 +265,7 @@ describe('CurationLogic', () => { }); }); - describe('selectors', () => { - describe('isAutomated', () => { - it('is true when suggestion status is automated', () => { - mount({ curation: { suggestion: { status: 'automated' } } }); - - expect(CurationLogic.values.isAutomated).toBe(true); - }); - - it('is false when suggestion status is not automated', () => { - for (status of ['pending', 'applied', 'rejected', 'disabled']) { - mount({ curation: { suggestion: { status } } }); - - expect(CurationLogic.values.isAutomated).toBe(false); - } - }); - }); - }); - describe('listeners', () => { - describe('convertToManual', () => { - it('should make an API call and re-load the curation on success', async () => { - http.put.mockReturnValueOnce(Promise.resolve()); - mount({ activeQuery: 'some query' }); - jest.spyOn(CurationLogic.actions, 'loadCuration'); - - CurationLogic.actions.convertToManual(); - await nextTick(); - - expect(http.put).toHaveBeenCalledWith( - '/internal/app_search/engines/some-engine/search_relevance_suggestions', - { - body: JSON.stringify([ - { - query: 'some query', - type: 'curation', - status: 'applied', - }, - ]), - } - ); - expect(CurationLogic.actions.loadCuration).toHaveBeenCalled(); - }); - - it('flashes any error messages', async () => { - http.put.mockReturnValueOnce(Promise.reject('error')); - mount({ activeQuery: 'some query' }); - - CurationLogic.actions.convertToManual(); - await nextTick(); - - expect(flashAPIErrors).toHaveBeenCalledWith('error'); - }); - }); - describe('loadCuration', () => { it('should set dataLoading state', () => { mount({ dataLoading: false }, { curationId: 'cur-123456789' }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts index a9fa5ab8c1048..c49fc76d06874 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts @@ -27,11 +27,9 @@ interface CurationValues { promotedDocumentsLoading: boolean; hiddenIds: string[]; hiddenDocumentsLoading: boolean; - isAutomated: boolean; } interface CurationActions { - convertToManual(): void; loadCuration(): void; onCurationLoad(curation: Curation): { curation: Curation }; updateCuration(): void; @@ -55,7 +53,6 @@ interface CurationProps { export const CurationLogic = kea>({ path: ['enterprise_search', 'app_search', 'curation_logic'], actions: () => ({ - convertToManual: true, loadCuration: true, onCurationLoad: (curation) => ({ curation }), updateCuration: true, @@ -165,34 +162,7 @@ export const CurationLogic = kea ({ - isAutomated: [ - () => [selectors.curation], - (curation: CurationValues['curation']) => { - return curation.suggestion?.status === 'automated'; - }, - ], - }), listeners: ({ actions, values, props }) => ({ - convertToManual: async () => { - const { http } = HttpLogic.values; - const { engineName } = EngineLogic.values; - - try { - await http.put(`/internal/app_search/engines/${engineName}/search_relevance_suggestions`, { - body: JSON.stringify([ - { - query: values.activeQuery, - type: 'curation', - status: 'applied', - }, - ]), - }); - actions.loadCuration(); - } catch (e) { - flashAPIErrors(e); - } - }, loadCuration: async () => { const { http } = HttpLogic.values; const { engineName } = EngineLogic.values; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.test.tsx index b7955cf514079..0624d0063e57d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.test.tsx @@ -13,8 +13,6 @@ import { shallow } from 'enzyme'; import { EuiLoadingContent, EuiEmptyPrompt } from '@elastic/eui'; -import { mountWithIntl } from '../../../../../test_helpers'; - import { DataPanel } from '../../../data_panel'; import { CurationResult } from '../results'; @@ -32,7 +30,6 @@ describe('OrganicDocuments', () => { }, activeQuery: 'world', organicDocumentsLoading: false, - isAutomated: false, }; const actions = { addPromotedId: jest.fn(), @@ -59,13 +56,6 @@ describe('OrganicDocuments', () => { expect(titleText).toEqual('Top organic documents for "world"'); }); - it('shows a title when the curation is manual', () => { - setMockValues({ ...values, isAutomated: false }); - const wrapper = shallow(); - - expect(wrapper.find(DataPanel).prop('subtitle')).toContain('Promote results'); - }); - it('renders a loading state', () => { setMockValues({ ...values, organicDocumentsLoading: true }); const wrapper = shallow(); @@ -73,21 +63,11 @@ describe('OrganicDocuments', () => { expect(wrapper.find(EuiLoadingContent)).toHaveLength(1); }); - describe('empty state', () => { - it('renders', () => { - setMockValues({ ...values, curation: { organic: [] } }); - const wrapper = shallow(); - - expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); - }); - - it('tells the user to modify the query if the curation is manual', () => { - setMockValues({ ...values, curation: { organic: [] }, isAutomated: false }); - const wrapper = shallow(); - const emptyPromptBody = mountWithIntl(<>{wrapper.find(EuiEmptyPrompt).prop('body')}); + it('renders an empty state', () => { + setMockValues({ ...values, curation: { organic: [] } }); + const wrapper = shallow(); - expect(emptyPromptBody.text()).toContain('Add or change'); - }); + expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); }); describe('actions', () => { @@ -106,13 +86,5 @@ describe('OrganicDocuments', () => { expect(actions.addHiddenId).toHaveBeenCalledWith('mock-document-3'); }); - - it('hides actions when the curation is automated', () => { - setMockValues({ ...values, isAutomated: true }); - const wrapper = shallow(); - const result = wrapper.find(CurationResult).first(); - - expect(result.prop('actions')).toEqual([]); - }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.tsx index 7314376a4a7ab..a3a761feefcd2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/organic_documents.tsx @@ -11,7 +11,6 @@ import { useValues, useActions } from 'kea'; import { EuiLoadingContent, EuiEmptyPrompt } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { DataPanel } from '../../../data_panel'; import { Result } from '../../../result/types'; @@ -26,7 +25,7 @@ import { CurationResult } from '../results'; export const OrganicDocuments: React.FC = () => { const { addPromotedId, addHiddenId } = useActions(CurationLogic); - const { curation, activeQuery, isAutomated, organicDocumentsLoading } = useValues(CurationLogic); + const { curation, activeQuery, organicDocumentsLoading } = useValues(CurationLogic); const documents = curation.organic; const hasDocuments = documents.length > 0 && !organicDocumentsLoading; @@ -47,50 +46,36 @@ export const OrganicDocuments: React.FC = () => { )} } - subtitle={!isAutomated && RESULT_ACTIONS_DIRECTIONS} + subtitle={RESULT_ACTIONS_DIRECTIONS} > {hasDocuments ? ( documents.map((document: Result) => ( addHiddenId(document.id.raw), - }, - { - ...PROMOTE_DOCUMENT_ACTION, - onClick: () => addPromotedId(document.id.raw), - }, - ] - } + actions={[ + { + ...HIDE_DOCUMENT_ACTION, + onClick: () => addHiddenId(document.id.raw), + }, + { + ...PROMOTE_DOCUMENT_ACTION, + onClick: () => addPromotedId(document.id.raw), + }, + ]} /> )) ) : organicDocumentsLoading ? ( ) : ( - {' '} - - - ), - }} - /> - } + body={i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.emptyDescription', + { + defaultMessage: + 'No organic results to display. Add or change the active query above.', + } + )} /> )} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.test.tsx index a66b33a47f35c..e0c6de973666c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.test.tsx @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import { setMockValues, setMockActions } from '../../../../../__mocks__/kea_logic'; import React from 'react'; @@ -12,7 +13,6 @@ import { shallow } from 'enzyme'; import { EuiDragDropContext, EuiDraggable, EuiEmptyPrompt, EuiButtonEmpty } from '@elastic/eui'; -import { mountWithIntl } from '../../../../../test_helpers'; import { DataPanel } from '../../../data_panel'; import { CurationResult } from '../results'; @@ -57,50 +57,11 @@ describe('PromotedDocuments', () => { }); }); - it('informs the user documents can be re-ordered if the curation is manual', () => { - setMockValues({ ...values, isAutomated: false }); - const wrapper = shallow(); - const subtitle = mountWithIntl(wrapper.prop('subtitle')); - - expect(subtitle.text()).toContain('Documents can be re-ordered'); - }); - - it('informs the user the curation is managed if the curation is automated', () => { - setMockValues({ ...values, isAutomated: true }); - const wrapper = shallow(); - const subtitle = mountWithIntl(wrapper.prop('subtitle')); - - expect(subtitle.text()).toContain('managed by App Search'); - }); - - describe('empty state', () => { - it('renders', () => { - setMockValues({ ...values, curation: { promoted: [] } }); - const wrapper = shallow(); - - expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); - }); - - it('hide information about starring documents if the curation is automated', () => { - setMockValues({ ...values, curation: { promoted: [] }, isAutomated: true }); - const wrapper = shallow(); - const emptyPromptBody = mountWithIntl(<>{wrapper.find(EuiEmptyPrompt).prop('body')}); - - expect(emptyPromptBody.text()).not.toContain('Star documents'); - }); - }); - - it('hides the panel actions when empty', () => { + it('renders an empty state & hides the panel actions when empty', () => { setMockValues({ ...values, curation: { promoted: [] } }); const wrapper = shallow(); - expect(wrapper.find(DataPanel).prop('action')).toBe(false); - }); - - it('hides the panel actions when the curation is automated', () => { - setMockValues({ ...values, isAutomated: true }); - const wrapper = shallow(); - + expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); expect(wrapper.find(DataPanel).prop('action')).toBe(false); }); @@ -120,14 +81,6 @@ describe('PromotedDocuments', () => { expect(actions.removePromotedId).toHaveBeenCalledWith('mock-document-4'); }); - it('hides demote button for results when the curation is automated', () => { - setMockValues({ ...values, isAutomated: true }); - const wrapper = shallow(); - const result = getDraggableChildren(wrapper.find(EuiDraggable).last()); - - expect(result.prop('actions')).toEqual([]); - }); - it('renders a demote all button that demotes all hidden results', () => { const wrapper = shallow(); const panelActions = shallow(wrapper.find(DataPanel).prop('action') as React.ReactElement); @@ -136,7 +89,7 @@ describe('PromotedDocuments', () => { expect(actions.clearPromotedIds).toHaveBeenCalled(); }); - describe('dragging', () => { + describe('draggging', () => { it('calls setPromotedIds with the reordered list when users are done dragging', () => { const wrapper = shallow(); wrapper.find(EuiDragDropContext).simulate('dragEnd', { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.tsx index e9d9136a45ac6..6b0a02aa2af58 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/documents/promoted_documents.tsx @@ -21,7 +21,6 @@ import { euiDragDropReorder, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; import { DataPanel } from '../../../data_panel'; @@ -30,7 +29,7 @@ import { CurationLogic } from '../curation_logic'; import { AddResultButton, CurationResult, convertToResultFormat } from '../results'; export const PromotedDocuments: React.FC = () => { - const { curation, isAutomated, promotedIds, promotedDocumentsLoading } = useValues(CurationLogic); + const { curation, promotedIds, promotedDocumentsLoading } = useValues(CurationLogic); const documents = curation.promoted; const hasDocuments = documents.length > 0; @@ -54,33 +53,21 @@ export const PromotedDocuments: React.FC = () => { )} } - subtitle={ - isAutomated ? ( - - ) : ( - - ) - } + subtitle={i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.description', + { + defaultMessage: + 'Promoted results appear before organic results. Documents can be re-ordered.', + } + )} action={ - !isAutomated && hasDocuments && ( - + {i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.removeAllButtonLabel', { defaultMessage: 'Demote all' } @@ -102,22 +89,17 @@ export const PromotedDocuments: React.FC = () => { draggableId={document.id} customDragHandle spacing="none" - isDragDisabled={isAutomated} > {(provided) => ( removePromotedId(document.id), - }, - ] - } + actions={[ + { + ...DEMOTE_DOCUMENT_ACTION, + onClick: () => removePromotedId(document.id), + }, + ]} dragHandleProps={provided.dragHandleProps} /> )} @@ -127,22 +109,13 @@ export const PromotedDocuments: React.FC = () => { ) : ( } /> )} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx deleted file mode 100644 index ad9f3bcd64e3e..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx +++ /dev/null @@ -1,94 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import '../../../../__mocks__/shallow_useeffect.mock'; -import { setMockActions, setMockValues } from '../../../../__mocks__/kea_logic'; -import { mockUseParams } from '../../../../__mocks__/react_router'; -import '../../../__mocks__/engine_logic.mock'; - -import React from 'react'; - -import { shallow, ShallowWrapper } from 'enzyme'; - -import { getPageTitle, getPageHeaderActions } from '../../../../test_helpers'; - -jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() })); -import { CurationLogic } from './curation_logic'; - -import { ManualCuration } from './manual_curation'; -import { AddResultFlyout } from './results'; - -describe('ManualCuration', () => { - const values = { - dataLoading: false, - queries: ['query A', 'query B'], - isFlyoutOpen: false, - }; - const actions = { - resetCuration: jest.fn(), - }; - - beforeEach(() => { - jest.clearAllMocks(); - setMockValues(values); - setMockActions(actions); - }); - - it('renders', () => { - const wrapper = shallow(); - - expect(getPageTitle(wrapper)).toEqual('Manage curation'); - expect(wrapper.prop('pageChrome')).toEqual([ - 'Engines', - 'some-engine', - 'Curations', - 'query A, query B', - ]); - }); - - it('renders the add result flyout when open', () => { - setMockValues({ ...values, isFlyoutOpen: true }); - const wrapper = shallow(); - - expect(wrapper.find(AddResultFlyout)).toHaveLength(1); - }); - - it('initializes CurationLogic with a curationId prop from URL param', () => { - mockUseParams.mockReturnValueOnce({ curationId: 'hello-world' }); - shallow(); - - expect(CurationLogic).toHaveBeenCalledWith({ curationId: 'hello-world' }); - }); - - describe('restore defaults button', () => { - let restoreDefaultsButton: ShallowWrapper; - let confirmSpy: jest.SpyInstance; - - beforeAll(() => { - const wrapper = shallow(); - restoreDefaultsButton = getPageHeaderActions(wrapper).childAt(0); - - confirmSpy = jest.spyOn(window, 'confirm'); - }); - - afterAll(() => { - confirmSpy.mockRestore(); - }); - - it('resets the curation upon user confirmation', () => { - confirmSpy.mockReturnValueOnce(true); - restoreDefaultsButton.simulate('click'); - expect(actions.resetCuration).toHaveBeenCalled(); - }); - - it('does not reset the curation if the user cancels', () => { - confirmSpy.mockReturnValueOnce(false); - restoreDefaultsButton.simulate('click'); - expect(actions.resetCuration).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx deleted file mode 100644 index d50575535bf21..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx +++ /dev/null @@ -1,68 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { useParams } from 'react-router-dom'; - -import { useValues, useActions } from 'kea'; - -import { EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; - -import { RESTORE_DEFAULTS_BUTTON_LABEL } from '../../../constants'; -import { AppSearchPageTemplate } from '../../layout'; -import { MANAGE_CURATION_TITLE, RESTORE_CONFIRMATION } from '../constants'; -import { getCurationsBreadcrumbs } from '../utils'; - -import { CurationLogic } from './curation_logic'; -import { PromotedDocuments, OrganicDocuments, HiddenDocuments } from './documents'; -import { ActiveQuerySelect, ManageQueriesModal } from './queries'; -import { AddResultLogic, AddResultFlyout } from './results'; - -export const ManualCuration: React.FC = () => { - const { curationId } = useParams() as { curationId: string }; - const { resetCuration } = useActions(CurationLogic({ curationId })); - const { dataLoading, queries } = useValues(CurationLogic({ curationId })); - const { isFlyoutOpen } = useValues(AddResultLogic); - - return ( - { - if (window.confirm(RESTORE_CONFIRMATION)) resetCuration(); - }} - > - {RESTORE_DEFAULTS_BUTTON_LABEL} -
    , - ], - }} - isLoading={dataLoading} - > - - - - - - - - - - - - - - - - - {isFlyoutOpen && } - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.test.tsx index 5b5c814a24c5b..53cefdd00c670 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.test.tsx @@ -5,43 +5,34 @@ * 2.0. */ -import { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; +import { setMockActions } from '../../../../../__mocks__/kea_logic'; import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, ShallowWrapper } from 'enzyme'; import { EuiButton } from '@elastic/eui'; import { AddResultButton } from './'; describe('AddResultButton', () => { - const values = { - isAutomated: false, - }; - const actions = { openFlyout: jest.fn(), }; - it('renders', () => { - const wrapper = shallow(); + let wrapper: ShallowWrapper; - expect(wrapper.is(EuiButton)).toBe(true); + beforeAll(() => { + setMockActions(actions); + wrapper = shallow(); }); - it('opens the add result flyout on click', () => { - setMockActions(actions); - const wrapper = shallow(); + it('renders', () => { + expect(wrapper.find(EuiButton)).toHaveLength(1); + }); + it('opens the add result flyout on click', () => { wrapper.find(EuiButton).simulate('click'); expect(actions.openFlyout).toHaveBeenCalled(); }); - - it('is disbled when the curation is automated', () => { - setMockValues({ ...values, isAutomated: true }); - const wrapper = shallow(); - - expect(wrapper.find(EuiButton).prop('disabled')).toBe(true); - }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.tsx index f2285064da307..025dda65f4fb8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/add_result_button.tsx @@ -7,21 +7,18 @@ import React from 'react'; -import { useActions, useValues } from 'kea'; +import { useActions } from 'kea'; import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { CurationLogic } from '..'; - import { AddResultLogic } from './'; export const AddResultButton: React.FC = () => { const { openFlyout } = useActions(AddResultLogic); - const { isAutomated } = useValues(CurationLogic); return ( - + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.addResult.buttonLabel', { defaultMessage: 'Add result manually', })} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts index 09c8a487b1b9b..866bf6490ebe8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts @@ -12,9 +12,7 @@ export interface CurationSuggestion { query: string; updated_at: string; promoted: string[]; - status: 'pending' | 'applied' | 'automated' | 'rejected' | 'disabled'; } - export interface Curation { id: string; last_updated: string; @@ -22,7 +20,6 @@ export interface Curation { promoted: CurationResult[]; hidden: CurationResult[]; organic: Result[]; - suggestion?: CurationSuggestion; } export interface CurationsAPIResponse { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_actions.tsx index 5eac38b88937c..52fbee90fe31a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_actions.tsx @@ -18,7 +18,7 @@ interface Props { export const ResultActions: React.FC = ({ actions }) => { return ( - {actions.map(({ onClick, title, iconType, iconColor, disabled }) => ( + {actions.map(({ onClick, title, iconType, iconColor }) => ( = ({ actions }) => { color={iconColor ? iconColor : 'primary'} aria-label={title} title={title} - disabled={disabled} /> ))} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts index d9f1bb394778e..4be3eb137177b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts @@ -41,5 +41,4 @@ export interface ResultAction { title: string; iconType: string; iconColor?: EuiButtonIconColor; - disabled?: boolean; } diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts index 2bdcfb9fe9d58..e6bfaa4a9cca2 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.test.ts @@ -38,35 +38,6 @@ describe('search relevance insights routes', () => { }); }); - describe('PUT /internal/app_search/engines/{name}/search_relevance_suggestions', () => { - const mockRouter = new MockRouter({ - method: 'put', - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions', - }); - - beforeEach(() => { - registerSearchRelevanceSuggestionsRoutes({ - ...mockDependencies, - router: mockRouter.router, - }); - }); - - it('creates a request to enterprise search', () => { - mockRouter.callRoute({ - params: { engineName: 'some-engine' }, - body: { - query: 'some query', - type: 'curation', - status: 'applied', - }, - }); - - expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions', - }); - }); - }); - describe('GET /internal/app_search/engines/{name}/search_relevance_suggestions/settings', () => { const mockRouter = new MockRouter({ method: 'get', diff --git a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts index 8b3b204c24d70..c6fa108a5629e 100644 --- a/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts +++ b/x-pack/plugins/enterprise_search/server/routes/app_search/search_relevance_suggestions.ts @@ -39,20 +39,6 @@ export function registerSearchRelevanceSuggestionsRoutes({ }) ); - router.put( - skipBodyValidation({ - path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions', - validate: { - params: schema.object({ - engineName: schema.string(), - }), - }, - }), - enterpriseSearchRequestHandler.createRequest({ - path: '/api/as/v0/engines/:engineName/search_relevance_suggestions', - }) - ); - router.get( { path: '/internal/app_search/engines/{engineName}/search_relevance_suggestions/settings', diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 62e35bf2aae5f..dcbb8ce26ee4a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9346,9 +9346,11 @@ "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryButtonLabel": "クエリを管理", "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryDescription": "このキュレーションのクエリを編集、追加、削除します。", "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryTitle": "クエリを管理", + "xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.emptyDescription": "表示するオーガニック結果はありません。上記のアクティブなクエリを追加または変更します。", "xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.title": "\"{currentQuery}\"の上位のオーガニックドキュメント", "xpack.enterpriseSearch.appSearch.engine.curations.overview.title": "キュレーションされた結果", "xpack.enterpriseSearch.appSearch.engine.curations.promoteButtonLabel": "この結果を昇格", + "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.description": "昇格された結果はオーガニック結果の前に表示されます。ドキュメントを並べ替えることができます。", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.emptyDescription": "以下のオーガニック結果からドキュメントにスターを付けるか、手動で結果を検索して昇格します。", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.removeAllButtonLabel": "すべて降格", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.title": "昇格されたドキュメント", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2f58cf9c10abf..87c96d1efe48d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9438,9 +9438,11 @@ "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryButtonLabel": "管理查询", "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryDescription": "编辑、添加或移除此策展的查询。", "xpack.enterpriseSearch.appSearch.engine.curations.manageQueryTitle": "管理查询", + "xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.emptyDescription": "没有要显示的有机结果。在上面添加或更改活动查询。", "xpack.enterpriseSearch.appSearch.engine.curations.organicDocuments.title": "“{currentQuery}”的排名靠前有机文档", "xpack.enterpriseSearch.appSearch.engine.curations.overview.title": "已策展结果", "xpack.enterpriseSearch.appSearch.engine.curations.promoteButtonLabel": "提升此结果", + "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.description": "提升结果显示在有机结果之前。可以重新排列文档。", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.emptyDescription": "使用星号标记来自下面有机结果的文档或手动搜索或提升结果。", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.removeAllButtonLabel": "全部降低", "xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.title": "提升文档", From 5216442d6cd499bef77a064875363cc21bf36fc0 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Mon, 4 Oct 2021 21:07:49 -0400 Subject: [PATCH 81/98] [ci] Add branch to failed test reporter github comments (#113860) --- .../report_failure.test.ts | 10 ++++++---- .../failed_tests_reporter/report_failure.ts | 18 ++++++++++++++---- .../run_failed_tests_reporter_cli.ts | 11 ++++++++--- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/packages/kbn-test/src/failed_tests_reporter/report_failure.test.ts b/packages/kbn-test/src/failed_tests_reporter/report_failure.test.ts index b2cc8d6d8ffb6..b2fd3de6bbbbc 100644 --- a/packages/kbn-test/src/failed_tests_reporter/report_failure.test.ts +++ b/packages/kbn-test/src/failed_tests_reporter/report_failure.test.ts @@ -26,7 +26,8 @@ describe('createFailureIssue()', () => { time: '2018-01-01T01:00:00Z', likelyIrrelevant: false, }, - api + api, + 'main' ); expect(api.createIssue).toMatchInlineSnapshot(` @@ -40,7 +41,7 @@ describe('createFailureIssue()', () => { this is the failure text \`\`\` - First failure: [CI Build](https://build-url) + First failure: [CI Build - main](https://build-url) ", Array [ @@ -74,7 +75,8 @@ describe('updateFailureIssue()', () => { " `, }, - api + api, + 'main' ); expect(api.editIssueBodyAndEnsureOpen).toMatchInlineSnapshot(` @@ -100,7 +102,7 @@ describe('updateFailureIssue()', () => { "calls": Array [ Array [ 1234, - "New failure: [CI Build](https://build-url)", + "New failure: [CI Build - main](https://build-url)", ], ], "results": Array [ diff --git a/packages/kbn-test/src/failed_tests_reporter/report_failure.ts b/packages/kbn-test/src/failed_tests_reporter/report_failure.ts index c881bc39abf61..c44fae560156a 100644 --- a/packages/kbn-test/src/failed_tests_reporter/report_failure.ts +++ b/packages/kbn-test/src/failed_tests_reporter/report_failure.ts @@ -10,7 +10,12 @@ import { TestFailure } from './get_failures'; import { GithubIssueMini, GithubApi } from './github_api'; import { getIssueMetadata, updateIssueMetadata } from './issue_metadata'; -export async function createFailureIssue(buildUrl: string, failure: TestFailure, api: GithubApi) { +export async function createFailureIssue( + buildUrl: string, + failure: TestFailure, + api: GithubApi, + branch: string +) { const title = `Failing test: ${failure.classname} - ${failure.name}`; const body = updateIssueMetadata( @@ -21,7 +26,7 @@ export async function createFailureIssue(buildUrl: string, failure: TestFailure, failure.failure, '```', '', - `First failure: [CI Build](${buildUrl})`, + `First failure: [CI Build - ${branch}](${buildUrl})`, ].join('\n'), { 'test.class': failure.classname, @@ -33,7 +38,12 @@ export async function createFailureIssue(buildUrl: string, failure: TestFailure, return await api.createIssue(title, body, ['failed-test']); } -export async function updateFailureIssue(buildUrl: string, issue: GithubIssueMini, api: GithubApi) { +export async function updateFailureIssue( + buildUrl: string, + issue: GithubIssueMini, + api: GithubApi, + branch: string +) { // Increment failCount const newCount = getIssueMetadata(issue.body, 'test.failCount', 0) + 1; const newBody = updateIssueMetadata(issue.body, { @@ -41,7 +51,7 @@ export async function updateFailureIssue(buildUrl: string, issue: GithubIssueMin }); await api.editIssueBodyAndEnsureOpen(issue.number, newBody); - await api.addIssueComment(issue.number, `New failure: [CI Build](${buildUrl})`); + await api.addIssueComment(issue.number, `New failure: [CI Build - ${branch}](${buildUrl})`); return newCount; } diff --git a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts index 6c88b7408b628..31cd43eae4141 100644 --- a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts +++ b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts @@ -37,8 +37,8 @@ export function runFailedTestsReporterCli() { ); } + let branch: string = ''; if (updateGithub) { - let branch: string = ''; let isPr = false; if (process.env.BUILDKITE === 'true') { @@ -139,7 +139,12 @@ export function runFailedTestsReporterCli() { } if (existingIssue) { - const newFailureCount = await updateFailureIssue(buildUrl, existingIssue, githubApi); + const newFailureCount = await updateFailureIssue( + buildUrl, + existingIssue, + githubApi, + branch + ); const url = existingIssue.html_url; pushMessage(`Test has failed ${newFailureCount - 1} times on tracked branches: ${url}`); if (updateGithub) { @@ -148,7 +153,7 @@ export function runFailedTestsReporterCli() { continue; } - const newIssue = await createFailureIssue(buildUrl, failure, githubApi); + const newIssue = await createFailureIssue(buildUrl, failure, githubApi, branch); pushMessage('Test has not failed recently on tracked branches'); if (updateGithub) { pushMessage(`Created new issue: ${newIssue.html_url}`); From 083eb2487674bb7a6f02303e960f930edfedc7c2 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Mon, 4 Oct 2021 21:08:01 -0400 Subject: [PATCH 82/98] [buildkite] Speed up OSS misc tests by removing TS refs and bumping instance (#113855) --- .buildkite/pipelines/hourly.yml | 2 +- .buildkite/pipelines/pull_request/base.yml | 2 +- .buildkite/scripts/steps/functional/oss_misc.sh | 3 --- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.buildkite/pipelines/hourly.yml b/.buildkite/pipelines/hourly.yml index 7aa8528dc3d9a..0edba11836fcd 100644 --- a/.buildkite/pipelines/hourly.yml +++ b/.buildkite/pipelines/hourly.yml @@ -98,7 +98,7 @@ steps: - command: .buildkite/scripts/steps/functional/oss_misc.sh label: 'OSS Misc Functional Tests' agents: - queue: ci-group-4d + queue: ci-group-6 depends_on: build timeout_in_minutes: 120 retry: diff --git a/.buildkite/pipelines/pull_request/base.yml b/.buildkite/pipelines/pull_request/base.yml index 1da3f654b7253..404bfb273b6f7 100644 --- a/.buildkite/pipelines/pull_request/base.yml +++ b/.buildkite/pipelines/pull_request/base.yml @@ -96,7 +96,7 @@ steps: - command: .buildkite/scripts/steps/functional/oss_misc.sh label: 'OSS Misc Functional Tests' agents: - queue: ci-group-4d + queue: ci-group-6 depends_on: build timeout_in_minutes: 120 retry: diff --git a/.buildkite/scripts/steps/functional/oss_misc.sh b/.buildkite/scripts/steps/functional/oss_misc.sh index a57a457ca189a..48be6669f321b 100755 --- a/.buildkite/scripts/steps/functional/oss_misc.sh +++ b/.buildkite/scripts/steps/functional/oss_misc.sh @@ -2,9 +2,6 @@ set -euo pipefail -# Required, at least for kbn_sample_panel_action -export BUILD_TS_REFS_DISABLE=false - source .buildkite/scripts/steps/functional/common.sh # Required, at least for plugin_functional tests From 7446e0755ad351668a35ab2dfe9801fabf007b6a Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Mon, 4 Oct 2021 21:43:35 -0400 Subject: [PATCH 83/98] [Security Solution][Timelines] - Timeline resolve api (#113157) --- .../security_solution/common/constants.ts | 1 + .../common/types/timeline/index.ts | 42 +++--- .../public/timelines/containers/api.ts | 35 +++++ .../timeline/__mocks__/resolve_timeline.ts | 124 +++++++++++++++++ .../lib/timeline/routes/timelines/index.ts | 1 + .../timelines/resolve_timeline/index.ts | 68 ++++++++++ .../saved_object/timelines/index.test.ts | 69 +++++++++- .../timeline/saved_object/timelines/index.ts | 101 +++++++------- .../security_solution/server/routes/index.ts | 2 + .../apis/security_solution/timeline.ts | 125 ++++++++++++++---- 10 files changed, 475 insertions(+), 93 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/lib/timeline/__mocks__/resolve_timeline.ts create mode 100644 x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index e91f74320c026..9ac24d96d329f 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -247,6 +247,7 @@ export const DETECTION_ENGINE_RULES_STATUS_URL = `${DETECTION_ENGINE_RULES_URL}/ export const DETECTION_ENGINE_PREPACKAGED_RULES_STATUS_URL = `${DETECTION_ENGINE_RULES_URL}/prepackaged/_status`; export const DETECTION_ENGINE_RULES_BULK_ACTION = `${DETECTION_ENGINE_RULES_URL}/_bulk_action`; +export const TIMELINE_RESOLVE_URL = '/api/timeline/resolve'; export const TIMELINE_URL = '/api/timeline'; export const TIMELINES_URL = '/api/timelines'; export const TIMELINE_FAVORITE_URL = '/api/timeline/_favorite'; diff --git a/x-pack/plugins/security_solution/common/types/timeline/index.ts b/x-pack/plugins/security_solution/common/types/timeline/index.ts index cc676541e2c24..c0046f7535db8 100644 --- a/x-pack/plugins/security_solution/common/types/timeline/index.ts +++ b/x-pack/plugins/security_solution/common/types/timeline/index.ts @@ -337,21 +337,6 @@ export const TimelineIdLiteralRt = runtimeTypes.union([ export type TimelineIdLiteral = runtimeTypes.TypeOf; -/** - * Timeline Saved object type with metadata - */ - -export const TimelineSavedObjectRuntimeType = runtimeTypes.intersection([ - runtimeTypes.type({ - id: runtimeTypes.string, - attributes: SavedTimelineRuntimeType, - version: runtimeTypes.string, - }), - runtimeTypes.partial({ - savedObjectId: runtimeTypes.string, - }), -]); - export const TimelineSavedToReturnObjectRuntimeType = runtimeTypes.intersection([ SavedTimelineRuntimeType, runtimeTypes.type({ @@ -379,6 +364,33 @@ export const SingleTimelineResponseType = runtimeTypes.type({ export type SingleTimelineResponse = runtimeTypes.TypeOf; +/** Resolved Timeline Response */ +export const ResolvedTimelineSavedObjectToReturnObjectRuntimeType = runtimeTypes.intersection([ + runtimeTypes.type({ + timeline: TimelineSavedToReturnObjectRuntimeType, + outcome: runtimeTypes.union([ + runtimeTypes.literal('exactMatch'), + runtimeTypes.literal('aliasMatch'), + runtimeTypes.literal('conflict'), + ]), + }), + runtimeTypes.partial({ + alias_target_id: runtimeTypes.string, + }), +]); + +export type ResolvedTimelineWithOutcomeSavedObject = runtimeTypes.TypeOf< + typeof ResolvedTimelineSavedObjectToReturnObjectRuntimeType +>; + +export const ResolvedSingleTimelineResponseType = runtimeTypes.type({ + data: ResolvedTimelineSavedObjectToReturnObjectRuntimeType, +}); + +export type SingleTimelineResolveResponse = runtimeTypes.TypeOf< + typeof ResolvedSingleTimelineResponseType +>; + /** * All Timeline Saved object type with metadata */ diff --git a/x-pack/plugins/security_solution/public/timelines/containers/api.ts b/x-pack/plugins/security_solution/public/timelines/containers/api.ts index 171b3fedd0e64..789c942d0e29a 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/api.ts +++ b/x-pack/plugins/security_solution/public/timelines/containers/api.ts @@ -22,11 +22,13 @@ import { ResponseFavoriteTimeline, AllTimelinesResponse, SingleTimelineResponse, + SingleTimelineResolveResponse, allTimelinesResponse, responseFavoriteTimeline, GetTimelinesArgs, SingleTimelineResponseType, TimelineType, + ResolvedSingleTimelineResponseType, } from '../../../common/types/timeline'; import { TIMELINE_URL, @@ -34,6 +36,7 @@ import { TIMELINE_IMPORT_URL, TIMELINE_EXPORT_URL, TIMELINE_PREPACKAGED_URL, + TIMELINE_RESOLVE_URL, TIMELINES_URL, TIMELINE_FAVORITE_URL, } from '../../../common/constants'; @@ -71,6 +74,12 @@ const decodeSingleTimelineResponse = (respTimeline?: SingleTimelineResponse) => fold(throwErrors(createToasterPlainError), identity) ); +const decodeResolvedSingleTimelineResponse = (respTimeline?: SingleTimelineResolveResponse) => + pipe( + ResolvedSingleTimelineResponseType.decode(respTimeline), + fold(throwErrors(createToasterPlainError), identity) + ); + const decodeAllTimelinesResponse = (respTimeline: AllTimelinesResponse) => pipe( allTimelinesResponse.decode(respTimeline), @@ -305,6 +314,19 @@ export const getTimeline = async (id: string) => { return decodeSingleTimelineResponse(response); }; +export const resolveTimeline = async (id: string) => { + const response = await KibanaServices.get().http.get( + TIMELINE_RESOLVE_URL, + { + query: { + id, + }, + } + ); + + return decodeResolvedSingleTimelineResponse(response); +}; + export const getTimelineTemplate = async (templateTimelineId: string) => { const response = await KibanaServices.get().http.get(TIMELINE_URL, { query: { @@ -315,6 +337,19 @@ export const getTimelineTemplate = async (templateTimelineId: string) => { return decodeSingleTimelineResponse(response); }; +export const getResolvedTimelineTemplate = async (templateTimelineId: string) => { + const response = await KibanaServices.get().http.get( + TIMELINE_RESOLVE_URL, + { + query: { + template_timeline_id: templateTimelineId, + }, + } + ); + + return decodeResolvedSingleTimelineResponse(response); +}; + export const getAllTimelines = async (args: GetTimelinesArgs, abortSignal: AbortSignal) => { const response = await KibanaServices.get().http.fetch(TIMELINES_URL, { method: 'GET', diff --git a/x-pack/plugins/security_solution/server/lib/timeline/__mocks__/resolve_timeline.ts b/x-pack/plugins/security_solution/server/lib/timeline/__mocks__/resolve_timeline.ts new file mode 100644 index 0000000000000..a6508f609d9d6 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/timeline/__mocks__/resolve_timeline.ts @@ -0,0 +1,124 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TimelineStatus, TimelineType } from '../../../../common/types/timeline'; +import { ResolvedTimelineWithOutcomeSavedObject } from './../../../../common/types/timeline/index'; + +export const mockResolvedSavedObject = { + saved_object: { + id: '760d3d20-2142-11ec-a46f-051cb8e3154c', + type: 'siem-ui-timeline', + namespaces: ['default'], + updated_at: '2021-09-29T16:29:48.478Z', + version: 'WzYxNzc0LDFd', + attributes: { + columns: [], + dataProviders: [], + description: '', + eventType: 'all', + filters: [], + kqlMode: 'filter', + timelineType: 'default', + kqlQuery: { + filterQuery: null, + }, + title: 'Test Timeline', + sort: [ + { + columnType: 'date', + sortDirection: 'desc', + columnId: '@timestamp', + }, + ], + status: 'active', + created: 1632932987378, + createdBy: 'tester', + updated: 1632932988422, + updatedBy: 'tester', + templateTimelineId: null, + templateTimelineVersion: null, + excludedRowRendererIds: [], + dateRange: { + start: '2021-09-29T04:00:00.000Z', + end: '2021-09-30T03:59:59.999Z', + }, + indexNames: [], + eqlOptions: { + tiebreakerField: '', + size: 100, + query: '', + eventCategoryField: 'event.category', + timestampField: '@timestamp', + }, + }, + references: [], + migrationVersion: { + 'siem-ui-timeline': '7.16.0', + }, + coreMigrationVersion: '8.0.0', + }, + outcome: 'aliasMatch', + alias_target_id: 'new-saved-object-id', +}; + +export const mockResolvedTimeline = { + savedObjectId: '760d3d20-2142-11ec-a46f-051cb8e3154c', + version: 'WzY1NDcxLDFd', + columns: [], + dataProviders: [], + description: '', + eventType: 'all', + filters: [], + kqlMode: 'filter', + timelineType: TimelineType.default, + kqlQuery: { filterQuery: null }, + title: 'Test Timeline', + sort: [ + { + columnType: 'date', + sortDirection: 'desc', + columnId: '@timestamp', + }, + ], + status: TimelineStatus.active, + created: 1632932987378, + createdBy: 'tester', + updated: 1632932988422, + updatedBy: 'tester', + templateTimelineId: null, + templateTimelineVersion: null, + excludedRowRendererIds: [], + dateRange: { + start: '2021-09-29T04:00:00.000Z', + end: '2021-09-30T03:59:59.999Z', + }, + indexNames: [], + eqlOptions: { + tiebreakerField: '', + size: 100, + query: '', + eventCategoryField: 'event.category', + timestampField: '@timestamp', + }, + savedQueryId: null, +}; + +export const mockPopulatedTimeline = { + ...mockResolvedTimeline, + eventIdToNoteIds: [], + favorite: [], + noteIds: [], + notes: [], + pinnedEventIds: [], + pinnedEventsSaveObject: [], +}; + +export const mockResolveTimelineResponse: ResolvedTimelineWithOutcomeSavedObject = { + timeline: mockPopulatedTimeline, + outcome: 'aliasMatch', + alias_target_id: 'new-saved-object-id', +}; diff --git a/x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/index.ts b/x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/index.ts index ebd0dbba7d197..ba20633a65145 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/index.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/index.ts @@ -12,3 +12,4 @@ export { getTimelinesRoute } from './get_timelines'; export { importTimelinesRoute } from './import_timelines'; export { patchTimelinesRoute } from './patch_timelines'; export { persistFavoriteRoute } from './persist_favorite'; +export { resolveTimelineRoute } from './resolve_timeline'; diff --git a/x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts b/x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts new file mode 100644 index 0000000000000..04aa6fef3a372 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/timeline/routes/timelines/resolve_timeline/index.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { transformError } from '@kbn/securitysolution-es-utils'; +import type { SecuritySolutionPluginRouter } from '../../../../../types'; + +import { TIMELINE_RESOLVE_URL } from '../../../../../../common/constants'; + +import { ConfigType } from '../../../../..'; +import { SetupPlugins } from '../../../../../plugin'; +import { buildRouteValidationWithExcess } from '../../../../../utils/build_validation/route_validation'; + +import { buildSiemResponse } from '../../../../detection_engine/routes/utils'; + +import { buildFrameworkRequest } from '../../../utils/common'; +import { getTimelineQuerySchema } from '../../../schemas/timelines'; +import { getTimelineTemplateOrNull, resolveTimelineOrNull } from '../../../saved_object/timelines'; + +export const resolveTimelineRoute = ( + router: SecuritySolutionPluginRouter, + config: ConfigType, + security: SetupPlugins['security'] +) => { + router.get( + { + path: TIMELINE_RESOLVE_URL, + validate: { + query: buildRouteValidationWithExcess(getTimelineQuerySchema), + }, + options: { + tags: ['access:securitySolution'], + }, + }, + async (context, request, response) => { + try { + const frameworkRequest = await buildFrameworkRequest(context, security, request); + const query = request.query ?? {}; + const { template_timeline_id: templateTimelineId, id } = query; + + let res = null; + + if (templateTimelineId != null && id == null) { + // Template timelineId is not a SO id, so it does not need to be updated to use resolve + res = await getTimelineTemplateOrNull(frameworkRequest, templateTimelineId); + } else if (templateTimelineId == null && id != null) { + // In the event the objectId is defined, run the resolve call + res = await resolveTimelineOrNull(frameworkRequest, id); + } else { + throw new Error('please provide id or template_timeline_id'); + } + + return response.ok({ body: res ? { data: res } : {} }); + } catch (err) { + const error = transformError(err); + const siemResponse = buildSiemResponse(response); + + return siemResponse.error({ + body: error.message, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.test.ts b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.test.ts index f7e4de69097f1..112796df527fa 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.test.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.test.ts @@ -8,11 +8,24 @@ import { FrameworkRequest } from '../../../framework'; import { mockGetTimelineValue, mockSavedObject } from '../../__mocks__/import_timelines'; -import { convertStringToBase64, getExistingPrepackagedTimelines, getAllTimeline } from '.'; +import { + convertStringToBase64, + getExistingPrepackagedTimelines, + getAllTimeline, + resolveTimelineOrNull, +} from '.'; import { convertSavedObjectToSavedTimeline } from './convert_saved_object_to_savedtimeline'; import { getNotesByTimelineId } from '../notes/saved_object'; import { getAllPinnedEventsByTimelineId } from '../pinned_events'; -import { AllTimelinesResponse } from '../../../../../common/types/timeline'; +import { + AllTimelinesResponse, + ResolvedTimelineWithOutcomeSavedObject, +} from '../../../../../common/types/timeline'; +import { + mockResolvedSavedObject, + mockResolvedTimeline, + mockResolveTimelineResponse, +} from '../../__mocks__/resolve_timeline'; jest.mock('./convert_saved_object_to_savedtimeline', () => ({ convertSavedObjectToSavedTimeline: jest.fn(), @@ -151,7 +164,7 @@ describe('saved_object', () => { (getAllPinnedEventsByTimelineId as jest.Mock).mockClear(); }); - test('should send correct options if no filters applys', async () => { + test('should send correct options if no filters applies', async () => { expect(mockFindSavedObject.mock.calls[0][0]).toEqual({ filter: 'not siem-ui-timeline.attributes.status: draft', page: pageInfo.pageIndex, @@ -226,7 +239,7 @@ describe('saved_object', () => { ); }); - test('should retuen correct result', async () => { + test('should return correct result', async () => { expect(result).toEqual({ totalCount: 1, customTemplateTimelineCount: 0, @@ -248,4 +261,52 @@ describe('saved_object', () => { }); }); }); + + describe('resolveTimelineOrNull', () => { + let mockResolveSavedObject: jest.Mock; + let mockRequest: FrameworkRequest; + let result: ResolvedTimelineWithOutcomeSavedObject | null = null; + beforeEach(async () => { + (convertSavedObjectToSavedTimeline as jest.Mock).mockReturnValue(mockResolvedTimeline); + mockResolveSavedObject = jest.fn().mockReturnValue(mockResolvedSavedObject); + mockRequest = { + user: { + username: 'username', + }, + context: { + core: { + savedObjects: { + client: { + resolve: mockResolveSavedObject, + }, + }, + }, + }, + } as unknown as FrameworkRequest; + + result = await resolveTimelineOrNull(mockRequest, '760d3d20-2142-11ec-a46f-051cb8e3154c'); + }); + + afterEach(() => { + mockResolveSavedObject.mockClear(); + (getNotesByTimelineId as jest.Mock).mockClear(); + (getAllPinnedEventsByTimelineId as jest.Mock).mockClear(); + }); + + test('should call getNotesByTimelineId', async () => { + expect((getNotesByTimelineId as jest.Mock).mock.calls[0][1]).toEqual( + mockResolvedSavedObject.saved_object.id + ); + }); + + test('should call getAllPinnedEventsByTimelineId', async () => { + expect((getAllPinnedEventsByTimelineId as jest.Mock).mock.calls[0][1]).toEqual( + mockResolvedSavedObject.saved_object.id + ); + }); + + test('should return the timeline with resolve attributes', async () => { + expect(result).toEqual(mockResolveTimelineResponse); + }); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.ts b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.ts index b3ed5675cea31..cc28e0c9eb853 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/timelines/index.ts @@ -30,6 +30,7 @@ import { TimelineStatus, TimelineResult, TimelineWithoutExternalRefs, + ResolvedTimelineWithOutcomeSavedObject, } from '../../../../../common/types/timeline'; import { FrameworkRequest } from '../../../framework'; import * as note from '../notes/saved_object'; @@ -52,49 +53,6 @@ export interface ResponseTemplateTimeline { templateTimeline: TimelineResult; } -export interface Timeline { - getTimeline: ( - request: FrameworkRequest, - timelineId: string, - timelineType?: TimelineTypeLiteralWithNull - ) => Promise; - - getAllTimeline: ( - request: FrameworkRequest, - onlyUserFavorite: boolean | null, - pageInfo: PageInfoTimeline, - search: string | null, - sort: SortTimeline | null, - status: TimelineStatusLiteralWithNull, - timelineType: TimelineTypeLiteralWithNull - ) => Promise; - - persistFavorite: ( - request: FrameworkRequest, - timelineId: string | null, - templateTimelineId: string | null, - templateTimelineVersion: number | null, - timelineType: TimelineType - ) => Promise; - - persistTimeline: ( - request: FrameworkRequest, - timelineId: string | null, - version: string | null, - timeline: SavedTimeline, - isImmutable?: boolean - ) => Promise; - - deleteTimeline: (request: FrameworkRequest, timelineIds: string[]) => Promise; - convertStringToBase64: (text: string) => string; - timelineWithReduxProperties: ( - notes: NoteSavedObject[], - pinnedEvents: PinnedEventSavedObject[], - timeline: TimelineSavedObject, - userName: string - ) => TimelineSavedObject; -} - export const getTimeline = async ( request: FrameworkRequest, timelineId: string, @@ -132,6 +90,18 @@ export const getTimelineOrNull = async ( return timeline; }; +export const resolveTimelineOrNull = async ( + frameworkRequest: FrameworkRequest, + savedObjectId: string +): Promise => { + let resolvedTimeline = null; + try { + resolvedTimeline = await resolveSavedTimeline(frameworkRequest, savedObjectId); + // eslint-disable-next-line no-empty + } catch (e) {} + return resolvedTimeline; +}; + export const getTimelineByTemplateTimelineId = async ( request: FrameworkRequest, templateTimelineId: string @@ -584,6 +554,44 @@ export const deleteTimeline = async (request: FrameworkRequest, timelineIds: str ); }; +const resolveBasicSavedTimeline = async (request: FrameworkRequest, timelineId: string) => { + const savedObjectsClient = request.context.core.savedObjects.client; + const { saved_object: savedObject, ...resolveAttributes } = + await savedObjectsClient.resolve( + timelineSavedObjectType, + timelineId + ); + + const populatedTimeline = timelineFieldsMigrator.populateFieldsFromReferences(savedObject); + + return { + resolvedTimelineSavedObject: convertSavedObjectToSavedTimeline(populatedTimeline), + ...resolveAttributes, + }; +}; + +const resolveSavedTimeline = async (request: FrameworkRequest, timelineId: string) => { + const userName = request.user?.username ?? UNAUTHENTICATED_USER; + + const { resolvedTimelineSavedObject, ...resolveAttributes } = await resolveBasicSavedTimeline( + request, + timelineId + ); + + const timelineWithNotesAndPinnedEvents = await Promise.all([ + note.getNotesByTimelineId(request, resolvedTimelineSavedObject.savedObjectId), + pinnedEvent.getAllPinnedEventsByTimelineId(request, resolvedTimelineSavedObject.savedObjectId), + resolvedTimelineSavedObject, + ]); + + const [notes, pinnedEvents, timeline] = timelineWithNotesAndPinnedEvents; + + return { + timeline: timelineWithReduxProperties(notes, pinnedEvents, timeline, userName), + ...resolveAttributes, + }; +}; + const getBasicSavedTimeline = async (request: FrameworkRequest, timelineId: string) => { const savedObjectsClient = request.context.core.savedObjects.client; const savedObject = await savedObjectsClient.get( @@ -646,13 +654,6 @@ const getAllSavedTimeline = async (request: FrameworkRequest, options: SavedObje export const convertStringToBase64 = (text: string): string => Buffer.from(text).toString('base64'); -// we have to use any here because the SavedObjectAttributes interface is like below -// export interface SavedObjectAttributes { -// [key: string]: SavedObjectAttributes | string | number | boolean | null; -// } -// then this interface does not allow types without index signature -// this is limiting us with our type for now so the easy way was to use any - export const timelineWithReduxProperties = ( notes: NoteSavedObject[], pinnedEvents: PinnedEventSavedObject[], diff --git a/x-pack/plugins/security_solution/server/routes/index.ts b/x-pack/plugins/security_solution/server/routes/index.ts index 95ec33868f52d..c4e50ae4f5a7b 100644 --- a/x-pack/plugins/security_solution/server/routes/index.ts +++ b/x-pack/plugins/security_solution/server/routes/index.ts @@ -45,6 +45,7 @@ import { importTimelinesRoute, patchTimelinesRoute, persistFavoriteRoute, + resolveTimelineRoute, } from '../lib/timeline/routes/timelines'; import { getDraftTimelinesRoute } from '../lib/timeline/routes/draft_timelines/get_draft_timelines'; import { cleanDraftTimelinesRoute } from '../lib/timeline/routes/draft_timelines/clean_draft_timelines'; @@ -99,6 +100,7 @@ export const initRoutes = ( exportTimelinesRoute(router, config, security); getDraftTimelinesRoute(router, config, security); getTimelineRoute(router, config, security); + resolveTimelineRoute(router, config, security); getTimelinesRoute(router, config, security); cleanDraftTimelinesRoute(router, config, security); deleteTimelinesRoute(router, config, security); diff --git a/x-pack/test/api_integration/apis/security_solution/timeline.ts b/x-pack/test/api_integration/apis/security_solution/timeline.ts index 10e082cf44004..f586719e6015e 100644 --- a/x-pack/test/api_integration/apis/security_solution/timeline.ts +++ b/x-pack/test/api_integration/apis/security_solution/timeline.ts @@ -16,44 +16,121 @@ import { createBasicTimeline, createBasicTimelineTemplate } from './saved_object export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); describe('Timeline', () => { - it('Make sure that we get Timeline data', async () => { - const titleToSaved = 'hello timeline'; - await createBasicTimeline(supertest, titleToSaved); + describe('timelines', () => { + it('Make sure that we get Timeline data', async () => { + const titleToSaved = 'hello timeline'; + await createBasicTimeline(supertest, titleToSaved); - const resp = await supertest.get('/api/timelines').set('kbn-xsrf', 'true'); + const resp = await supertest.get('/api/timelines').set('kbn-xsrf', 'true'); - const timelines = resp.body.timeline; + const timelines = resp.body.timeline; - expect(timelines.length).to.greaterThan(0); - }); + expect(timelines.length).to.greaterThan(0); + }); + + it('Make sure that pagination is working in Timeline query', async () => { + const titleToSaved = 'hello timeline'; + await createBasicTimeline(supertest, titleToSaved); + + const resp = await supertest + .get('/api/timelines?page_size=1&page_index=1') + .set('kbn-xsrf', 'true'); - it('Make sure that pagination is working in Timeline query', async () => { - const titleToSaved = 'hello timeline'; - await createBasicTimeline(supertest, titleToSaved); + const timelines = resp.body.timeline; - const resp = await supertest - .get('/api/timelines?page_size=1&page_index=1') - .set('kbn-xsrf', 'true'); + expect(timelines.length).to.equal(1); + }); - const timelines = resp.body.timeline; + it('Make sure that we get Timeline template data', async () => { + const titleToSaved = 'hello timeline template'; + await createBasicTimelineTemplate(supertest, titleToSaved); - expect(timelines.length).to.equal(1); + const resp = await supertest + .get('/api/timelines?timeline_type=template') + .set('kbn-xsrf', 'true'); + + const templates: SavedTimeline[] = resp.body.timeline; + + expect(templates.length).to.greaterThan(0); + expect(templates.filter((t) => t.timelineType === TimelineType.default).length).to.equal(0); + }); }); + describe('resolve timeline', () => { + before(async () => { + await esArchiver.load( + 'x-pack/test/functional/es_archives/security_solution/timelines/7.15.0' + ); + }); + + after(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/timelines/7.15.0' + ); + }); + + it('should return outcome exactMatch when the id is unchanged', async () => { + const resp = await supertest + .get('/api/timeline/resolve') + .query({ id: '8dc70950-1012-11ec-9ad3-2d7c6600c0f7' }); + + expect(resp.body.data.outcome).to.be('exactMatch'); + expect(resp.body.data.alias_target_id).to.be(undefined); + expect(resp.body.data.timeline.title).to.be('Awesome Timeline'); + }); + + describe('notes', () => { + it('should return notes with eventId', async () => { + const resp = await supertest + .get('/api/timeline/resolve') + .query({ id: '6484cc90-126e-11ec-83d2-db1096c73738' }); + + expect(resp.body.data.timeline.notes[0].eventId).to.be('Edo00XsBEVtyvU-8LGNe'); + }); + + it('should return notes with the timelineId matching request id', async () => { + const resp = await supertest + .get('/api/timeline/resolve') + .query({ id: '6484cc90-126e-11ec-83d2-db1096c73738' }); + + expect(resp.body.data.timeline.notes[0].timelineId).to.be( + '6484cc90-126e-11ec-83d2-db1096c73738' + ); + expect(resp.body.data.timeline.notes[1].timelineId).to.be( + '6484cc90-126e-11ec-83d2-db1096c73738' + ); + }); + }); - it('Make sure that we get Timeline template data', async () => { - const titleToSaved = 'hello timeline template'; - await createBasicTimelineTemplate(supertest, titleToSaved); + describe('pinned events', () => { + it('should pinned events with eventId', async () => { + const resp = await supertest + .get('/api/timeline/resolve') + .query({ id: '6484cc90-126e-11ec-83d2-db1096c73738' }); - const resp = await supertest - .get('/api/timelines?timeline_type=template') - .set('kbn-xsrf', 'true'); + expect(resp.body.data.timeline.pinnedEventsSaveObject[0].eventId).to.be( + 'DNo00XsBEVtyvU-8LGNe' + ); + expect(resp.body.data.timeline.pinnedEventsSaveObject[1].eventId).to.be( + 'Edo00XsBEVtyvU-8LGNe' + ); + }); - const templates: SavedTimeline[] = resp.body.timeline; + it('should return pinned events with the timelineId matching request id', async () => { + const resp = await supertest + .get('/api/timeline/resolve') + .query({ id: '6484cc90-126e-11ec-83d2-db1096c73738' }); - expect(templates.length).to.greaterThan(0); - expect(templates.filter((t) => t.timelineType === TimelineType.default).length).to.equal(0); + expect(resp.body.data.timeline.pinnedEventsSaveObject[0].timelineId).to.be( + '6484cc90-126e-11ec-83d2-db1096c73738' + ); + expect(resp.body.data.timeline.pinnedEventsSaveObject[1].timelineId).to.be( + '6484cc90-126e-11ec-83d2-db1096c73738' + ); + }); + }); }); }); } From 8f7dd3f5cb8b2d2cbd1d69d0676eca8d7b83fabb Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Mon, 4 Oct 2021 22:43:54 -0500 Subject: [PATCH 84/98] [Workplace Search] Add read views for Source Sync Scheduling (#113199) * Add constants Placeholders in place whle content is being written * Update mock to match API and add types The weird typing around `DaysOfWeek` was taken from this SO answer to get an array from a union type: https://stackoverflow.com/a/45486495/1949235 * Add routes and stubbed docs urls * Add components for list items These components are the repeatable components in each of the frequency tabs. - FrequencyItem - BlockedWindowItem Form changes methods are stubbed for now. * Add tab components for Frequency page * Add Frequency page component * Add synchronization logic This is just the basics. More will be added in a future PR * Add Synchronization op-level page * Add Synchronization router and subnav * Add `Objects and assets` page stub This is merely a placeholder page so the routes could be built out. Section will be moved from settings in a future PR * Add name and new nav item to source sub nav * Add SynchronizationRouter nav to Source router * Fix a couple of typos * Add callout and disable subnav for disabled sync This was added to the API after the rest of the work was done, so adding it here. https://github.com/elastic/workplace-search-team/issues/2043 * Update frequency item to account for edge case There was a very long discussion about the edge case that is covered here. https://github.com/elastic/ent-search/pull/4715 Basically here is what we landed on: In most cases, the user will use the form to set the sync frequency, in which case the duration will be in the format of "PT3D" (ISO 8601). However, if an operator has set the sync frequency via the API, the duration could be a complex format, such as "P1DT2H3M4S". It was decided that in this case, we should omit seconds and go with the least common denominator from minutes. Example: "P1DT2H3M4S" -> "1563 Minutes" * Fix failing tests and add key * Update constants with note for translators * Fix typo Co-authored-by: Vadim Yakhin Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Vadim Yakhin --- .../applications/shared/constants/index.ts | 1 + .../applications/shared/constants/units.ts | 28 +++ .../__mocks__/content_sources.mock.ts | 26 ++- .../workplace_search/constants.ts | 27 +++ .../applications/workplace_search/routes.ts | 9 + .../applications/workplace_search/types.ts | 43 ++++- .../components/source_sub_nav.test.tsx | 69 ++++++- .../components/source_sub_nav.tsx | 27 ++- .../__mocks__/syncronization.mock.ts | 17 ++ .../blocked_window_item.test.tsx | 27 +++ .../synchronization/blocked_window_item.tsx | 157 ++++++++++++++++ .../blocked_window_tab.test.tsx | 54 ++++++ .../synchronization/blocked_window_tab.tsx | 53 ++++++ .../synchronization/frequency.test.tsx | 80 ++++++++ .../components/synchronization/frequency.tsx | 109 +++++++++++ .../synchronization/frequency_item.test.tsx | 64 +++++++ .../synchronization/frequency_item.tsx | 157 ++++++++++++++++ .../components/synchronization/index.ts | 8 + .../synchronization/objects_and_assets.tsx | 39 ++++ .../sync_frequency_tab.test.tsx | 41 +++++ .../synchronization/sync_frequency_tab.tsx | 84 +++++++++ .../synchronization/synchronization.test.tsx | 33 ++++ .../synchronization/synchronization.tsx | 71 ++++++++ .../synchronization_logic.test.ts | 79 ++++++++ .../synchronization/synchronization_logic.ts | 86 +++++++++ .../synchronization_router.test.tsx | 33 ++++ .../synchronization_router.tsx | 38 ++++ .../synchronization_sub_nav.test.tsx | 39 ++++ .../synchronization_sub_nav.tsx | 45 +++++ .../views/content_sources/constants.ts | 171 ++++++++++++++++++ .../content_sources/source_router.test.tsx | 2 +- .../views/content_sources/source_router.tsx | 8 + 32 files changed, 1716 insertions(+), 9 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/__mocks__/syncronization.mock.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/index.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/sync_frequency_tab.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/sync_frequency_tab.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/constants/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/constants/index.ts index 2504f51626bb0..6075f6e9822d3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/constants/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/constants/index.ts @@ -8,4 +8,5 @@ export * from './actions'; export * from './labels'; export * from './tables'; +export * from './units'; export { DEFAULT_META } from './default_meta'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/constants/units.ts b/x-pack/plugins/enterprise_search/public/applications/shared/constants/units.ts index 9d8c30c7e57d2..fdf879807bc6e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/constants/units.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/constants/units.ts @@ -7,6 +7,10 @@ import { i18n } from '@kbn/i18n'; +export const MINUTES_UNIT_LABEL = i18n.translate('xpack.enterpriseSearch.units.minutesLabel', { + defaultMessage: 'Minutes', +}); + export const HOURS_UNIT_LABEL = i18n.translate('xpack.enterpriseSearch.units.hoursLabel', { defaultMessage: 'Hours', }); @@ -22,3 +26,27 @@ export const WEEKS_UNIT_LABEL = i18n.translate('xpack.enterpriseSearch.units.wee export const MONTHS_UNIT_LABEL = i18n.translate('xpack.enterpriseSearch.units.monthsLabel', { defaultMessage: 'Months', }); + +export const DAYS_OF_WEEK_LABELS = { + SUNDAY: i18n.translate('xpack.enterpriseSearch.units.daysOfWeekLabel.sunday', { + defaultMessage: 'Sunday', + }), + MONDAY: i18n.translate('xpack.enterpriseSearch.units.daysOfWeekLabel.monday', { + defaultMessage: 'Monday', + }), + TUESDAY: i18n.translate('xpack.enterpriseSearch.units.daysOfWeekLabel.tuesday', { + defaultMessage: 'Tuesday', + }), + WEDNESDAY: i18n.translate('xpack.enterpriseSearch.units.daysOfWeekLabel.wednesday', { + defaultMessage: 'Wednesday', + }), + THURSDAY: i18n.translate('xpack.enterpriseSearch.units.daysOfWeekLabel.thursday', { + defaultMessage: 'Thursday', + }), + FRIDAY: i18n.translate('xpack.enterpriseSearch.units.daysOfWeekLabel.friday', { + defaultMessage: 'Friday', + }), + SATURDAY: i18n.translate('xpack.enterpriseSearch.units.daysOfWeekLabel.saturday', { + defaultMessage: 'Saturday', + }), +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts index 28e796c256396..e7b4e543b5eb8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts @@ -50,8 +50,28 @@ const defaultIndexing = { defaultAction: 'include', rules: [], schedule: { - intervals: [], - blocked: [], + full: 'P1D', + incremental: 'P2H', + delete: 'P10M', + permissions: 'P3H', + estimates: { + full: { + nextStart: '2021-09-30T15:37:38+00:00', + duration: 'PT1M5S', + }, + incremental: { + nextStart: '2021-09-27T17:39:24+00:00', + duration: 'PT2S', + }, + delete: { + nextStart: '2021-09-27T21:39:24+00:00', + duration: 'PT49S', + }, + permissions: { + nextStart: '2021-09-27T17:39:24+00:00', + duration: 'PT2S', + }, + }, }, features: { contentExtraction: { @@ -90,6 +110,7 @@ export const fullContentSources = [ groups, custom: false, isIndexedSource: true, + isSyncConfigEnabled: true, areThumbnailsConfigEnabled: true, accessToken: '123token', urlField: 'myLink', @@ -111,6 +132,7 @@ export const fullContentSources = [ indexing: defaultIndexing, custom: true, isIndexedSource: true, + isSyncConfigEnabled: true, areThumbnailsConfigEnabled: true, accessToken: '123token', urlField: 'url', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts index 3666a794617ac..4a3b6a11c707d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/constants.ts @@ -48,6 +48,21 @@ export const NAV = { SCHEMA: i18n.translate('xpack.enterpriseSearch.workplaceSearch.nav.schema', { defaultMessage: 'Schema', }), + SYNCHRONIZATION: i18n.translate('xpack.enterpriseSearch.workplaceSearch.nav.synchronization', { + defaultMessage: 'Synchronization', + }), + SYNCHRONIZATION_FREQUENCY: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.nav.synchronizationFrequency', + { + defaultMessage: 'Frequency', + } + ), + SYNCHRONIZATION_OBJECTS_AND_ASSETS: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.nav.synchronizationObjectsAndAssets', + { + defaultMessage: 'Objects and assets', + } + ), DISPLAY_SETTINGS: i18n.translate('xpack.enterpriseSearch.workplaceSearch.nav.displaySettings', { defaultMessage: 'Display Settings', }), @@ -745,6 +760,18 @@ export const DESCRIPTION_LABEL = i18n.translate( } ); +export const BLOCK_LABEL = i18n.translate('xpack.enterpriseSearch.workplaceSearch.blockLabel', { + defaultMessage: 'Block', +}); + +export const BETWEEN_LABEL = i18n.translate('xpack.enterpriseSearch.workplaceSearch.betweenLabel', { + defaultMessage: 'between', +}); + +export const EVERY_LABEL = i18n.translate('xpack.enterpriseSearch.workplaceSearch.everyLabel', { + defaultMessage: 'every', +}); + export const AND = i18n.translate('xpack.enterpriseSearch.workplaceSearch.and', { defaultMessage: 'and', }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts index cd699f7df86cb..691b52c9f51e4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts @@ -45,6 +45,10 @@ export const CUSTOM_SOURCE_DOCS_URL = `${DOCS_PREFIX}/workplace-search-custom-ap export const CUSTOM_API_DOCS_URL = `${DOCS_PREFIX}/workplace-search-custom-sources-api.html`; export const CUSTOM_API_DOCUMENT_PERMISSIONS_DOCS_URL = `${CUSTOM_SOURCE_DOCS_URL}#custom-api-source-document-level-access-control`; export const ENT_SEARCH_LICENSE_MANAGEMENT = `${docLinks.enterpriseSearchBase}/license-management.html`; +export const SYNCHRONIZATION_DOCS_URL = '#TODO'; +export const DIFFERENT_SYNC_TYPES_DOCS_URL = '#TODO'; +export const SYNC_BEST_PRACTICES_DOCS_URL = '#TODO'; +export const OBJECTS_AND_ASSETS_DOCS_URL = '#TODO'; export const PERSONAL_PATH = '/p'; @@ -89,12 +93,17 @@ export const SOURCE_DETAILS_PATH = `${SOURCES_PATH}/:sourceId`; export const SOURCE_CONTENT_PATH = `${SOURCES_PATH}/:sourceId/content`; export const SOURCE_SCHEMAS_PATH = `${SOURCES_PATH}/:sourceId/schemas`; export const SOURCE_DISPLAY_SETTINGS_PATH = `${SOURCES_PATH}/:sourceId/display_settings`; +export const SOURCE_SYNCHRONIZATION_PATH = `${SOURCES_PATH}/:sourceId/synchronization`; export const SOURCE_SETTINGS_PATH = `${SOURCES_PATH}/:sourceId/settings`; export const REINDEX_JOB_PATH = `${SOURCE_SCHEMAS_PATH}/:activeReindexJobId`; export const DISPLAY_SETTINGS_SEARCH_RESULT_PATH = `${SOURCE_DISPLAY_SETTINGS_PATH}/`; export const DISPLAY_SETTINGS_RESULT_DETAIL_PATH = `${SOURCE_DISPLAY_SETTINGS_PATH}/result_detail`; +export const SYNC_FREQUENCY_PATH = `${SOURCE_SYNCHRONIZATION_PATH}/frequency`; +export const BLOCKED_TIME_WINDOWS_PATH = `${SOURCE_SYNCHRONIZATION_PATH}/frequency/blocked_windows`; +export const OBJECTS_AND_ASSETS_PATH = `${SOURCE_SYNCHRONIZATION_PATH}/objects_and_assets`; + export const ORG_SETTINGS_PATH = '/settings'; export const ORG_SETTINGS_CUSTOMIZE_PATH = `${ORG_SETTINGS_PATH}/customize`; export const ORG_SETTINGS_CONNECTORS_PATH = `${ORG_SETTINGS_PATH}/connectors`; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts index c524bd4f7617a..9956eae229a04 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/types.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { Moment } from 'moment'; + import { RoleMapping } from '../shared/types'; export * from '../../../common/types/workplace_search'; @@ -128,7 +130,44 @@ interface SourceActivity { status: string; } -interface IndexingConfig { +export interface SyncEstimate { + duration?: string; + nextStart: string; + lastRun?: string; +} + +interface SyncIndexItem { + full: T; + incremental: T; + delete: T; + permissions?: T; +} + +interface IndexingSchedule extends SyncIndexItem { + estimates: SyncIndexItem; +} + +export type SyncJobType = 'full' | 'incremental' | 'delete' | 'permissions'; + +export const DAYS_OF_WEEK_VALUES = [ + 'sunday', + 'monday', + 'tuesday', + 'wednesday', + 'thursday', + 'friday', + 'saturday', +] as const; +export type DayOfWeek = typeof DAYS_OF_WEEK_VALUES[number]; + +export interface BlockedWindow { + jobType: SyncJobType; + day: DayOfWeek; + start: Moment; + end: Moment; +} + +export interface IndexingConfig { enabled: boolean; features: { contentExtraction: { @@ -138,6 +177,7 @@ interface IndexingConfig { enabled: boolean; }; }; + schedule: IndexingSchedule; } export interface ContentSourceFullData extends ContentSourceDetails { @@ -148,6 +188,7 @@ export interface ContentSourceFullData extends ContentSourceDetails { indexing: IndexingConfig; custom: boolean; isIndexedSource: boolean; + isSyncConfigEnabled: boolean; areThumbnailsConfigEnabled: boolean; accessToken: string; urlField: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx index 7f07c59587f96..d5ba030e582b8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.test.tsx @@ -7,6 +7,8 @@ import { setMockValues } from '../../../../__mocks__/kea_logic'; +import React from 'react'; + jest.mock('../../../../shared/layout', () => ({ generateNavLink: jest.fn(({ to }) => ({ href: to })), })); @@ -21,9 +23,13 @@ describe('useSourceSubNav', () => { }); it('returns EUI nav items', () => { - setMockValues({ isOrganization: true, contentSource: { id: '1' } }); + setMockValues({ isOrganization: true, contentSource: { id: '1', name: 'foo' } }); expect(useSourceSubNav()).toEqual([ + { + id: 'sourceName', + name: foo, + }, { id: 'sourceOverview', name: 'Overview', @@ -43,9 +49,16 @@ describe('useSourceSubNav', () => { }); it('returns extra nav items for custom sources', () => { - setMockValues({ isOrganization: true, contentSource: { id: '2', serviceType: 'custom' } }); + setMockValues({ + isOrganization: true, + contentSource: { id: '2', serviceType: 'custom', name: 'foo' }, + }); expect(useSourceSubNav()).toEqual([ + { + id: 'sourceName', + name: foo, + }, { id: 'sourceOverview', name: 'Overview', @@ -74,10 +87,60 @@ describe('useSourceSubNav', () => { ]); }); + it('returns extra nav items for synchronization', () => { + setMockValues({ + isOrganization: true, + contentSource: { id: '2', isIndexedSource: true, name: 'foo', isSyncConfigEnabled: true }, + }); + + expect(useSourceSubNav()).toEqual([ + { + id: 'sourceName', + name: foo, + }, + { + id: 'sourceOverview', + name: 'Overview', + href: '/sources/2', + }, + { + id: 'sourceContent', + name: 'Content', + href: '/sources/2/content', + }, + { + id: 'sourceSynchronization', + name: 'Synchronization', + href: '/sources/2/synchronization', + items: [ + { + id: 'sourceSynchronizationFrequency', + name: 'Frequency', + href: '/sources/2/synchronization/frequency', + }, + { + id: 'sourceSynchronizationObjectsAndAssets', + name: 'Objects and assets', + href: '/sources/2/synchronization/objects_and_assets', + }, + ], + }, + { + id: 'sourceSettings', + name: 'Settings', + href: '/sources/2/settings', + }, + ]); + }); + it('returns nav links to personal dashboard when not on an organization page', () => { - setMockValues({ isOrganization: false, contentSource: { id: '3' } }); + setMockValues({ isOrganization: false, contentSource: { id: '3', name: 'foo' } }); expect(useSourceSubNav()).toEqual([ + { + id: 'sourceName', + name: foo, + }, { id: 'sourceOverview', name: 'Overview', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.tsx index 6b595a06f0404..cae1e8834cdd2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_sub_nav.tsx @@ -5,6 +5,8 @@ * 2.0. */ +import React from 'react'; + import { useValues } from 'kea'; import { EuiSideNavItemType } from '@elastic/eui'; @@ -19,18 +21,29 @@ import { SOURCE_SCHEMAS_PATH, SOURCE_DISPLAY_SETTINGS_PATH, SOURCE_SETTINGS_PATH, + SOURCE_SYNCHRONIZATION_PATH, } from '../../../routes'; import { SourceLogic } from '../source_logic'; +import { useSynchronizationSubNav } from './synchronization/synchronization_sub_nav'; + export const useSourceSubNav = () => { const { isOrganization } = useValues(AppLogic); + const syncSubnav = useSynchronizationSubNav(); const { - contentSource: { id, serviceType }, + contentSource: { id, serviceType, isIndexedSource, name }, } = useValues(SourceLogic); if (!id) return undefined; + const isCustom = serviceType === CUSTOM_SERVICE_TYPE; + const showSynchronization = isIndexedSource && isOrganization; + const navItems: Array> = [ + { + id: 'sourceName', + name: {name}, + }, { id: 'sourceOverview', name: NAV.OVERVIEW, @@ -43,7 +56,17 @@ export const useSourceSubNav = () => { }, ]; - const isCustom = serviceType === CUSTOM_SERVICE_TYPE; + if (showSynchronization) { + navItems.push({ + id: 'sourceSynchronization', + name: NAV.SYNCHRONIZATION, + ...generateNavLink({ + to: getContentSourcePath(SOURCE_SYNCHRONIZATION_PATH, id, isOrganization), + }), + items: syncSubnav, + }); + } + if (isCustom) { navItems.push({ id: 'sourceSchema', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/__mocks__/syncronization.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/__mocks__/syncronization.mock.ts new file mode 100644 index 0000000000000..a71be55339f48 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/__mocks__/syncronization.mock.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment from 'moment'; + +import { SyncJobType, DayOfWeek } from '../../../../../types'; + +export const blockedWindow = { + jobType: 'incremental' as SyncJobType, + day: 'sunday' as DayOfWeek, + start: moment().set('hour', 11).set('minutes', 0), + end: moment().set('hour', 13).set('minutes', 0), +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.test.tsx new file mode 100644 index 0000000000000..9f8f0b08f3ca3 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.test.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { blockedWindow } from './__mocks__/syncronization.mock'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiComboBox, EuiDatePicker, EuiSuperSelect } from '@elastic/eui'; + +import { BlockedWindowItem } from './blocked_window_item'; + +describe('BlockedWindowItem', () => { + const props = { blockedWindow }; + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiComboBox)).toHaveLength(1); + expect(wrapper.find(EuiSuperSelect)).toHaveLength(1); + expect(wrapper.find(EuiDatePicker)).toHaveLength(2); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.tsx new file mode 100644 index 0000000000000..80f4244101fd8 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.tsx @@ -0,0 +1,157 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { + EuiButton, + EuiComboBox, + EuiComboBoxOptionOption, + EuiDatePicker, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiSuperSelect, + EuiText, +} from '@elastic/eui'; + +import { DAYS_OF_WEEK_LABELS } from '../../../../../shared/constants'; +import { BLOCK_LABEL, BETWEEN_LABEL, EVERY_LABEL, AND, REMOVE_BUTTON } from '../../../../constants'; +import { BlockedWindow, DAYS_OF_WEEK_VALUES } from '../../../../types'; + +import { + FULL_SYNC_LABEL, + INCREMENTAL_SYNC_LABEL, + DELETION_SYNC_LABEL, + PERMISSIONS_SYNC_LABEL, + FULL_SYNC_DESCRIPTION, + INCREMENTAL_SYNC_DESCRIPTION, + DELETION_SYNC_DESCRIPTION, + PERMISSIONS_SYNC_DESCRIPTION, +} from '../../constants'; + +interface Props { + blockedWindow: BlockedWindow; +} + +const syncOptions = [ + { + value: 'full', + inputDisplay: FULL_SYNC_LABEL, + dropdownDisplay: ( + <> + {FULL_SYNC_LABEL} + {FULL_SYNC_DESCRIPTION} + + ), + }, + { + value: 'incremental', + inputDisplay: INCREMENTAL_SYNC_LABEL, + dropdownDisplay: ( + <> + {INCREMENTAL_SYNC_LABEL} + {INCREMENTAL_SYNC_DESCRIPTION} + + ), + }, + { + value: 'deletion', + inputDisplay: DELETION_SYNC_LABEL, + dropdownDisplay: ( + <> + {DELETION_SYNC_LABEL} + {DELETION_SYNC_DESCRIPTION} + + ), + }, + { + value: 'permissions', + inputDisplay: PERMISSIONS_SYNC_LABEL, + dropdownDisplay: ( + <> + {PERMISSIONS_SYNC_LABEL} + {PERMISSIONS_SYNC_DESCRIPTION} + + ), + }, +]; + +const dayPickerOptions = DAYS_OF_WEEK_VALUES.reduce((options, day) => { + options.push({ + label: DAYS_OF_WEEK_LABELS[day.toUpperCase() as keyof typeof DAYS_OF_WEEK_LABELS], + value: day, + }); + return options; +}, [] as Array>); + +export const BlockedWindowItem: React.FC = ({ blockedWindow }) => { + const handleSyncTypeChange = () => '#TODO'; + const handleStartDateChange = () => '#TODO'; + const handleEndDateChange = () => '#TODO'; + + return ( + <> + + + + {BLOCK_LABEL} + + + + + + {BETWEEN_LABEL} + + + + + + {AND} + + + + + + {EVERY_LABEL} + + + + + + + {REMOVE_BUTTON} + + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.test.tsx new file mode 100644 index 0000000000000..0d5183b5e95e1 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.test.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../../../__mocks__/shallow_useeffect.mock'; +import { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; +import { blockedWindow } from './__mocks__/syncronization.mock'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; + +import { BlockedWindowItem } from './blocked_window_item'; +import { BlockedWindows } from './blocked_window_tab'; + +describe('BlockedWindows', () => { + const addBlockedWindow = jest.fn(); + const mockActions = { + addBlockedWindow, + }; + const mockValues = { + blockedWindows: [blockedWindow], + }; + + beforeEach(() => { + setMockActions(mockActions); + setMockValues(mockValues); + }); + + it('renders blocked windows', () => { + const wrapper = shallow(); + + expect(wrapper.find(BlockedWindowItem)).toHaveLength(1); + }); + + it('renders empty state', () => { + setMockValues({ blockedWindows: [] }); + const wrapper = shallow(); + + expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); + }); + + it('handles button click', () => { + const wrapper = shallow(); + wrapper.find(EuiButton).simulate('click'); + + expect(addBlockedWindow).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.tsx new file mode 100644 index 0000000000000..474bf4cab2a8e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues, useActions } from 'kea'; + +import { EuiButton, EuiEmptyPrompt, EuiSpacer } from '@elastic/eui'; + +import { ADD_LABEL } from '../../../../constants'; +import { BLOCKED_EMPTY_STATE_TITLE, BLOCKED_EMPTY_STATE_DESCRIPTION } from '../../constants'; + +import { BlockedWindowItem } from './blocked_window_item'; +import { SynchronizationLogic } from './synchronization_logic'; + +export const BlockedWindows: React.FC = () => { + const { blockedWindows } = useValues(SynchronizationLogic); + const { addBlockedWindow } = useActions(SynchronizationLogic); + + const hasBlockedWindows = blockedWindows.length > 0; + + const emptyState = ( + <> + + {BLOCKED_EMPTY_STATE_TITLE}} + body={

    {BLOCKED_EMPTY_STATE_DESCRIPTION}

    } + actions={ + + {ADD_LABEL} + + } + /> + + ); + + const blockedWindowItems = ( + <> + {blockedWindows.map((blockedWindow, i) => ( + + ))} + + {ADD_LABEL} + + ); + + return hasBlockedWindows ? blockedWindowItems : emptyState; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.test.tsx new file mode 100644 index 0000000000000..08de4b41758a2 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.test.tsx @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../../../__mocks__/shallow_useeffect.mock'; +import { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiTabbedContent } from '@elastic/eui'; + +import { SourceLayout } from '../source_layout'; + +import { Frequency } from './frequency'; + +describe('Frequency', () => { + const handleSelectedTabChanged = jest.fn(); + const mockActions = { + handleSelectedTabChanged, + }; + const mockValues = {}; + + beforeEach(() => { + setMockActions(mockActions); + setMockValues(mockValues); + }); + + it('renders first tab', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiTabbedContent)).toHaveLength(1); + expect(wrapper.find(SourceLayout).prop('pageChrome')).toEqual(['Frequency', 'Sync frequency']); + }); + + it('renders second tab', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiTabbedContent)).toHaveLength(1); + expect(wrapper.find(SourceLayout).prop('pageChrome')).toEqual([ + 'Frequency', + 'Blocked time windows', + ]); + }); + + describe('tabbed content', () => { + const tabs = [ + { + id: 'source_sync_frequency', + name: 'Sync frequency', + content: <>, + }, + { + id: 'blocked_time_windows', + name: 'Blocked time windows', + content: <>, + }, + ]; + + it('handles first tab click', () => { + const wrapper = shallow(); + const tabsEl = wrapper.find(EuiTabbedContent); + tabsEl.prop('onTabClick')!(tabs[0]); + + expect(handleSelectedTabChanged).toHaveBeenCalledWith('source_sync_frequency'); + }); + + it('handles second tab click', () => { + const wrapper = shallow(); + const tabsEl = wrapper.find(EuiTabbedContent); + tabsEl.prop('onTabClick')!(tabs[1]); + + expect(handleSelectedTabChanged).toHaveBeenCalledWith('blocked_time_windows'); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.tsx new file mode 100644 index 0000000000000..fb19c84ecfdd1 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.tsx @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useActions } from 'kea'; + +import { + EuiButton, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiSpacer, + EuiTabbedContent, + EuiTabbedContentTab, +} from '@elastic/eui'; + +import { SAVE_BUTTON_LABEL } from '../../../../../shared/constants'; +import { ViewContentHeader } from '../../../../components/shared/view_content_header'; +import { NAV, RESET_BUTTON } from '../../../../constants'; +import { DIFFERENT_SYNC_TYPES_DOCS_URL, SYNC_BEST_PRACTICES_DOCS_URL } from '../../../../routes'; +import { + SOURCE_FREQUENCY_DESCRIPTION, + SOURCE_SYNC_FREQUENCY_TITLE, + BLOCKED_TIME_WINDOWS_TITLE, + DIFFERENT_SYNC_TYPES_LINK_LABEL, + SYNC_BEST_PRACTICES_LINK_LABEL, +} from '../../constants'; +import { SourceLayout } from '../source_layout'; + +import { BlockedWindows } from './blocked_window_tab'; +import { SyncFrequency } from './sync_frequency_tab'; +import { SynchronizationLogic, TabId } from './synchronization_logic'; + +interface FrequencyProps { + tabId: number; +} + +export const Frequency: React.FC = ({ tabId }) => { + const { handleSelectedTabChanged } = useActions(SynchronizationLogic); + + const tabs = [ + { + id: 'source_sync_frequency', + name: SOURCE_SYNC_FREQUENCY_TITLE, + content: , + }, + { + id: 'blocked_time_windows', + name: BLOCKED_TIME_WINDOWS_TITLE, + content: , + }, + ] as EuiTabbedContentTab[]; + + const onSelectedTabChanged = (tab: EuiTabbedContentTab) => { + handleSelectedTabChanged(tab.id as TabId); + }; + + const actions = ( + + + {RESET_BUTTON}{' '} + + + {SAVE_BUTTON_LABEL}{' '} + + + ); + + const docsLinks = ( + + + + {DIFFERENT_SYNC_TYPES_LINK_LABEL} + + + + + {SYNC_BEST_PRACTICES_LINK_LABEL} + + + + ); + + return ( + + + {docsLinks} + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.test.tsx new file mode 100644 index 0000000000000..fb346ad96117e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.test.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiFieldNumber, EuiSuperSelect } from '@elastic/eui'; + +import { FrequencyItem } from './frequency_item'; + +describe('FrequencyItem', () => { + const props = { + label: 'Item', + description: 'My item', + duration: 'PT2D', + estimate: { + duration: 'PT3D', + nextStart: '2021-09-27T21:39:24+00:00', + lastRun: '2021-09-25T21:39:24+00:00', + }, + }; + + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiSuperSelect)).toHaveLength(1); + expect(wrapper.find(EuiFieldNumber)).toHaveLength(1); + }); + + describe('ISO8601 formatting', () => { + it('handles minutes display', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiFieldNumber).prop('value')).toEqual(1563); + expect(wrapper.find(EuiSuperSelect).prop('valueOfSelected')).toEqual('minutes'); + }); + + it('handles hours display', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiFieldNumber).prop('value')).toEqual(26); + expect(wrapper.find(EuiSuperSelect).prop('valueOfSelected')).toEqual('hours'); + }); + + it('handles days display', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiFieldNumber).prop('value')).toEqual(3); + expect(wrapper.find(EuiSuperSelect).prop('valueOfSelected')).toEqual('days'); + }); + + it('handles seconds display (defaults to 1 minute)', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiFieldNumber).prop('value')).toEqual(1); + expect(wrapper.find(EuiSuperSelect).prop('valueOfSelected')).toEqual('minutes'); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.tsx new file mode 100644 index 0000000000000..4e9eec28dc1eb --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.tsx @@ -0,0 +1,157 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import moment from 'moment'; + +import { + EuiFlexGroup, + EuiFieldNumber, + EuiFlexItem, + EuiIconTip, + EuiSpacer, + EuiSuperSelect, + EuiText, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + MINUTES_UNIT_LABEL, + HOURS_UNIT_LABEL, + DAYS_UNIT_LABEL, +} from '../../../../../shared/constants'; +import { SyncEstimate } from '../../../../types'; + +interface Props { + label: string; + description: string; + duration: string; + estimate: SyncEstimate; +} + +const unitOptions = [ + { + value: 'minutes', + inputDisplay: MINUTES_UNIT_LABEL, + }, + { + value: 'hours', + inputDisplay: HOURS_UNIT_LABEL, + }, + { + value: 'days', + inputDisplay: DAYS_UNIT_LABEL, + }, +]; + +export const FrequencyItem: React.FC = ({ label, description, duration, estimate }) => { + const [interval, unit] = formatDuration(duration); + const { lastRun, nextStart, duration: durationEstimate } = estimate; + const estimateDisplay = durationEstimate && moment.duration(durationEstimate).humanize(); + + const onChange = () => '#TODO'; + + const frequencyItemLabel = ( + {label}, + }} + /> + ); + + const lastRunSummary = ( + + + + ), + lastRunTime: moment(lastRun).fromNow(), + }} + /> + ); + + const nextStartSummary = ( + + + + ), + nextStartTime: moment(nextStart).fromNow(), + }} + /> + ); + + const estimateSummary = ( + + ); + + return ( + <> + + + {frequencyItemLabel} + + + + + + + + + + + + + + {lastRun && lastRunSummary} {nextStartSummary} {estimateDisplay && estimateSummary} + + + + ); +}; + +// In most cases, the user will use the form to set the sync frequency, in which case the duration +// will be in the format of "PT3D" (ISO 8601). However, if an operator has set the sync frequency via +// the API, the duration could be a complex format, such as "P1DT2H3M4S". It was decided that in this +// case, we should omit seconds and go with the least common denominator from minutes. +// +// Example: "P1DT2H3M4S" -> "1563 Minutes" +const formatDuration = (duration: string): [interval: number, unit: string] => { + const momentDuration = moment.duration(duration); + if (duration.includes('M')) { + return [Math.round(momentDuration.asMinutes()), unitOptions[0].value]; + } + if (duration.includes('H')) { + return [Math.round(momentDuration.asHours()), unitOptions[1].value]; + } + if (duration.includes('D')) { + return [Math.round(momentDuration.asDays()), unitOptions[2].value]; + } + + return [1, unitOptions[0].value]; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/index.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/index.ts new file mode 100644 index 0000000000000..450bc41bf46f7 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/index.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { SynchronizationRouter } from './synchronization_router'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx new file mode 100644 index 0000000000000..4c2804459f1ba --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { EuiHorizontalRule, EuiLink } from '@elastic/eui'; + +import { ViewContentHeader } from '../../../../components/shared/view_content_header'; +import { NAV } from '../../../../constants'; +import { OBJECTS_AND_ASSETS_DOCS_URL } from '../../../../routes'; +import { + SOURCE_OBJECTS_AND_ASSETS_DESCRIPTION, + SYNC_OBJECTS_TYPES_LINK_LABEL, +} from '../../constants'; +import { SourceLayout } from '../source_layout'; + +export const ObjectsAndAssets: React.FC = () => { + return ( + + + + {SYNC_OBJECTS_TYPES_LINK_LABEL} + + +
    TODO
    +
    + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/sync_frequency_tab.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/sync_frequency_tab.test.tsx new file mode 100644 index 0000000000000..6c382b0addab8 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/sync_frequency_tab.test.tsx @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../../../__mocks__/shallow_useeffect.mock'; +import { setMockValues } from '../../../../../__mocks__/kea_logic'; +import { fullContentSources } from '../../../../__mocks__/content_sources.mock'; + +import React from 'react'; + +import { shallow } from 'enzyme'; +import { cloneDeep } from 'lodash'; + +import { FrequencyItem } from './frequency_item'; +import { SyncFrequency } from './sync_frequency_tab'; + +describe('SyncFrequency', () => { + const contentSource = fullContentSources[0]; + const sourceWithNoDLP = cloneDeep(contentSource); + sourceWithNoDLP.indexing.schedule.permissions = undefined as any; + sourceWithNoDLP.indexing.schedule.estimates.permissions = undefined as any; + + it('renders with DLP', () => { + setMockValues({ contentSource }); + const wrapper = shallow(); + + expect(wrapper.find(FrequencyItem)).toHaveLength(4); + }); + + it('renders without DLP', () => { + setMockValues({ + contentSource: sourceWithNoDLP, + }); + const wrapper = shallow(); + + expect(wrapper.find(FrequencyItem)).toHaveLength(3); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/sync_frequency_tab.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/sync_frequency_tab.tsx new file mode 100644 index 0000000000000..2a0ccb1fdb2c9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/sync_frequency_tab.tsx @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues } from 'kea'; + +import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; + +import { + FULL_SYNC_LABEL, + INCREMENTAL_SYNC_LABEL, + DELETION_SYNC_LABEL, + PERMISSIONS_SYNC_LABEL, + FULL_SYNC_DESCRIPTION, + INCREMENTAL_SYNC_DESCRIPTION, + DELETION_SYNC_DESCRIPTION, + PERMISSIONS_SYNC_DESCRIPTION, +} from '../../constants'; +import { SourceLogic } from '../../source_logic'; + +import { FrequencyItem } from './frequency_item'; + +export const SyncFrequency: React.FC = () => { + const { + contentSource: { + indexing: { + schedule: { + full: fullDuration, + incremental: incrementalDuration, + delete: deleteDuration, + permissions: permissionsDuration, + estimates: { + full: fullEstimate, + incremental: incrementalEstimate, + delete: deleteEstimate, + permissions: permissionsEstimate, + }, + }, + }, + }, + } = useValues(SourceLogic); + + return ( + <> + + + + + + + {permissionsDuration && permissionsEstimate && ( + <> + + + + )} + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.test.tsx new file mode 100644 index 0000000000000..632af08611ca9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.test.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { setMockValues } from '../../../../../__mocks__/kea_logic'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiLink, EuiCallOut, EuiSwitch } from '@elastic/eui'; + +import { Synchronization } from './synchronization'; + +describe('Synchronization', () => { + it('renders when config enabled', () => { + setMockValues({ contentSource: { isSyncConfigEnabled: true } }); + const wrapper = shallow(); + + expect(wrapper.find(EuiLink)).toHaveLength(1); + expect(wrapper.find(EuiSwitch)).toHaveLength(1); + }); + + it('renders when config disabled', () => { + setMockValues({ contentSource: { isSyncConfigEnabled: false } }); + const wrapper = shallow(); + + expect(wrapper.find(EuiCallOut)).toHaveLength(1); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.tsx new file mode 100644 index 0000000000000..21daee8f26d40 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.tsx @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues } from 'kea'; + +import { EuiCallOut, EuiLink, EuiPanel, EuiSwitch, EuiSpacer, EuiText } from '@elastic/eui'; + +import { ViewContentHeader } from '../../../../components/shared/view_content_header'; +import { NAV } from '../../../../constants'; +import { SYNCHRONIZATION_DOCS_URL } from '../../../../routes'; +import { + SOURCE_SYNCRONIZATION_DESCRIPTION, + SYNCHRONIZATION_DISABLED_TITLE, + SYNCHRONIZATION_DISABLED_DESCRIPTION, + SOURCE_SYNCRONIZATION_TOGGLE_LABEL, + SOURCE_SYNCRONIZATION_TOGGLE_DESCRIPTION, + SYNCHRONIZATION_LINK_LABEL, +} from '../../constants'; +import { SourceLogic } from '../../source_logic'; +import { SourceLayout } from '../source_layout'; + +export const Synchronization: React.FC = () => { + const { + contentSource: { isSyncConfigEnabled }, + } = useValues(SourceLogic); + + const onChange = (checked: boolean) => `#TODO: ${checked}`; + const syncToggle = ( + + onChange(e.target.checked)} + /> + + + {SOURCE_SYNCRONIZATION_TOGGLE_DESCRIPTION} + + + ); + + const syncDisabledCallout = ( + +

    {SYNCHRONIZATION_DISABLED_DESCRIPTION}

    +
    + ); + + return ( + + + + {SYNCHRONIZATION_LINK_LABEL} + + + {isSyncConfigEnabled ? syncToggle : syncDisabledCallout} + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts new file mode 100644 index 0000000000000..50553d1493417 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { LogicMounter, mockKibanaValues } from '../../../../../__mocks__/kea_logic'; + +import { nextTick } from '@kbn/test/jest'; + +const contentSource = { id: 'source123' }; +jest.mock('../../source_logic', () => ({ + SourceLogic: { values: { contentSource } }, +})); + +jest.mock('../../../../app_logic', () => ({ + AppLogic: { values: { isOrganization: true } }, +})); + +import { SynchronizationLogic, emptyBlockedWindow } from './synchronization_logic'; + +describe('SynchronizationLogic', () => { + const { navigateToUrl } = mockKibanaValues; + const { mount } = new LogicMounter(SynchronizationLogic); + + const defaultValues = { + navigatingBetweenTabs: false, + blockedWindows: [], + }; + + beforeEach(() => { + jest.clearAllMocks(); + mount(); + }); + + it('has expected default values', () => { + expect(SynchronizationLogic.values).toEqual(defaultValues); + }); + + describe('actions', () => { + it('setNavigatingBetweenTabs', () => { + SynchronizationLogic.actions.setNavigatingBetweenTabs(true); + + expect(SynchronizationLogic.values.navigatingBetweenTabs).toEqual(true); + }); + + it('addBlockedWindow', () => { + SynchronizationLogic.actions.addBlockedWindow(); + + expect(SynchronizationLogic.values.blockedWindows).toEqual([emptyBlockedWindow]); + }); + }); + + describe('listeners', () => { + describe('handleSelectedTabChanged', () => { + it('calls setNavigatingBetweenTabs', async () => { + const setNavigatingBetweenTabsSpy = jest.spyOn( + SynchronizationLogic.actions, + 'setNavigatingBetweenTabs' + ); + SynchronizationLogic.actions.handleSelectedTabChanged('source_sync_frequency'); + await nextTick(); + + expect(setNavigatingBetweenTabsSpy).toHaveBeenCalledWith(true); + expect(navigateToUrl).toHaveBeenCalledWith('/sources/source123/synchronization/frequency'); + }); + + it('calls calls correct route for "blocked_time_windows"', async () => { + SynchronizationLogic.actions.handleSelectedTabChanged('blocked_time_windows'); + await nextTick(); + + expect(navigateToUrl).toHaveBeenCalledWith( + '/sources/source123/synchronization/frequency/blocked_windows' + ); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts new file mode 100644 index 0000000000000..4f67f6471e6e1 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kea, MakeLogicType } from 'kea'; +import moment from 'moment'; + +export type TabId = 'source_sync_frequency' | 'blocked_time_windows'; + +import { KibanaLogic } from '../../../../../shared/kibana'; +import { AppLogic } from '../../../../app_logic'; +import { + SYNC_FREQUENCY_PATH, + BLOCKED_TIME_WINDOWS_PATH, + getContentSourcePath, +} from '../../../../routes'; +import { BlockedWindow } from '../../../../types'; + +import { SourceLogic } from '../../source_logic'; + +interface SynchronizationActions { + setNavigatingBetweenTabs(navigatingBetweenTabs: boolean): boolean; + handleSelectedTabChanged(tabId: TabId): TabId; + addBlockedWindow(): void; +} + +interface SynchronizationValues { + hasUnsavedChanges: boolean; + navigatingBetweenTabs: boolean; + blockedWindows: BlockedWindow[]; +} + +export const emptyBlockedWindow: BlockedWindow = { + jobType: 'full', + day: 'monday', + start: moment().set('hour', 11).set('minutes', 0), + end: moment().set('hour', 13).set('minutes', 0), +}; + +export const SynchronizationLogic = kea< + MakeLogicType +>({ + actions: { + setNavigatingBetweenTabs: (navigatingBetweenTabs: boolean) => navigatingBetweenTabs, + handleSelectedTabChanged: (tabId: TabId) => tabId, + addBlockedWindow: true, + }, + reducers: { + navigatingBetweenTabs: [ + false, + { + setNavigatingBetweenTabs: (_, navigatingBetweenTabs) => navigatingBetweenTabs, + }, + ], + blockedWindows: [ + [], + { + addBlockedWindow: (state, _) => [...state, emptyBlockedWindow], + }, + ], + }, + listeners: ({ actions }) => ({ + handleSelectedTabChanged: async (tabId, breakpoint) => { + const { isOrganization } = AppLogic.values; + const { id: sourceId } = SourceLogic.values.contentSource; + const path = + tabId === 'source_sync_frequency' + ? getContentSourcePath(SYNC_FREQUENCY_PATH, sourceId, isOrganization) + : getContentSourcePath(BLOCKED_TIME_WINDOWS_PATH, sourceId, isOrganization); + + // This method is needed because the shared `UnsavedChangesPrompt` component is triggered + // when navigating between tabs. We set a boolean flag that tells the prompt there are no + // unsaved changes when navigating between the tabs and reset it one the transition is complete + // in order to restore the intended functionality when navigating away with unsaved changes. + actions.setNavigatingBetweenTabs(true); + + await breakpoint(); + + KibanaLogic.values.navigateToUrl(path); + actions.setNavigatingBetweenTabs(false); + }, + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.test.tsx new file mode 100644 index 0000000000000..cf130d2c21a57 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.test.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import '../../../../../__mocks__/shallow_useeffect.mock'; + +import { setMockValues } from '../../../../../__mocks__/kea_logic'; + +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import { shallow } from 'enzyme'; + +import { Frequency } from './frequency'; +import { ObjectsAndAssets } from './objects_and_assets'; +import { Synchronization } from './synchronization'; +import { SynchronizationRouter } from './synchronization_router'; + +describe('SynchronizationRouter', () => { + it('renders', () => { + setMockValues({ isOrganization: true }); + const wrapper = shallow(); + + expect(wrapper.find(Synchronization)).toHaveLength(1); + expect(wrapper.find(ObjectsAndAssets)).toHaveLength(1); + expect(wrapper.find(Frequency)).toHaveLength(2); + expect(wrapper.find(Switch)).toHaveLength(1); + expect(wrapper.find(Route)).toHaveLength(4); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.tsx new file mode 100644 index 0000000000000..ede0f293377cf --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_router.tsx @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import { + SYNC_FREQUENCY_PATH, + BLOCKED_TIME_WINDOWS_PATH, + OBJECTS_AND_ASSETS_PATH, + SOURCE_SYNCHRONIZATION_PATH, + getSourcesPath, +} from '../../../../routes'; + +import { Frequency } from './frequency'; +import { ObjectsAndAssets } from './objects_and_assets'; +import { Synchronization } from './synchronization'; + +export const SynchronizationRouter: React.FC = () => ( + + + + + + + + + + + + + + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.test.tsx new file mode 100644 index 0000000000000..a2978c34475db --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.test.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { setMockValues } from '../../../../../__mocks__/kea_logic'; + +jest.mock('../../../../../shared/layout', () => ({ + generateNavLink: jest.fn(({ to }) => ({ href: to })), +})); + +import { useSynchronizationSubNav } from './synchronization_sub_nav'; + +describe('useSynchronizationSubNav', () => { + it('renders nav items', () => { + setMockValues({ contentSource: { id: '1', isSyncConfigEnabled: true } }); + + expect(useSynchronizationSubNav()).toEqual([ + { + id: 'sourceSynchronizationFrequency', + name: 'Frequency', + href: '/sources/1/synchronization/frequency', + }, + { + id: 'sourceSynchronizationObjectsAndAssets', + name: 'Objects and assets', + href: '/sources/1/synchronization/objects_and_assets', + }, + ]); + }); + + it('returns undefined when no content source id is present', () => { + setMockValues({ contentSource: {} }); + + expect(useSynchronizationSubNav()).toEqual(undefined); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.tsx new file mode 100644 index 0000000000000..2df6e9177211f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_sub_nav.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useValues } from 'kea'; + +import { EuiSideNavItemType } from '@elastic/eui'; + +import { generateNavLink } from '../../../../../shared/layout'; +import { NAV } from '../../../../constants'; +import { + getContentSourcePath, + SYNC_FREQUENCY_PATH, + OBJECTS_AND_ASSETS_PATH, +} from '../../../../routes'; +import { SourceLogic } from '../../source_logic'; + +export const useSynchronizationSubNav = () => { + const { + contentSource: { id, isSyncConfigEnabled }, + } = useValues(SourceLogic); + + if (!id || !isSyncConfigEnabled) return undefined; + + const navItems: Array> = [ + { + id: 'sourceSynchronizationFrequency', + name: NAV.SYNCHRONIZATION_FREQUENCY, + ...generateNavLink({ + to: getContentSourcePath(SYNC_FREQUENCY_PATH, id, true), + shouldShowActiveForSubroutes: true, + }), + }, + { + id: 'sourceSynchronizationObjectsAndAssets', + name: NAV.SYNCHRONIZATION_OBJECTS_AND_ASSETS, + ...generateNavLink({ to: getContentSourcePath(OBJECTS_AND_ASSETS_PATH, id, true) }), + }, + ]; + + return navItems; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts index b90d6abe38702..ae55a970a4f9f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts @@ -540,3 +540,174 @@ export const SOURCE_OVERVIEW_TITLE = i18n.translate( defaultMessage: 'Source overview', } ); + +export const SOURCE_SYNCRONIZATION_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncronizationDescription', + { + defaultMessage: + 'DO NOT TRANSLATE, temporary placeholder: Sync chupa chups dragée gummi bears jelly beans brownie. Fruitcake pie chocolate cake caramels carrot cake cotton candy dragée sweet roll soufflé.', + } +); + +export const SOURCE_FREQUENCY_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceFrequencyDescription', + { + defaultMessage: + 'DO NOT TRANSLATE, temporary placeholder: Frequency chupa chups dragée gummi bears jelly beans brownie. Fruitcake pie chocolate cake caramels carrot cake cotton candy dragée sweet roll soufflé.', + } +); + +export const SOURCE_OBJECTS_AND_ASSETS_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceObjectsAndAssetsDescription', + { + defaultMessage: + 'DO NOT TRANSLATE, temporary placeholder: Objects chupa chups dragée gummi bears jelly beans brownie. Fruitcake pie chocolate cake caramels carrot cake cotton candy dragée sweet roll soufflé.', + } +); + +export const SOURCE_SYNCRONIZATION_TOGGLE_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncronizationToggleLabel', + { + defaultMessage: 'Synchronize this source', + } +); + +export const SOURCE_SYNCRONIZATION_TOGGLE_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncronizationToggleDescription', + { + defaultMessage: 'Source content will automatically be kept in sync.', + } +); + +export const SOURCE_SYNCRONIZATION_FREQUENCY_TITLE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncronizationFrequencyTitle', + { + defaultMessage: 'Syncronization frequency', + } +); + +export const SOURCE_SYNC_FREQUENCY_TITLE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncFrequencyTitle', + { + defaultMessage: 'Sync frequency', + } +); + +export const BLOCKED_TIME_WINDOWS_TITLE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.blockedWindowsTitle', + { + defaultMessage: 'Blocked time windows', + } +); + +export const SYNCHRONIZATION_LINK_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.synchronizationLinkLabel', + { + defaultMessage: 'Learn more about synchronization', + } +); + +export const SYNCHRONIZATION_DISABLED_TITLE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.synchronizationDisabledTitle', + { + defaultMessage: 'Source synchronization is disabled.', + } +); + +export const SYNCHRONIZATION_DISABLED_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.synchronizationDisabledDescription', + { + defaultMessage: 'Contact your administrator to enable synchronization controls.', + } +); + +export const DIFFERENT_SYNC_TYPES_LINK_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.differentSyncTypesLinkLabel', + { + defaultMessage: 'Learn more about different sync types', + } +); + +export const SYNC_BEST_PRACTICES_LINK_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.syncBestPracticesLinkLabel', + { + defaultMessage: 'Learn more about sync best practices', + } +); + +export const SYNC_OBJECTS_TYPES_LINK_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.syncObjectsTypesLinkLabel', + { + defaultMessage: 'Learn more about sync objects types', + } +); + +export const FULL_SYNC_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.fullSyncLabel', + { + defaultMessage: 'Full sync', + } +); + +export const FULL_SYNC_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.fullSyncDescription', + { + defaultMessage: 'Retrieves all the documents possible from the content source', + } +); + +export const INCREMENTAL_SYNC_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.incrementalSyncLabel', + { + defaultMessage: 'Incremental sync', + } +); + +export const INCREMENTAL_SYNC_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.incrementalSyncDescription', + { + defaultMessage: 'Retrieves documents/updates since the last sync job', + } +); + +export const DELETION_SYNC_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.deletionSyncLabel', + { + defaultMessage: 'Deletion sync', + } +); + +export const DELETION_SYNC_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.deletionSyncDescription', + { + defaultMessage: 'Removes documents that no longer exist in the content source', + } +); + +export const PERMISSIONS_SYNC_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.permissionsSyncLabel', + { + defaultMessage: 'Permissions sync', + } +); + +export const PERMISSIONS_SYNC_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.permissionsSyncDescription', + { + defaultMessage: 'Retrieves all permission changes since the last sync job', + } +); + +export const BLOCKED_EMPTY_STATE_TITLE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.blockedEmptyStateTitle', + { + defaultMessage: 'You have no blocked time windows', + } +); + +export const BLOCKED_EMPTY_STATE_DESCRIPTION = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.blockedEmptyStateDescription', + { + defaultMessage: 'Add a blocked time window to only perform syncs at the right time.', + } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx index fbc8eb159a7a8..3f9bbc59e8427 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx @@ -90,7 +90,7 @@ describe('SourceRouter', () => { expect(wrapper.find(Overview)).toHaveLength(1); expect(wrapper.find(SourceSettings)).toHaveLength(1); expect(wrapper.find(SourceContent)).toHaveLength(1); - expect(wrapper.find(Route)).toHaveLength(4); + expect(wrapper.find(Route)).toHaveLength(5); }); it('renders source routes (custom)', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx index 2a7dc2ebcc285..6cb9ea6bc681b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx @@ -21,6 +21,7 @@ import { SOURCE_SCHEMAS_PATH, SOURCE_DISPLAY_SETTINGS_PATH, SOURCE_SETTINGS_PATH, + SOURCE_SYNCHRONIZATION_PATH, getContentSourcePath as sourcePath, getSourcesPath, } from '../../routes'; @@ -32,6 +33,7 @@ import { Schema } from './components/schema'; import { SchemaChangeErrors } from './components/schema/schema_change_errors'; import { SourceContent } from './components/source_content'; import { SourceSettings } from './components/source_settings'; +import { SynchronizationRouter } from './components/synchronization'; import { SourceLogic } from './source_logic'; export const SourceRouter: React.FC = () => { @@ -59,6 +61,7 @@ export const SourceRouter: React.FC = () => { const { serviceType } = contentSource; const isCustomSource = serviceType === CUSTOM_SERVICE_TYPE; + const showSynchronization = !isCustomSource && isOrganization; return ( @@ -68,6 +71,11 @@ export const SourceRouter: React.FC = () => { + {showSynchronization && ( + + + + )} {isCustomSource && ( From dbad35f1cc2fc3866b5adbf1b5122b7f473d1c29 Mon Sep 17 00:00:00 2001 From: Mat Schaffer Date: Tue, 5 Oct 2021 15:16:21 +0900 Subject: [PATCH 85/98] Apm pages (#113716) * Apm overview page * APM instances page * Add APM instance page * Add ignores on js components * One more ts-ignore --- .../monitoring/public/application/index.tsx | 39 +++++- .../application/pages/apm/apm_template.tsx | 31 +++++ .../public/application/pages/apm/index.ts | 10 ++ .../public/application/pages/apm/instance.tsx | 92 ++++++++++++++ .../application/pages/apm/instances.tsx | 112 ++++++++++++++++++ .../public/application/pages/apm/overview.tsx | 77 ++++++++++++ 6 files changed, 355 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/monitoring/public/application/pages/apm/apm_template.tsx create mode 100644 x-pack/plugins/monitoring/public/application/pages/apm/index.ts create mode 100644 x-pack/plugins/monitoring/public/application/pages/apm/instance.tsx create mode 100644 x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx create mode 100644 x-pack/plugins/monitoring/public/application/pages/apm/overview.tsx diff --git a/x-pack/plugins/monitoring/public/application/index.tsx b/x-pack/plugins/monitoring/public/application/index.tsx index 088891621923c..9ecfca2f2df2e 100644 --- a/x-pack/plugins/monitoring/public/application/index.tsx +++ b/x-pack/plugins/monitoring/public/application/index.tsx @@ -23,8 +23,8 @@ import { ElasticsearchOverviewPage } from './pages/elasticsearch/overview'; import { BeatsOverviewPage } from './pages/beats/overview'; import { BeatsInstancesPage } from './pages/beats/instances'; import { BeatsInstancePage } from './pages/beats/instance'; +import { ApmOverviewPage, ApmInstancesPage, ApmInstancePage } from './pages/apm'; import { KibanaOverviewPage } from './pages/kibana/overview'; -import { CODE_PATH_ELASTICSEARCH, CODE_PATH_BEATS, CODE_PATH_KIBANA } from '../../common/constants'; import { ElasticsearchNodesPage } from './pages/elasticsearch/nodes_page'; import { ElasticsearchIndicesPage } from './pages/elasticsearch/indices_page'; import { ElasticsearchIndexPage } from './pages/elasticsearch/index_page'; @@ -33,6 +33,12 @@ import { ElasticsearchNodePage } from './pages/elasticsearch/node_page'; import { ElasticsearchNodeAdvancedPage } from './pages/elasticsearch/node_advanced_page'; import { MonitoringTimeContainer } from './hooks/use_monitoring_time'; import { BreadcrumbContainer } from './hooks/use_breadcrumbs'; +import { + CODE_PATH_ELASTICSEARCH, + CODE_PATH_KIBANA, + CODE_PATH_BEATS, + CODE_PATH_APM, +} from '../../common/constants'; export const renderApp = ( core: CoreStart, @@ -87,7 +93,6 @@ const MonitoringApp: React.FC<{ /> {/* ElasticSearch Views */} - + {/* Kibana Views */} + + {/* Beats Views */} - {/* Kibana Views */} + {/* APM Views */} + + + + diff --git a/x-pack/plugins/monitoring/public/application/pages/apm/apm_template.tsx b/x-pack/plugins/monitoring/public/application/pages/apm/apm_template.tsx new file mode 100644 index 0000000000000..023370469a458 --- /dev/null +++ b/x-pack/plugins/monitoring/public/application/pages/apm/apm_template.tsx @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { PageTemplate } from '../page_template'; +import { TabMenuItem, PageTemplateProps } from '../page_template'; + +export const ApmTemplate: React.FC = ({ ...props }) => { + const tabs: TabMenuItem[] = [ + { + id: 'overview', + label: i18n.translate('xpack.monitoring.apmNavigation.overviewLinkText', { + defaultMessage: 'Overview', + }), + route: '/apm', + }, + { + id: 'instances', + label: i18n.translate('xpack.monitoring.apmNavigation.instancesLinkText', { + defaultMessage: 'Instances', + }), + route: '/apm/instances', + }, + ]; + + return ; +}; diff --git a/x-pack/plugins/monitoring/public/application/pages/apm/index.ts b/x-pack/plugins/monitoring/public/application/pages/apm/index.ts new file mode 100644 index 0000000000000..209e293c49353 --- /dev/null +++ b/x-pack/plugins/monitoring/public/application/pages/apm/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { ApmOverviewPage } from './overview'; +export { ApmInstancesPage } from './instances'; +export { ApmInstancePage } from './instance'; diff --git a/x-pack/plugins/monitoring/public/application/pages/apm/instance.tsx b/x-pack/plugins/monitoring/public/application/pages/apm/instance.tsx new file mode 100644 index 0000000000000..dc55ecb22b61a --- /dev/null +++ b/x-pack/plugins/monitoring/public/application/pages/apm/instance.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useContext, useState, useCallback, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; +import { find } from 'lodash'; +import { ComponentProps } from '../../route_init'; +import { GlobalStateContext } from '../../global_state_context'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { useCharts } from '../../hooks/use_charts'; +import { BreadcrumbContainer } from '../../hooks/use_breadcrumbs'; +import { PageTemplate } from '../page_template'; +// @ts-ignore +import { ApmServerInstance } from '../../../components/apm/instance'; + +export const ApmInstancePage: React.FC = ({ clusters }) => { + const { instance }: { instance: string } = useParams(); + + const globalState = useContext(GlobalStateContext); + const { services } = useKibana<{ data: any }>(); + const { generate: generateBreadcrumbs } = useContext(BreadcrumbContainer.Context); + const { zoomInfo, onBrush } = useCharts(); + const clusterUuid = globalState.cluster_uuid; + const ccs = globalState.ccs; + const cluster = find(clusters, { + cluster_uuid: clusterUuid, + }) as any; + const [data, setData] = useState({} as any); + const [instanceName, setInstanceName] = useState(''); + + const title = i18n.translate('xpack.monitoring.apm.instance.routeTitle', { + defaultMessage: '{apm} - Instance', + values: { + apm: 'APM server', + }, + }); + + const pageTitle = i18n.translate('xpack.monitoring.apm.instance.pageTitle', { + defaultMessage: 'APM server instance: {instanceName}', + values: { + instanceName, + }, + }); + + useEffect(() => { + if (cluster) { + generateBreadcrumbs(cluster.cluster_name, { + inApm: true, + instance: instanceName, + }); + } + }, [cluster, instanceName, generateBreadcrumbs]); + + const getPageData = useCallback(async () => { + const bounds = services.data?.query.timefilter.timefilter.getBounds(); + const url = `../api/monitoring/v1/clusters/${clusterUuid}/apm/${instance}`; + const response = await services.http?.fetch(url, { + method: 'POST', + body: JSON.stringify({ + ccs, + timeRange: { + min: bounds.min.toISOString(), + max: bounds.max.toISOString(), + }, + }), + }); + + setData(response); + setInstanceName(response.apmSummary.name); + }, [ccs, clusterUuid, instance, services.data?.query.timefilter.timefilter, services.http]); + + return ( + + + + ); +}; diff --git a/x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx b/x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx new file mode 100644 index 0000000000000..86ea8079277c7 --- /dev/null +++ b/x-pack/plugins/monitoring/public/application/pages/apm/instances.tsx @@ -0,0 +1,112 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useContext, useState, useCallback, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { find } from 'lodash'; +import { ComponentProps } from '../../route_init'; +import { GlobalStateContext } from '../../global_state_context'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { useTable } from '../../hooks/use_table'; +import { ApmTemplate } from './apm_template'; +// @ts-ignore +import { ApmServerInstances } from '../../../components/apm/instances'; +import { SetupModeRenderer } from '../../setup_mode/setup_mode_renderer'; +import { SetupModeContext } from '../../../components/setup_mode/setup_mode_context'; +import { BreadcrumbContainer } from '../../hooks/use_breadcrumbs'; + +interface SetupModeProps { + setupMode: any; + flyoutComponent: any; + bottomBarComponent: any; +} + +export const ApmInstancesPage: React.FC = ({ clusters }) => { + const globalState = useContext(GlobalStateContext); + const { services } = useKibana<{ data: any }>(); + const { generate: generateBreadcrumbs } = useContext(BreadcrumbContainer.Context); + const { updateTotalItemCount, getPaginationTableProps } = useTable('apm.instances'); + const clusterUuid = globalState.cluster_uuid; + const ccs = globalState.ccs; + const cluster = find(clusters, { + cluster_uuid: clusterUuid, + }) as any; + const [data, setData] = useState({} as any); + + const title = i18n.translate('xpack.monitoring.apm.instances.routeTitle', { + defaultMessage: '{apm} - Instances', + values: { + apm: 'APM server', + }, + }); + + const pageTitle = i18n.translate('xpack.monitoring.apm.instances.pageTitle', { + defaultMessage: 'APM server instances', + }); + + useEffect(() => { + if (cluster) { + generateBreadcrumbs(cluster.cluster_name, { + inApm: true, + }); + } + }, [cluster, generateBreadcrumbs]); + + const getPageData = useCallback(async () => { + const bounds = services.data?.query.timefilter.timefilter.getBounds(); + const url = `../api/monitoring/v1/clusters/${clusterUuid}/apm/instances`; + const response = await services.http?.fetch(url, { + method: 'POST', + body: JSON.stringify({ + ccs, + timeRange: { + min: bounds.min.toISOString(), + max: bounds.max.toISOString(), + }, + }), + }); + + setData(response); + updateTotalItemCount(response.stats.total); + }, [ + ccs, + clusterUuid, + services.data?.query.timefilter.timefilter, + services.http, + updateTotalItemCount, + ]); + + const { pagination, sorting, onTableChange } = getPaginationTableProps(); + + return ( + + ( + + {flyoutComponent} + + {bottomBarComponent} + + )} + /> + + ); +}; diff --git a/x-pack/plugins/monitoring/public/application/pages/apm/overview.tsx b/x-pack/plugins/monitoring/public/application/pages/apm/overview.tsx new file mode 100644 index 0000000000000..cca31c0a7e65d --- /dev/null +++ b/x-pack/plugins/monitoring/public/application/pages/apm/overview.tsx @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useContext, useState, useCallback, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { find } from 'lodash'; +import { ComponentProps } from '../../route_init'; +import { ApmTemplate } from './apm_template'; +import { GlobalStateContext } from '../../global_state_context'; +import { useCharts } from '../../hooks/use_charts'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { BreadcrumbContainer } from '../../hooks/use_breadcrumbs'; +// @ts-ignore +import { ApmOverview } from '../../../components/apm/overview'; + +export const ApmOverviewPage: React.FC = ({ clusters }) => { + const globalState = useContext(GlobalStateContext); + const { zoomInfo, onBrush } = useCharts(); + const { services } = useKibana<{ data: any }>(); + const clusterUuid = globalState.cluster_uuid; + const ccs = globalState.ccs; + const { generate: generateBreadcrumbs } = useContext(BreadcrumbContainer.Context); + const cluster = find(clusters, { + cluster_uuid: clusterUuid, + }) as any; + + const [data, setData] = useState(null); + + const title = i18n.translate('xpack.monitoring.apm.overview.routeTitle', { + defaultMessage: 'APM server', + }); + + const pageTitle = i18n.translate('xpack.monitoring.apm.overview.pageTitle', { + defaultMessage: 'APM server overview', + }); + + useEffect(() => { + if (cluster) { + generateBreadcrumbs(cluster.cluster_name, { + inApm: true, + }); + } + }, [cluster, generateBreadcrumbs]); + + const getPageData = useCallback(async () => { + const bounds = services.data?.query.timefilter.timefilter.getBounds(); + const url = `../api/monitoring/v1/clusters/${clusterUuid}/apm`; + + const response = await services.http?.fetch(url, { + method: 'POST', + body: JSON.stringify({ + ccs, + timeRange: { + min: bounds.min.toISOString(), + max: bounds.max.toISOString(), + }, + }), + }); + + setData(response); + }, [ccs, clusterUuid, services.data?.query.timefilter.timefilter, services.http]); + + return ( + + {data && } + + ); +}; From 00bb59713ed115343eb70d4e39059476edafbade Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 5 Oct 2021 09:13:14 +0200 Subject: [PATCH 86/98] [Uptime] Annotate waterfall chart with additional metrics (#103642) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/runtime_types/network_events.ts | 1 + .../use_step_waterfall_metrics.test.tsx | 102 ++++++++++++++++++ .../step_detail/use_step_waterfall_metrics.ts | 100 +++++++++++++++++ .../waterfall/waterfall_chart_container.tsx | 8 ++ .../waterfall_chart_wrapper.test.tsx | 6 +- .../waterfall/waterfall_chart_wrapper.tsx | 5 +- .../synthetics/waterfall/components/styles.ts | 5 + .../components/waterfall_bar_chart.tsx | 2 + .../components/waterfall_chart_fixed_axis.tsx | 2 + .../components/waterfall_markers.tsx | 96 +++++++++++++++++ .../waterfall/context/waterfall_chart.tsx | 15 +++ .../pages/synthetics/step_detail_page.tsx | 6 ++ .../public/state/reducers/network_events.ts | 13 ++- .../lib/requests/get_network_events.test.ts | 1 + .../server/lib/requests/get_network_events.ts | 47 +++++--- 15 files changed, 390 insertions(+), 19 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.ts create mode 100644 x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_markers.tsx diff --git a/x-pack/plugins/uptime/common/runtime_types/network_events.ts b/x-pack/plugins/uptime/common/runtime_types/network_events.ts index d24014aec8eab..0b717f46cedc8 100644 --- a/x-pack/plugins/uptime/common/runtime_types/network_events.ts +++ b/x-pack/plugins/uptime/common/runtime_types/network_events.ts @@ -56,6 +56,7 @@ export const SyntheticsNetworkEventsApiResponseType = t.type({ events: t.array(NetworkEventType), total: t.number, isWaterfallSupported: t.boolean, + hasNavigationRequest: t.boolean, }); export type SyntheticsNetworkEventsApiResponse = t.TypeOf< diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.test.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.test.tsx new file mode 100644 index 0000000000000..8b23d867572f3 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.test.tsx @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { renderHook } from '@testing-library/react-hooks'; +import { + BROWSER_TRACE_NAME, + BROWSER_TRACE_START, + BROWSER_TRACE_TYPE, + useStepWaterfallMetrics, +} from './use_step_waterfall_metrics'; +import * as reduxHooks from 'react-redux'; +import * as searchHooks from '../../../../../../observability/public/hooks/use_es_search'; + +describe('useStepWaterfallMetrics', () => { + jest + .spyOn(reduxHooks, 'useSelector') + .mockReturnValue({ settings: { heartbeatIndices: 'heartbeat-*' } }); + + it('returns result as expected', () => { + // @ts-ignore + const searchHook = jest.spyOn(searchHooks, 'useEsSearch').mockReturnValue({ + loading: false, + data: { + hits: { + total: { value: 2, relation: 'eq' }, + hits: [ + { + fields: { + [BROWSER_TRACE_TYPE]: ['mark'], + [BROWSER_TRACE_NAME]: ['navigationStart'], + [BROWSER_TRACE_START]: [3456789], + }, + }, + { + fields: { + [BROWSER_TRACE_TYPE]: ['mark'], + [BROWSER_TRACE_NAME]: ['domContentLoaded'], + [BROWSER_TRACE_START]: [4456789], + }, + }, + ], + }, + } as any, + }); + + const { result } = renderHook( + (props) => + useStepWaterfallMetrics({ + checkGroup: '44D-444FFF-444-FFF-3333', + hasNavigationRequest: true, + stepIndex: 1, + }), + {} + ); + + expect(searchHook).toHaveBeenCalledWith( + { + body: { + _source: false, + fields: ['browser.*'], + query: { + bool: { + filter: [ + { + term: { + 'synthetics.step.index': 1, + }, + }, + { + term: { + 'monitor.check_group': '44D-444FFF-444-FFF-3333', + }, + }, + { + term: { + 'synthetics.type': 'step/metrics', + }, + }, + ], + }, + }, + size: 1000, + }, + index: 'heartbeat-*', + }, + ['heartbeat-*', '44D-444FFF-444-FFF-3333', true] + ); + expect(result.current).toEqual({ + loading: false, + metrics: [ + { + id: 'domContentLoaded', + offset: 1000, + }, + ], + }); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.ts b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.ts new file mode 100644 index 0000000000000..cf60f6d7d5567 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/use_step_waterfall_metrics.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useSelector } from 'react-redux'; +import { createEsParams, useEsSearch } from '../../../../../../observability/public'; +import { selectDynamicSettings } from '../../../../state/selectors'; +import { MarkerItems } from '../waterfall/context/waterfall_chart'; + +export interface Props { + checkGroup: string; + stepIndex: number; + hasNavigationRequest?: boolean; +} +export const BROWSER_TRACE_TYPE = 'browser.relative_trace.type'; +export const BROWSER_TRACE_NAME = 'browser.relative_trace.name'; +export const BROWSER_TRACE_START = 'browser.relative_trace.start.us'; +export const NAVIGATION_START = 'navigationStart'; + +export const useStepWaterfallMetrics = ({ checkGroup, hasNavigationRequest, stepIndex }: Props) => { + const { settings } = useSelector(selectDynamicSettings); + + const heartbeatIndices = settings?.heartbeatIndices || ''; + + const { data, loading } = useEsSearch( + hasNavigationRequest + ? createEsParams({ + index: heartbeatIndices!, + body: { + query: { + bool: { + filter: [ + { + term: { + 'synthetics.step.index': stepIndex, + }, + }, + { + term: { + 'monitor.check_group': checkGroup, + }, + }, + { + term: { + 'synthetics.type': 'step/metrics', + }, + }, + ], + }, + }, + fields: ['browser.*'], + size: 1000, + _source: false, + }, + }) + : {}, + [heartbeatIndices, checkGroup, hasNavigationRequest] + ); + + if (!hasNavigationRequest) { + return { metrics: [], loading: false }; + } + + const metrics: MarkerItems = []; + + if (data && hasNavigationRequest) { + const metricDocs = data.hits.hits as unknown as Array<{ fields: any }>; + let navigationStart = 0; + let navigationStartExist = false; + + metricDocs.forEach(({ fields }) => { + if (fields[BROWSER_TRACE_TYPE]?.[0] === 'mark') { + const { [BROWSER_TRACE_NAME]: metricType, [BROWSER_TRACE_START]: metricValue } = fields; + if (metricType?.[0] === NAVIGATION_START) { + navigationStart = metricValue?.[0]; + navigationStartExist = true; + } + } + }); + + if (navigationStartExist) { + metricDocs.forEach(({ fields }) => { + if (fields[BROWSER_TRACE_TYPE]?.[0] === 'mark') { + const { [BROWSER_TRACE_NAME]: metricType, [BROWSER_TRACE_START]: metricValue } = fields; + if (metricType?.[0] !== NAVIGATION_START) { + metrics.push({ + id: metricType?.[0], + offset: (metricValue?.[0] - navigationStart) / 1000, + }); + } + } + }); + } + } + + return { metrics, loading }; +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_container.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_container.tsx index 044353125e748..d249c23c44d75 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_container.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_container.tsx @@ -14,6 +14,7 @@ import { getNetworkEvents } from '../../../../../state/actions/network_events'; import { networkEventsSelector } from '../../../../../state/selectors'; import { WaterfallChartWrapper } from './waterfall_chart_wrapper'; import { extractItems } from './data_formatting'; +import { useStepWaterfallMetrics } from '../use_step_waterfall_metrics'; export const NO_DATA_TEXT = i18n.translate('xpack.uptime.synthetics.stepDetail.waterfallNoData', { defaultMessage: 'No waterfall data could be found for this step', @@ -44,6 +45,12 @@ export const WaterfallChartContainer: React.FC = ({ checkGroup, stepIndex const isWaterfallSupported = networkEvents?.isWaterfallSupported; const hasEvents = networkEvents?.events?.length > 0; + const { metrics } = useStepWaterfallMetrics({ + checkGroup, + stepIndex, + hasNavigationRequest: networkEvents?.hasNavigationRequest, + }); + return ( <> {!waterfallLoaded && ( @@ -70,6 +77,7 @@ export const WaterfallChartContainer: React.FC = ({ checkGroup, stepIndex {waterfallLoaded && hasEvents && isWaterfallSupported && ( )} diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.test.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.test.tsx index fbb6f2c75a540..81ed2d024340c 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.test.tsx @@ -31,7 +31,11 @@ describe('WaterfallChartWrapper', () => { it('renders the correct sidebar items', () => { const { getAllByTestId } = render( - + ); const sideBarItems = getAllByTestId('middleTruncatedTextSROnly'); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx index 26be3cbadee45..8071fd1e3c4d3 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/waterfall/waterfall_chart_wrapper.tsx @@ -14,6 +14,7 @@ import { useTrackMetric, METRIC_TYPE } from '../../../../../../../observability/ import { WaterfallFilter } from './waterfall_filter'; import { WaterfallFlyout } from './waterfall_flyout'; import { WaterfallSidebarItem } from './waterfall_sidebar_item'; +import { MarkerItems } from '../../waterfall/context/waterfall_chart'; export const renderLegendItem: RenderItem = (item) => { return ( @@ -26,9 +27,10 @@ export const renderLegendItem: RenderItem = (item) => { interface Props { total: number; data: NetworkItems; + markerItems?: MarkerItems; } -export const WaterfallChartWrapper: React.FC = ({ data, total }) => { +export const WaterfallChartWrapper: React.FC = ({ data, total, markerItems }) => { const [query, setQuery] = useState(''); const [activeFilters, setActiveFilters] = useState([]); const [onlyHighlighted, setOnlyHighlighted] = useState(false); @@ -107,6 +109,7 @@ export const WaterfallChartWrapper: React.FC = ({ data, total }) => { return ( props.theme.eui.euiZLevel4}; height: 100%; + &&& { + .echAnnotation__icon { + top: 8px; + } + } `; interface WaterfallChartSidebarContainer { diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_bar_chart.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_bar_chart.tsx index 8723dd744132a..d4a7cf6a1f66f 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_bar_chart.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_bar_chart.tsx @@ -24,6 +24,7 @@ import { WaterfallChartChartContainer, WaterfallChartTooltip } from './styles'; import { useWaterfallContext, WaterfallData } from '..'; import { WaterfallTooltipContent } from './waterfall_tooltip_content'; import { formatTooltipHeading } from '../../step_detail/waterfall/data_formatting'; +import { WaterfallChartMarkers } from './waterfall_markers'; const getChartHeight = (data: WaterfallData): number => { // We get the last item x(number of bars) and adds 1 to cater for 0 index @@ -120,6 +121,7 @@ export const WaterfallBarChart = ({ styleAccessor={barStyleAccessor} data={chartData} /> + ); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart_fixed_axis.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart_fixed_axis.tsx index 3a7ab421b6277..3824b9ae19d0f 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart_fixed_axis.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart_fixed_axis.tsx @@ -20,6 +20,7 @@ import { } from '@elastic/charts'; import { useChartTheme } from '../../../../../hooks/use_chart_theme'; import { WaterfallChartFixedAxisContainer } from './styles'; +import { WaterfallChartMarkers } from './waterfall_markers'; interface Props { tickFormat: TickFormatter; @@ -59,6 +60,7 @@ export const WaterfallChartFixedAxis = ({ tickFormat, domain, barStyleAccessor } styleAccessor={barStyleAccessor} data={[{ x: 0, y0: 0, y1: 1 }]} /> + ); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_markers.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_markers.tsx new file mode 100644 index 0000000000000..b341b052e0102 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_markers.tsx @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { AnnotationDomainType, LineAnnotation } from '@elastic/charts'; +import { EuiIcon } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useWaterfallContext } from '..'; +import { useTheme } from '../../../../../../../observability/public'; +import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; + +export const FCP_LABEL = i18n.translate('xpack.uptime.synthetics.waterfall.fcpLabel', { + defaultMessage: 'First contentful paint', +}); + +export const LCP_LABEL = i18n.translate('xpack.uptime.synthetics.waterfall.lcpLabel', { + defaultMessage: 'Largest contentful paint', +}); + +export const LAYOUT_SHIFT_LABEL = i18n.translate( + 'xpack.uptime.synthetics.waterfall.layoutShiftLabel', + { + defaultMessage: 'Layout shift', + } +); + +export const LOAD_EVENT_LABEL = i18n.translate('xpack.uptime.synthetics.waterfall.loadEventLabel', { + defaultMessage: 'Load event', +}); + +export const DOCUMENT_CONTENT_LOADED_LABEL = i18n.translate( + 'xpack.uptime.synthetics.waterfall.domContentLabel', + { + defaultMessage: 'DOM Content Loaded', + } +); + +export function WaterfallChartMarkers() { + const { markerItems } = useWaterfallContext(); + + const theme = useTheme(); + + if (!markerItems) { + return null; + } + + const markersInfo: Record = { + domContentLoaded: { label: DOCUMENT_CONTENT_LOADED_LABEL, color: theme.eui.euiColorVis0 }, + firstContentfulPaint: { label: FCP_LABEL, color: theme.eui.euiColorVis1 }, + largestContentfulPaint: { label: LCP_LABEL, color: theme.eui.euiColorVis2 }, + layoutShift: { label: LAYOUT_SHIFT_LABEL, color: theme.eui.euiColorVis3 }, + loadEvent: { label: LOAD_EVENT_LABEL, color: theme.eui.euiColorVis9 }, + }; + + return ( + + {markerItems.map(({ id, offset }) => ( + } + style={{ + line: { + strokeWidth: 2, + stroke: markersInfo[id]?.color ?? theme.eui.euiColorMediumShade, + opacity: 1, + }, + }} + /> + ))} + + ); +} + +const Wrapper = euiStyled.span` + &&& { + > .echAnnotation__icon { + top: 8px; + } + } +`; diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/context/waterfall_chart.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/context/waterfall_chart.tsx index 16b3a24de7d0c..cce0533293e07 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/context/waterfall_chart.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/context/waterfall_chart.tsx @@ -10,6 +10,17 @@ import { WaterfallData, WaterfallDataEntry, WaterfallMetadata } from '../types'; import { OnSidebarClick, OnElementClick, OnProjectionClick } from '../components/use_flyout'; import { SidebarItems } from '../../step_detail/waterfall/types'; +export type MarkerItems = Array<{ + id: + | 'domContentLoaded' + | 'firstContentfulPaint' + | 'largestContentfulPaint' + | 'layoutShift' + | 'loadEvent' + | 'navigationStart'; + offset: number; +}>; + export interface IWaterfallContext { totalNetworkRequests: number; highlightedNetworkRequests: number; @@ -26,6 +37,7 @@ export interface IWaterfallContext { item: WaterfallDataEntry['config']['tooltipProps'], index?: number ) => JSX.Element; + markerItems?: MarkerItems; } export const WaterfallContext = createContext>({}); @@ -43,11 +55,13 @@ interface ProviderProps { legendItems?: IWaterfallContext['legendItems']; metadata: IWaterfallContext['metadata']; renderTooltipItem: IWaterfallContext['renderTooltipItem']; + markerItems?: MarkerItems; } export const WaterfallProvider: React.FC = ({ children, data, + markerItems, onElementClick, onProjectionClick, onSidebarClick, @@ -64,6 +78,7 @@ export const WaterfallProvider: React.FC = ({ { /> ); }; +import { getDynamicSettings } from '../../state/actions/dynamic_settings'; export const StepDetailPage: React.FC = () => { useInitApp(); const { checkGroupId, stepIndex } = useParams<{ checkGroupId: string; stepIndex: string }>(); useTrackPageview({ app: 'uptime', path: 'stepDetail' }); useTrackPageview({ app: 'uptime', path: 'stepDetail', delay: 15000 }); + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getDynamicSettings()); + }, [dispatch]); return ; }; diff --git a/x-pack/plugins/uptime/public/state/reducers/network_events.ts b/x-pack/plugins/uptime/public/state/reducers/network_events.ts index 56fef5947fb0e..e58a8f75c7fa3 100644 --- a/x-pack/plugins/uptime/public/state/reducers/network_events.ts +++ b/x-pack/plugins/uptime/public/state/reducers/network_events.ts @@ -23,6 +23,7 @@ export interface NetworkEventsState { loading: boolean; error?: Error; isWaterfallSupported: boolean; + hasNavigationRequest?: boolean; }; }; } @@ -71,7 +72,14 @@ export const networkEventsReducer = handleActions( [String(getNetworkEventsSuccess)]: ( state: NetworkEventsState, { - payload: { events, total, checkGroup, stepIndex, isWaterfallSupported }, + payload: { + events, + total, + checkGroup, + stepIndex, + isWaterfallSupported, + hasNavigationRequest, + }, }: Action ) => { return { @@ -85,12 +93,14 @@ export const networkEventsReducer = handleActions( events, total, isWaterfallSupported, + hasNavigationRequest, } : { loading: false, events, total, isWaterfallSupported, + hasNavigationRequest, }, } : { @@ -99,6 +109,7 @@ export const networkEventsReducer = handleActions( events, total, isWaterfallSupported, + hasNavigationRequest, }, }, }; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts index b7f417168fd3a..e0cd17327a9b6 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts @@ -298,6 +298,7 @@ describe('getNetworkEvents', () => { "url": "www.test.com", }, ], + "hasNavigationRequest": false, "isWaterfallSupported": true, "total": 1, } diff --git a/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts b/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts index b27b1a4c736d5..20e5c3a2a1185 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts @@ -20,7 +20,12 @@ export const secondsToMillis = (seconds: number) => export const getNetworkEvents: UMElasticsearchQueryFn< GetNetworkEventsParams, - { events: NetworkEvent[]; total: number; isWaterfallSupported: boolean } + { + events: NetworkEvent[]; + total: number; + isWaterfallSupported: boolean; + hasNavigationRequest: boolean; + } > = async ({ uptimeEsClient, checkGroup, stepIndex }) => { const params = { track_total_hits: true, @@ -41,25 +46,34 @@ export const getNetworkEvents: UMElasticsearchQueryFn< const { body: result } = await uptimeEsClient.search({ body: params }); let isWaterfallSupported = false; + let hasNavigationRequest = false; + const events = result.hits.hits.map((event: any) => { - if (event._source.http && event._source.url) { + const docSource = event._source; + + if (docSource.http && docSource.url) { isWaterfallSupported = true; } - const requestSentTime = secondsToMillis(event._source.synthetics.payload.request_sent_time); - const loadEndTime = secondsToMillis(event._source.synthetics.payload.load_end_time); - const securityDetails = event._source.tls?.server?.x509; + const requestSentTime = secondsToMillis(docSource.synthetics.payload.request_sent_time); + const loadEndTime = secondsToMillis(docSource.synthetics.payload.load_end_time); + const securityDetails = docSource.tls?.server?.x509; + + if (docSource.synthetics.payload?.is_navigation_request) { + // if step has navigation request, this means we will display waterfall metrics in ui + hasNavigationRequest = true; + } return { - timestamp: event._source['@timestamp'], - method: event._source.http?.request?.method, - url: event._source.url?.full, - status: event._source.http?.response?.status, - mimeType: event._source.http?.response?.mime_type, + timestamp: docSource['@timestamp'], + method: docSource.http?.request?.method, + url: docSource.url?.full, + status: docSource.http?.response?.status, + mimeType: docSource.http?.response?.mime_type, requestSentTime, loadEndTime, - timings: event._source.synthetics.payload.timings, - transferSize: event._source.synthetics.payload.transfer_size, - resourceSize: event._source.synthetics.payload.resource_size, + timings: docSource.synthetics.payload.timings, + transferSize: docSource.synthetics.payload.transfer_size, + resourceSize: docSource.synthetics.payload.resource_size, certificates: securityDetails ? { issuer: securityDetails.issuer?.common_name, @@ -68,9 +82,9 @@ export const getNetworkEvents: UMElasticsearchQueryFn< validTo: securityDetails.not_after, } : undefined, - requestHeaders: event._source.http?.request?.headers, - responseHeaders: event._source.http?.response?.headers, - ip: event._source.http?.response?.remote_i_p_address, + requestHeaders: docSource.http?.request?.headers, + responseHeaders: docSource.http?.response?.headers, + ip: docSource.http?.response?.remote_i_p_address, }; }); @@ -78,5 +92,6 @@ export const getNetworkEvents: UMElasticsearchQueryFn< total: result.hits.total.value, events, isWaterfallSupported, + hasNavigationRequest, }; }; From 723370ab23573e50b3524a62c6b9998f2042423d Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 5 Oct 2021 10:52:31 +0200 Subject: [PATCH 87/98] Refactor (#113699) * refactors timeline test * tries to remove flakiness on indicator match test * fixes issues Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../timeline_templates/creation.spec.ts | 24 +++++++------------ .../integration/timelines/creation.spec.ts | 24 +++++++++---------- .../cypress/screens/templates.ts | 8 +++++++ .../cypress/tasks/alerts_detection_rules.ts | 12 ++++------ .../cypress/tasks/templates.ts | 12 ++++++++++ .../cypress/tasks/timeline.ts | 7 +++++- .../cypress/tasks/timelines.ts | 7 ++++-- .../open_timeline/search_row/index.tsx | 3 ++- .../open_timeline/use_timeline_status.tsx | 1 + 9 files changed, 60 insertions(+), 38 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/screens/templates.ts create mode 100644 x-pack/plugins/security_solution/cypress/tasks/templates.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts index 3930088f8bfdd..48269677466b6 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts @@ -51,12 +51,11 @@ import { TIMELINES_URL } from '../../urls/navigation'; describe('Timeline Templates', () => { beforeEach(() => { cleanKibana(); - loginAndWaitForPageWithoutDateRange(TIMELINES_URL); - cy.intercept('PATCH', '/api/timeline').as('timeline'); }); it('Creates a timeline template', async () => { + loginAndWaitForPageWithoutDateRange(TIMELINES_URL); openTimelineUsingToggle(); createNewTimelineTemplate(); populateTimeline(); @@ -103,20 +102,15 @@ describe('Timeline Templates', () => { }); it('Create template from timeline', () => { + createTimeline(getTimeline()); + loginAndWaitForPageWithoutDateRange(TIMELINES_URL); waitForTimelinesPanelToBeLoaded(); + expandEventAction(); + clickingOnCreateTemplateFromTimelineBtn(); - createTimeline(getTimeline()).then(() => { - expandEventAction(); - clickingOnCreateTemplateFromTimelineBtn(); - cy.wait('@timeline', { timeout: 100000 }).then(({ request }) => { - expect(request.body.timeline).to.haveOwnProperty('templateTimelineId'); - expect(request.body.timeline).to.haveOwnProperty('description', getTimeline().description); - expect(request.body.timeline.kqlQuery.filterQuery.kuery).to.haveOwnProperty( - 'expression', - getTimeline().query - ); - cy.get(TIMELINE_FLYOUT_WRAPPER).should('have.css', 'visibility', 'visible'); - }); - }); + cy.wait('@timeline', { timeout: 100000 }); + cy.get(TIMELINE_FLYOUT_WRAPPER).should('have.css', 'visibility', 'visible'); + cy.get(TIMELINE_DESCRIPTION).should('have.text', getTimeline().description); + cy.get(TIMELINE_QUERY).should('have.text', getTimeline().query); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts index 6b86957c78e6e..fb41aec91b6c4 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts @@ -23,9 +23,9 @@ import { import { createTimelineTemplate } from '../../tasks/api_calls/timelines'; import { cleanKibana } from '../../tasks/common'; - import { loginAndWaitForPage, loginAndWaitForPageWithoutDateRange } from '../../tasks/login'; import { openTimelineUsingToggle } from '../../tasks/security_main'; +import { selectCustomTemplates } from '../../tasks/templates'; import { addEqlToTimeline, addFilter, @@ -115,22 +115,22 @@ describe('Timelines', (): void => { describe('Create a timeline from a template', () => { before(() => { + cy.intercept('/api/timeline*').as('timeline'); cleanKibana(); + createTimelineTemplate(getTimeline()); loginAndWaitForPageWithoutDateRange(TIMELINE_TEMPLATES_URL); waitForTimelinesPanelToBeLoaded(); }); it('Should have the same query and open the timeline modal', () => { - createTimelineTemplate(getTimeline()).then(() => { - expandEventAction(); - cy.intercept('/api/timeline').as('timeline'); - - clickingOnCreateTimelineFormTemplateBtn(); - cy.wait('@timeline', { timeout: 100000 }); - - cy.get(TIMELINE_FLYOUT_WRAPPER).should('have.css', 'visibility', 'visible'); - cy.get(TIMELINE_DESCRIPTION).should('have.text', getTimeline().description); - cy.get(TIMELINE_QUERY).should('have.text', getTimeline().query); - }); + selectCustomTemplates(); + cy.wait('@timeline', { timeout: 100000 }); + expandEventAction(); + clickingOnCreateTimelineFormTemplateBtn(); + cy.wait('@timeline', { timeout: 100000 }); + + cy.get(TIMELINE_FLYOUT_WRAPPER).should('have.css', 'visibility', 'visible'); + cy.get(TIMELINE_DESCRIPTION).should('have.text', getTimeline().description); + cy.get(TIMELINE_QUERY).should('have.text', getTimeline().query); }); }); diff --git a/x-pack/plugins/security_solution/cypress/screens/templates.ts b/x-pack/plugins/security_solution/cypress/screens/templates.ts new file mode 100644 index 0000000000000..65fab879b1432 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/screens/templates.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const CUSTOM_TEMPLATES = '[data-test-subj="Custom templates"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts index 7d2116cff7bfb..6b985c7009b27 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts @@ -72,15 +72,13 @@ export const duplicateFirstRule = () => { * flake. */ export const duplicateRuleFromMenu = () => { + const click = ($el: Cypress.ObjectLike) => cy.wrap($el).click({ force: true }); cy.get(LOADING_INDICATOR).should('not.exist'); - cy.root() - .pipe(($el) => { - $el.find(ALL_ACTIONS).trigger('click'); - return $el.find(DUPLICATE_RULE_MENU_PANEL_BTN); - }) - .should(($el) => expect($el).to.be.visible); + cy.get(ALL_ACTIONS).pipe(click); + cy.get(DUPLICATE_RULE_MENU_PANEL_BTN).should('be.visible'); + // Because of a fade effect and fast clicking this can produce more than one click - cy.get(DUPLICATE_RULE_MENU_PANEL_BTN).pipe(($el) => $el.trigger('click')); + cy.get(DUPLICATE_RULE_MENU_PANEL_BTN).pipe(click); }; /** diff --git a/x-pack/plugins/security_solution/cypress/tasks/templates.ts b/x-pack/plugins/security_solution/cypress/tasks/templates.ts new file mode 100644 index 0000000000000..6490a7c1df717 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/tasks/templates.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CUSTOM_TEMPLATES } from '../screens/templates'; + +export const selectCustomTemplates = () => { + cy.get(CUSTOM_TEMPLATES).click({ force: true }); +}; diff --git a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts index 03ccb784bd259..039e8ed44886e 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts @@ -390,5 +390,10 @@ export const clickingOnCreateTemplateFromTimelineBtn = () => { }; export const expandEventAction = () => { - cy.get(TIMELINE_COLLAPSED_ITEMS_BTN).first().click(); + cy.waitUntil(() => { + cy.get(TIMELINE_COLLAPSED_ITEMS_BTN).should('exist'); + cy.get(TIMELINE_COLLAPSED_ITEMS_BTN).should('be.visible'); + return cy.get(TIMELINE_COLLAPSED_ITEMS_BTN).then(($el) => $el.length === 1); + }); + cy.get(TIMELINE_COLLAPSED_ITEMS_BTN).click(); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/timelines.ts b/x-pack/plugins/security_solution/cypress/tasks/timelines.ts index bda78955a2449..a135ce8c90510 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/timelines.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/timelines.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { LOADING_INDICATOR } from '../screens/security_header'; import { TIMELINE_CHECKBOX, BULK_ACTIONS, @@ -24,6 +25,8 @@ export const openTimeline = (id: string) => { cy.get(TIMELINE(id)).should('be.visible').pipe(click); }; -export const waitForTimelinesPanelToBeLoaded = (): Cypress.Chainable> => { - return cy.get(TIMELINES_TABLE).should('exist'); +export const waitForTimelinesPanelToBeLoaded = () => { + cy.get(LOADING_INDICATOR).should('exist'); + cy.get(LOADING_INDICATOR).should('not.exist'); + cy.get(TIMELINES_TABLE).should('exist'); }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/search_row/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/search_row/index.tsx index d1f95496bb70c..15f97b72855fc 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/search_row/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/search_row/index.tsx @@ -62,6 +62,7 @@ export const SearchRow = React.memo( ? i18n.SEARCH_PLACEHOLDER : i18n.SEARCH_TEMPLATE_PLACEHOLDER, incremental: false, + 'data-test-subj': 'search-bar', }), [timelineType] ); @@ -70,7 +71,7 @@ export const SearchRow = React.memo( - + diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_status.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_status.tsx index 060212d0972de..097919d7e6f08 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_status.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/use_timeline_status.tsx @@ -97,6 +97,7 @@ export const useTimelineStatus = ({ onClick={onFilterClicked.bind(null, tab.id)} withNext={tab.withNext} isDisabled={tab.disabled} + data-test-subj={tab.name} > {tab.name} From ae7a6cffeb6048a1333aed307d4f39297acfd1bb Mon Sep 17 00:00:00 2001 From: Cristina Amico Date: Tue, 5 Oct 2021 11:50:52 +0200 Subject: [PATCH 88/98] [Fleet] Set code editor height to solve an overlap in default policy settings (#113763) --- .../package_policy_input_var_field.tsx | 58 +++++++++++-------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx index 398421278b723..954addd4202b1 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx @@ -17,12 +17,17 @@ import { EuiFieldPassword, EuiCodeBlock, } from '@elastic/eui'; +import styled from 'styled-components'; import type { RegistryVarsEntry } from '../../../../types'; import { CodeEditor } from '../../../../../../../../../../src/plugins/kibana_react/public'; import { MultiTextInput } from './multi_text_input'; +const FixedHeightDiv = styled.div` + height: 300px; +`; + export const PackagePolicyInputVarField: React.FunctionComponent<{ varDef: RegistryVarsEntry; value: any; @@ -55,31 +60,34 @@ export const PackagePolicyInputVarField: React.FunctionComponent<{
    {value}
    ) : ( - + + + ); case 'bool': return ( From b62566da335f1f761709e5dea389f87d667ba278 Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Tue, 5 Oct 2021 12:57:40 +0300 Subject: [PATCH 89/98] [ci-stats] Collects additional timings for cli tools (#113030) * [ci-stats] Collects additional metrics about bootstrap Signed-off-by: Tyler Smalley * test reporting * [ci-stats] Collects additional metrics about bootstrap Signed-off-by: Tyler Smalley * Move ts timing to build_ts_refs_cli script Signed-off-by: Tyler Smalley * Add timings to run Signed-off-by: Tyler Smalley * info debug level Signed-off-by: Tyler Smalley * fix build * Move report function to dev-utils align name of tests report from functional test runner * report snapshot install \ ready times fix event names * Report memory usage and branch hash * fix eslint * fix integration test * build * mergy merge * mergy merge 2 * eslint * eslint * ready events * Update packages/kbn-es/src/cli_commands/snapshot.js Co-authored-by: Tyler Smalley * Update packages/kbn-es/src/cluster.js Co-authored-by: Tyler Smalley * Update packages/kbn-es/src/cli_commands/snapshot.js Co-authored-by: Tyler Smalley * Update packages/kbn-test/src/functional_tests/cli/start_servers/cli.js Co-authored-by: Tyler Smalley * Update src/dev/run_check_published_api_changes.ts Co-authored-by: Tyler Smalley * Update packages/kbn-test/src/jest/run.ts Co-authored-by: Tyler Smalley * Update src/dev/run_i18n_check.ts Co-authored-by: Tyler Smalley * Update packages/kbn-test/src/functional_test_runner/cli.ts Co-authored-by: Tyler Smalley * code review * pm * merge * dist * jest fix Co-authored-by: Tyler Smalley Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Tyler Smalley --- .../ci_stats_reporter/ci_stats_reporter.ts | 21 +++++++++++++--- .../src/ci_stats_reporter/index.ts | 1 + .../src/ci_stats_reporter/report_time.ts | 25 +++++++++++++++++++ packages/kbn-es/src/cli_commands/snapshot.js | 20 ++++++++++++++- packages/kbn-es/src/cluster.js | 18 ++++++++++++- packages/kbn-pm/dist/index.js | 23 ++++++++++++++--- .../src/functional_test_runner/cli.ts | 18 ++++++++++++- .../functional_tests/cli/start_servers/cli.js | 4 ++- .../kbn-test/src/functional_tests/tasks.ts | 16 ++++++++++-- packages/kbn-test/src/jest/run.ts | 21 +++++++++++++--- src/dev/run_check_published_api_changes.ts | 19 +++++++++++++- src/dev/run_i18n_check.ts | 23 +++++++++++++++-- 12 files changed, 190 insertions(+), 19 deletions(-) create mode 100644 packages/kbn-dev-utils/src/ci_stats_reporter/report_time.ts diff --git a/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts b/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts index 4d6ea646b2ab1..45d31c1eefad9 100644 --- a/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts +++ b/packages/kbn-dev-utils/src/ci_stats_reporter/ci_stats_reporter.ts @@ -82,6 +82,7 @@ export class CiStatsReporter { const upstreamBranch = options.upstreamBranch ?? this.getUpstreamBranch(); const kibanaUuid = options.kibanaUuid === undefined ? this.getKibanaUuid() : options.kibanaUuid; let email; + let branch; try { const { stdout } = await execa('git', ['config', 'user.email']); @@ -90,19 +91,33 @@ export class CiStatsReporter { this.log.debug(e.message); } + try { + const { stdout } = await execa('git', ['branch', '--show-current']); + branch = stdout; + } catch (e) { + this.log.debug(e.message); + } + + const memUsage = process.memoryUsage(); const isElasticCommitter = email && email.endsWith('@elastic.co') ? true : false; const defaultMetadata = { + kibanaUuid, + isElasticCommitter, committerHash: email ? crypto.createHash('sha256').update(email).digest('hex').substring(0, 20) : undefined, + email: isElasticCommitter ? email : undefined, + branch: isElasticCommitter ? branch : undefined, cpuCount: Os.cpus()?.length, cpuModel: Os.cpus()[0]?.model, cpuSpeed: Os.cpus()[0]?.speed, - email: isElasticCommitter ? email : undefined, freeMem: Os.freemem(), - isElasticCommitter, - kibanaUuid, + memoryUsageRss: memUsage.rss, + memoryUsageHeapTotal: memUsage.heapTotal, + memoryUsageHeapUsed: memUsage.heapUsed, + memoryUsageExternal: memUsage.external, + memoryUsageArrayBuffers: memUsage.arrayBuffers, nestedTiming: process.env.CI_STATS_NESTED_TIMING ? true : false, osArch: Os.arch(), osPlatform: Os.platform(), diff --git a/packages/kbn-dev-utils/src/ci_stats_reporter/index.ts b/packages/kbn-dev-utils/src/ci_stats_reporter/index.ts index d99217c38b410..9cb05608526eb 100644 --- a/packages/kbn-dev-utils/src/ci_stats_reporter/index.ts +++ b/packages/kbn-dev-utils/src/ci_stats_reporter/index.ts @@ -8,3 +8,4 @@ export * from './ci_stats_reporter'; export * from './ship_ci_stats_cli'; +export { getTimeReporter } from './report_time'; diff --git a/packages/kbn-dev-utils/src/ci_stats_reporter/report_time.ts b/packages/kbn-dev-utils/src/ci_stats_reporter/report_time.ts new file mode 100644 index 0000000000000..d10250a03f091 --- /dev/null +++ b/packages/kbn-dev-utils/src/ci_stats_reporter/report_time.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CiStatsReporter, ToolingLog } from '..'; + +export const getTimeReporter = (log: ToolingLog, group: string) => { + const reporter = CiStatsReporter.fromEnv(log); + return async (startTime: number, id: string, meta: Record) => { + await reporter.timings({ + timings: [ + { + group, + id, + ms: Date.now() - startTime, + meta, + }, + ], + }); + }; +}; diff --git a/packages/kbn-es/src/cli_commands/snapshot.js b/packages/kbn-es/src/cli_commands/snapshot.js index 7f5653db72b49..e64dcb7c77318 100644 --- a/packages/kbn-es/src/cli_commands/snapshot.js +++ b/packages/kbn-es/src/cli_commands/snapshot.js @@ -8,6 +8,7 @@ const dedent = require('dedent'); const getopts = require('getopts'); +import { ToolingLog, getTimeReporter } from '@kbn/dev-utils'; const { Cluster } = require('../cluster'); exports.description = 'Downloads and run from a nightly snapshot'; @@ -36,6 +37,13 @@ exports.help = (defaults = {}) => { }; exports.run = async (defaults = {}) => { + const runStartTime = Date.now(); + const log = new ToolingLog({ + level: 'info', + writeTo: process.stdout, + }); + const reportTime = getTimeReporter(log, 'scripts/es snapshot'); + const argv = process.argv.slice(2); const options = getopts(argv, { alias: { @@ -56,12 +64,22 @@ exports.run = async (defaults = {}) => { if (options['download-only']) { await cluster.downloadSnapshot(options); } else { + const installStartTime = Date.now(); const { installPath } = await cluster.installSnapshot(options); if (options.dataArchive) { await cluster.extractDataDirectory(installPath, options.dataArchive); } - await cluster.run(installPath, options); + reportTime(installStartTime, 'installed', { + success: true, + ...options, + }); + + await cluster.run(installPath, { + reportTime, + startTime: runStartTime, + ...options, + }); } }; diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index ac4380da88be0..0866b14f4ade8 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -240,7 +240,7 @@ exports.Cluster = class Cluster { * @return {undefined} */ _exec(installPath, opts = {}) { - const { skipNativeRealmSetup = false, ...options } = opts; + const { skipNativeRealmSetup = false, reportTime = () => {}, startTime, ...options } = opts; if (this._process || this._outcome) { throw new Error('ES has already been started'); @@ -321,10 +321,17 @@ exports.Cluster = class Cluster { await nativeRealm.setPasswords(options); }); + let reportSent = false; // parse and forward es stdout to the log this._process.stdout.on('data', (data) => { const lines = parseEsLog(data.toString()); lines.forEach((line) => { + if (!reportSent && line.message.includes('publish_address')) { + reportSent = true; + reportTime(startTime, 'ready', { + success: true, + }); + } this._log.info(line.formattedMessage); }); }); @@ -341,7 +348,16 @@ exports.Cluster = class Cluster { // JVM exits with 143 on SIGTERM and 130 on SIGINT, dont' treat them as errors if (code > 0 && !(code === 143 || code === 130)) { + reportTime(startTime, 'abort', { + success: true, + error: code, + }); throw createCliError(`ES exited with code ${code}`); + } else { + reportTime(startTime, 'error', { + success: false, + error: `exited with ${code}`, + }); } }); } diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index c96a1eb28cfce..cab1f6d916f02 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -9014,6 +9014,7 @@ class CiStatsReporter { const upstreamBranch = (_options$upstreamBran = options.upstreamBranch) !== null && _options$upstreamBran !== void 0 ? _options$upstreamBran : this.getUpstreamBranch(); const kibanaUuid = options.kibanaUuid === undefined ? this.getKibanaUuid() : options.kibanaUuid; let email; + let branch; try { const { @@ -9024,16 +9025,32 @@ class CiStatsReporter { this.log.debug(e.message); } + try { + const { + stdout + } = await (0, _execa.default)('git', ['branch', '--show-current']); + branch = stdout; + } catch (e) { + this.log.debug(e.message); + } + + const memUsage = process.memoryUsage(); const isElasticCommitter = email && email.endsWith('@elastic.co') ? true : false; const defaultMetadata = { + kibanaUuid, + isElasticCommitter, committerHash: email ? _crypto.default.createHash('sha256').update(email).digest('hex').substring(0, 20) : undefined, + email: isElasticCommitter ? email : undefined, + branch: isElasticCommitter ? branch : undefined, cpuCount: (_Os$cpus = _os.default.cpus()) === null || _Os$cpus === void 0 ? void 0 : _Os$cpus.length, cpuModel: (_Os$cpus$ = _os.default.cpus()[0]) === null || _Os$cpus$ === void 0 ? void 0 : _Os$cpus$.model, cpuSpeed: (_Os$cpus$2 = _os.default.cpus()[0]) === null || _Os$cpus$2 === void 0 ? void 0 : _Os$cpus$2.speed, - email: isElasticCommitter ? email : undefined, freeMem: _os.default.freemem(), - isElasticCommitter, - kibanaUuid, + memoryUsageRss: memUsage.rss, + memoryUsageHeapTotal: memUsage.heapTotal, + memoryUsageHeapUsed: memUsage.heapUsed, + memoryUsageExternal: memUsage.external, + memoryUsageArrayBuffers: memUsage.arrayBuffers, nestedTiming: process.env.CI_STATS_NESTED_TIMING ? true : false, osArch: _os.default.arch(), osPlatform: _os.default.platform(), diff --git a/packages/kbn-test/src/functional_test_runner/cli.ts b/packages/kbn-test/src/functional_test_runner/cli.ts index ccd578aa038f8..3ad365a028b65 100644 --- a/packages/kbn-test/src/functional_test_runner/cli.ts +++ b/packages/kbn-test/src/functional_test_runner/cli.ts @@ -9,7 +9,7 @@ import { resolve } from 'path'; import { inspect } from 'util'; -import { run, createFlagError, Flags } from '@kbn/dev-utils'; +import { run, createFlagError, Flags, ToolingLog, getTimeReporter } from '@kbn/dev-utils'; import exitHook from 'exit-hook'; import { FunctionalTestRunner } from './functional_test_runner'; @@ -27,6 +27,12 @@ const parseInstallDir = (flags: Flags) => { }; export function runFtrCli() { + const runStartTime = Date.now(); + const toolingLog = new ToolingLog({ + level: 'info', + writeTo: process.stdout, + }); + const reportTime = getTimeReporter(toolingLog, 'scripts/functional_test_runner'); run( async ({ flags, log }) => { const functionalTestRunner = new FunctionalTestRunner( @@ -68,9 +74,19 @@ export function runFtrCli() { teardownRun = true; if (err) { + await reportTime(runStartTime, 'total', { + success: false, + err: err.message, + ...flags, + }); log.indent(-log.indent()); log.error(err); process.exitCode = 1; + } else { + await reportTime(runStartTime, 'total', { + success: true, + ...flags, + }); } try { diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js b/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js index 824cf3e6ceec1..df7f8750b2ae3 100644 --- a/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js +++ b/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js @@ -18,6 +18,8 @@ import { processOptions, displayHelp } from './args'; export async function startServersCli(defaultConfigPath) { await runCli(displayHelp, async (userOptions) => { const options = processOptions(userOptions, defaultConfigPath); - await startServers(options); + await startServers({ + ...options, + }); }); } diff --git a/packages/kbn-test/src/functional_tests/tasks.ts b/packages/kbn-test/src/functional_tests/tasks.ts index d45f8656ed728..3bc697c143f40 100644 --- a/packages/kbn-test/src/functional_tests/tasks.ts +++ b/packages/kbn-test/src/functional_tests/tasks.ts @@ -9,7 +9,7 @@ import { relative } from 'path'; import * as Rx from 'rxjs'; import { startWith, switchMap, take } from 'rxjs/operators'; -import { withProcRunner, ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; +import { withProcRunner, ToolingLog, REPO_ROOT, getTimeReporter } from '@kbn/dev-utils'; import dedent from 'dedent'; import { @@ -147,7 +147,14 @@ interface StartServerOptions { useDefaultConfig?: boolean; } -export async function startServers(options: StartServerOptions) { +export async function startServers({ ...options }: StartServerOptions) { + const runStartTime = Date.now(); + const toolingLog = new ToolingLog({ + level: 'info', + writeTo: process.stdout, + }); + const reportTime = getTimeReporter(toolingLog, 'scripts/functional_tests_server'); + const log = options.createLogger(); const opts = { ...options, @@ -170,6 +177,11 @@ export async function startServers(options: StartServerOptions) { }, }); + reportTime(runStartTime, 'ready', { + success: true, + ...options, + }); + // wait for 5 seconds of silence before logging the // success message so that it doesn't get buried await silence(log, 5000); diff --git a/packages/kbn-test/src/jest/run.ts b/packages/kbn-test/src/jest/run.ts index 441104befde91..07610a3eb84c6 100644 --- a/packages/kbn-test/src/jest/run.ts +++ b/packages/kbn-test/src/jest/run.ts @@ -21,7 +21,8 @@ import { resolve, relative, sep as osSep } from 'path'; import { existsSync } from 'fs'; import { run } from 'jest'; import { buildArgv } from 'jest-cli/build/cli'; -import { ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog, getTimeReporter } from '@kbn/dev-utils'; +import { map } from 'lodash'; // yarn test:jest src/core/server/saved_objects // yarn test:jest src/core/public/core_system.test.ts @@ -35,9 +36,14 @@ export function runJest(configName = 'jest.config.js') { writeTo: process.stdout, }); + const runStartTime = Date.now(); + const reportTime = getTimeReporter(log, 'scripts/jest'); + let cwd: string; + let testFiles: string[]; + if (!argv.config) { - const cwd = process.env.INIT_CWD || process.cwd(); - const testFiles = argv._.splice(2).map((p) => resolve(cwd, p)); + cwd = process.env.INIT_CWD || process.cwd(); + testFiles = argv._.splice(2).map((p) => resolve(cwd, p)); const commonTestFiles = commonBasePath(testFiles); const testFilesProvided = testFiles.length > 0; @@ -73,7 +79,14 @@ export function runJest(configName = 'jest.config.js') { process.env.NODE_ENV = 'test'; } - run(); + run().then(() => { + // Success means that tests finished, doesn't mean they passed. + reportTime(runStartTime, 'total', { + success: true, + isXpack: cwd.includes('x-pack'), + testFiles: map(testFiles, (testFile) => relative(cwd, testFile)), + }); + }); } /** diff --git a/src/dev/run_check_published_api_changes.ts b/src/dev/run_check_published_api_changes.ts index 7c8105bc40c51..452922ac56bcd 100644 --- a/src/dev/run_check_published_api_changes.ts +++ b/src/dev/run_check_published_api_changes.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ToolingLog } from '@kbn/dev-utils'; +import { ToolingLog, getTimeReporter } from '@kbn/dev-utils'; import { Extractor, IConfigFile, @@ -27,6 +27,9 @@ const log = new ToolingLog({ writeTo: process.stdout, }); +const runStartTime = Date.now(); +const reportTime = getTimeReporter(log, 'scripts/check_published_api_changes'); + /* * Step 1: execute build:types * This users tsconfig.types.json to generate types in `target/types` @@ -184,6 +187,7 @@ async function run(folder: string, { opts }: { opts: Options }): Promise { + reportTime(runStartTime, 'error', { + success: false, + error: e.message, + }); log.error(e); process.exitCode = 1; }); diff --git a/src/dev/run_i18n_check.ts b/src/dev/run_i18n_check.ts index 48ce2e013fc29..8aa93d33f60fd 100644 --- a/src/dev/run_i18n_check.ts +++ b/src/dev/run_i18n_check.ts @@ -9,7 +9,7 @@ import chalk from 'chalk'; import Listr from 'listr'; -import { createFailError, run } from '@kbn/dev-utils'; +import { createFailError, run, ToolingLog, getTimeReporter } from '@kbn/dev-utils'; import { ErrorReporter, I18nConfig } from './i18n'; import { extractDefaultMessages, @@ -19,6 +19,14 @@ import { mergeConfigs, } from './i18n/tasks'; +const toolingLog = new ToolingLog({ + level: 'info', + writeTo: process.stdout, +}); + +const runStartTime = Date.now(); +const reportTime = getTimeReporter(toolingLog, 'scripts/i18n_check'); + const skipOnNoTranslations = ({ config }: { config: I18nConfig }) => !config.translations.length && 'No translations found.'; @@ -116,13 +124,24 @@ run( const reporter = new ErrorReporter(); const messages: Map = new Map(); await list.run({ messages, reporter }); - } catch (error) { + + reportTime(runStartTime, 'total', { + success: true, + }); + } catch (error: Error | ErrorReporter) { process.exitCode = 1; if (error instanceof ErrorReporter) { error.errors.forEach((e: string | Error) => log.error(e)); + reportTime(runStartTime, 'error', { + success: false, + }); } else { log.error('Unhandled exception!'); log.error(error); + reportTime(runStartTime, 'error', { + success: false, + error: error.message, + }); } } }, From a2ac439f56313b7a3fc4708f54a4deebf2615136 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Tue, 5 Oct 2021 02:58:01 -0700 Subject: [PATCH 90/98] [Fleet] Remove enterprise license requirement for custom registry URL (#113858) --- .../services/epm/registry/registry_url.ts | 11 ++--------- .../fleet/server/services/fleet_server/index.ts | 17 ++++++++++------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/registry/registry_url.ts b/x-pack/plugins/fleet/server/services/epm/registry/registry_url.ts index 568aafddecbad..dfca8511fd84c 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/registry_url.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/registry_url.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { appContextService, licenseService } from '../../'; +import { appContextService } from '../../'; // from https://github.com/elastic/package-registry#docker (maybe from OpenAPI one day) // the unused variables cause a TS warning about unused values @@ -32,16 +32,9 @@ const getDefaultRegistryUrl = (): string => { export const getRegistryUrl = (): string => { const customUrl = appContextService.getConfig()?.registryUrl; - const isEnterprise = licenseService.isEnterprise(); - - if (customUrl && isEnterprise) { - return customUrl; - } if (customUrl) { - appContextService - .getLogger() - .warn('Enterprise license is required to use a custom registry url.'); + return customUrl; } return getDefaultRegistryUrl(); diff --git a/x-pack/plugins/fleet/server/services/fleet_server/index.ts b/x-pack/plugins/fleet/server/services/fleet_server/index.ts index 733d962a86e9e..0d386b9ba4995 100644 --- a/x-pack/plugins/fleet/server/services/fleet_server/index.ts +++ b/x-pack/plugins/fleet/server/services/fleet_server/index.ts @@ -50,22 +50,25 @@ export async function startFleetServerSetup() { _onResolve = resolve; }); const logger = appContextService.getLogger(); + + // Check for security if (!appContextService.hasSecurity()) { // Fleet will not work if security is not enabled logger?.warn('Fleet requires the security plugin to be enabled.'); return; } + // Log information about custom registry URL + const customUrl = appContextService.getConfig()?.registryUrl; + if (customUrl) { + logger.info( + `Custom registry url is an experimental feature and is unsupported. Using custom registry at ${customUrl}` + ); + } + try { // We need licence to be initialized before using the SO service. await licenseService.getLicenseInformation$()?.pipe(first())?.toPromise(); - - const customUrl = appContextService.getConfig()?.registryUrl; - const isEnterprise = licenseService.isEnterprise(); - if (customUrl && isEnterprise) { - logger.info('Custom registry url is an experimental feature and is unsupported.'); - } - await runFleetServerMigration(); _isFleetServerSetup = true; } catch (err) { From 1e7d4e1adfa9aaebb8f34c81022e3816050cda56 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Tue, 5 Oct 2021 13:32:28 +0300 Subject: [PATCH 91/98] [Lens] Unskips the heatmap functional tests suite (#113728) * Stabilizes the lens heatmap functional tests * Uncomment Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/test/functional/apps/lens/heatmap.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/test/functional/apps/lens/heatmap.ts b/x-pack/test/functional/apps/lens/heatmap.ts index ddc4130d388ce..deca06b6b351a 100644 --- a/x-pack/test/functional/apps/lens/heatmap.ts +++ b/x-pack/test/functional/apps/lens/heatmap.ts @@ -13,8 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const elasticChart = getService('elasticChart'); const testSubjects = getService('testSubjects'); - // FLAKY: https://github.com/elastic/kibana/issues/113043 - describe.skip('lens heatmap', () => { + describe('lens heatmap', () => { before(async () => { await PageObjects.visualize.navigateToNewVisualization(); await PageObjects.visualize.clickVisType('lens'); @@ -74,8 +73,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.lens.openPalettePanel('lnsHeatmap'); await testSubjects.setValue('lnsPalettePanel_dynamicColoring_stop_value_0', '10', { clearWithKeyboard: true, + typeCharByChar: true, }); - await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.lens.waitForVisualization(); const debugState = await PageObjects.lens.getCurrentChartDebugState(); From 35e9f6ad6b23ade46480633fa5457731e583e065 Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Tue, 5 Oct 2021 12:45:56 +0200 Subject: [PATCH 92/98] :bug: fix duplicate suggestion issue + missing over time (#113449) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../editor_frame/suggestion_helpers.ts | 1 + .../indexpattern_suggestions.test.tsx | 97 +++++++++++++++++++ .../indexpattern_suggestions.ts | 8 +- x-pack/plugins/lens/public/types.ts | 1 + 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts index 7f1e4aa58dba3..f3245759c9ef5 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts @@ -115,6 +115,7 @@ export function getSuggestions({ } else { dataSourceSuggestions = datasource.getDatasourceSuggestionsFromCurrentState( datasourceState, + (layerId) => isLayerSupportedByVisualization(layerId, [layerTypes.DATA]), activeData ); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx index a5d6db4be3319..bf4b10de386a1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx @@ -1704,6 +1704,103 @@ describe('IndexPattern Data Source suggestions', () => { ); }); + it('adds date histogram over default time field for tables without time dimension and a threshold', async () => { + const initialState = testInitialState(); + const state: IndexPatternPrivateState = { + ...initialState, + layers: { + first: { + indexPatternId: '1', + columnOrder: ['cola', 'colb'], + columns: { + cola: { + label: 'My Terms', + customLabel: true, + dataType: 'string', + isBucketed: true, + operationType: 'terms', + sourceField: 'source', + scale: 'ordinal', + params: { + orderBy: { type: 'alphabetical' }, + orderDirection: 'asc', + size: 5, + }, + }, + colb: { + label: 'My Op', + customLabel: true, + dataType: 'number', + isBucketed: false, + operationType: 'average', + sourceField: 'bytes', + scale: 'ratio', + }, + }, + }, + threshold: { + indexPatternId: '2', + columnOrder: ['thresholda'], + columns: { + thresholda: { + label: 'My Op', + customLabel: true, + dataType: 'number', + isBucketed: false, + operationType: 'average', + sourceField: 'bytes', + scale: 'ratio', + }, + }, + }, + }, + }; + + expect( + getSuggestionSubset( + getDatasourceSuggestionsFromCurrentState(state, (layerId) => layerId !== 'threshold') + ) + ).toContainEqual( + expect.objectContaining({ + table: { + isMultiRow: true, + changeType: 'extended', + label: 'Over time', + columns: [ + { + columnId: 'cola', + operation: { + label: 'My Terms', + dataType: 'string', + isBucketed: true, + scale: 'ordinal', + }, + }, + { + columnId: 'id1', + operation: { + label: 'timestampLabel', + dataType: 'date', + isBucketed: true, + scale: 'interval', + }, + }, + { + columnId: 'colb', + operation: { + label: 'My Op', + dataType: 'number', + isBucketed: false, + scale: 'ratio', + }, + }, + ], + layerId: 'first', + }, + }) + ); + }); + it('does not create an over time suggestion if tables with numeric buckets with time dimension', async () => { const initialState = testInitialState(); const state: IndexPatternPrivateState = { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts index 0fe0ef617dc27..604b63aa29246 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts @@ -350,9 +350,11 @@ function createNewLayerWithMetricAggregation( } export function getDatasourceSuggestionsFromCurrentState( - state: IndexPatternPrivateState + state: IndexPatternPrivateState, + filterLayers: (layerId: string) => boolean = () => true ): Array> { - const layers = Object.entries(state.layers || {}); + const layers = Object.entries(state.layers || {}).filter(([layerId]) => filterLayers(layerId)); + if (layers.length > 1) { // Return suggestions that reduce the data to each layer individually return layers @@ -394,7 +396,7 @@ export function getDatasourceSuggestionsFromCurrentState( } return flatten( - Object.entries(state.layers || {}) + layers .filter(([_id, layer]) => layer.columnOrder.length && layer.indexPatternId) .map(([layerId, layer]) => { const indexPattern = state.indexPatterns[layer.indexPatternId]; diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index 75ed5f4907e0b..2e7876f83fc41 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -246,6 +246,7 @@ export interface Datasource { ) => Array>; getDatasourceSuggestionsFromCurrentState: ( state: T, + filterFn?: (layerId: string) => boolean, activeData?: Record ) => Array>; From 158b396ae1150d8ee63fa1e2b2fb8dcb33b72af5 Mon Sep 17 00:00:00 2001 From: Dmitry Tomashevich <39378793+Dmitriynj@users.noreply.github.com> Date: Tue, 5 Oct 2021 14:08:54 +0300 Subject: [PATCH 93/98] [Discover] Fix navigation to a `new` from saved search and saved query, fix `discover:searchOnPageLoad` (#112262) * [Discover] fix saved search become active * [Discover] add another fix to be consistent with data fetching code * [Discover] simplify solution * [Discover] add functionals * [Discover] fix saved query bug, add functionals * [Discover] fix functionals * [Discover] fix functional test * [Discover] split saved query tests * [Discover] preselect logstash index pattern * [Discover] remove saved query after test complete * [Discover] change query fill order * [Discover] try to fix unrelated functional test * [Discover] one more fix * [Discover] try to fix one more problem * [Discover] fix commonly used time range test * [Discover] revert uisettings init in before statement, do small adjustments * [Discover] fix unit test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../uninitialized/uninitialized.tsx | 2 +- .../apps/main/discover_main_app.tsx | 3 +- .../apps/main/discover_main_route.tsx | 2 - .../apps/main/services/use_discover_state.ts | 10 +- .../apps/main/services/use_saved_search.ts | 1 + .../apps/main/utils/get_fetch_observable.ts | 15 ++- .../main/utils/get_fetch_observeable.test.ts | 2 + .../main/utils/get_state_defaults.test.ts | 2 + .../apps/main/utils/get_state_defaults.ts | 1 + test/functional/apps/discover/_discover.ts | 28 +---- .../apps/discover/_saved_queries.ts | 74 +++++++++--- .../apps/discover/_search_on_page_load.ts | 112 ++++++++++++++++++ test/functional/apps/discover/index.ts | 1 + .../apps/discover/saved_searches.ts | 51 +++++++- 14 files changed, 248 insertions(+), 56 deletions(-) create mode 100644 test/functional/apps/discover/_search_on_page_load.ts diff --git a/src/plugins/discover/public/application/apps/main/components/uninitialized/uninitialized.tsx b/src/plugins/discover/public/application/apps/main/components/uninitialized/uninitialized.tsx index c9e0c43900ba1..6c1b1bfc87d20 100644 --- a/src/plugins/discover/public/application/apps/main/components/uninitialized/uninitialized.tsx +++ b/src/plugins/discover/public/application/apps/main/components/uninitialized/uninitialized.tsx @@ -32,7 +32,7 @@ export const DiscoverUninitialized = ({ onRefresh }: Props) => {

    } actions={ - + { @@ -46,7 +46,6 @@ export function DiscoverMainApp(props: DiscoverMainProps) { }, [history] ); - const savedSearch = props.savedSearch; /** * State related logic diff --git a/src/plugins/discover/public/application/apps/main/discover_main_route.tsx b/src/plugins/discover/public/application/apps/main/discover_main_route.tsx index 5141908e44ade..a95668642558c 100644 --- a/src/plugins/discover/public/application/apps/main/discover_main_route.tsx +++ b/src/plugins/discover/public/application/apps/main/discover_main_route.tsx @@ -75,8 +75,6 @@ export function DiscoverMainRoute({ services, history }: DiscoverMainProps) { async function loadSavedSearch() { try { - // force a refresh if a given saved search without id was saved - setSavedSearch(undefined); const loadedSavedSearch = await services.getSavedSearchById(savedSearchId); const loadedIndexPattern = await loadDefaultOrCurrentIndexPattern(loadedSavedSearch); if (loadedSavedSearch && !loadedSavedSearch?.searchSource.getField('index')) { diff --git a/src/plugins/discover/public/application/apps/main/services/use_discover_state.ts b/src/plugins/discover/public/application/apps/main/services/use_discover_state.ts index e11a9937111a1..223d896b16cd1 100644 --- a/src/plugins/discover/public/application/apps/main/services/use_discover_state.ts +++ b/src/plugins/discover/public/application/apps/main/services/use_discover_state.ts @@ -96,6 +96,7 @@ export function useDiscoverState({ useEffect(() => { const stopSync = stateContainer.initializeAndSync(indexPattern, filterManager, data); + return () => stopSync(); }, [stateContainer, filterManager, data, indexPattern]); @@ -209,16 +210,13 @@ export function useDiscoverState({ }, [config, data, savedSearch, reset, stateContainer]); /** - * Initial data fetching, also triggered when index pattern changes + * Trigger data fetching on indexPattern or savedSearch changes */ useEffect(() => { - if (!indexPattern) { - return; - } - if (initialFetchStatus === FetchStatus.LOADING) { + if (indexPattern) { refetch$.next(); } - }, [initialFetchStatus, refetch$, indexPattern]); + }, [initialFetchStatus, refetch$, indexPattern, savedSearch.id]); return { data$, diff --git a/src/plugins/discover/public/application/apps/main/services/use_saved_search.ts b/src/plugins/discover/public/application/apps/main/services/use_saved_search.ts index 26f95afba5a93..d11c76283fedd 100644 --- a/src/plugins/discover/public/application/apps/main/services/use_saved_search.ts +++ b/src/plugins/discover/public/application/apps/main/services/use_saved_search.ts @@ -156,6 +156,7 @@ export const useSavedSearch = ({ refetch$, searchSessionManager, searchSource, + initialFetchStatus, }); const subscription = fetch$.subscribe((val) => { diff --git a/src/plugins/discover/public/application/apps/main/utils/get_fetch_observable.ts b/src/plugins/discover/public/application/apps/main/utils/get_fetch_observable.ts index aac6196e64f6f..528f0e74d3ed6 100644 --- a/src/plugins/discover/public/application/apps/main/utils/get_fetch_observable.ts +++ b/src/plugins/discover/public/application/apps/main/utils/get_fetch_observable.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ import { merge } from 'rxjs'; -import { debounceTime, filter, tap } from 'rxjs/operators'; +import { debounceTime, filter, skip, tap } from 'rxjs/operators'; import { FetchStatus } from '../../../types'; import type { @@ -26,6 +26,7 @@ export function getFetch$({ main$, refetch$, searchSessionManager, + initialFetchStatus, }: { setAutoRefreshDone: (val: AutoRefreshDoneFn | undefined) => void; data: DataPublicPluginStart; @@ -33,10 +34,11 @@ export function getFetch$({ refetch$: DataRefetch$; searchSessionManager: DiscoverSearchSessionManager; searchSource: SearchSource; + initialFetchStatus: FetchStatus; }) { const { timefilter } = data.query.timefilter; const { filterManager } = data.query; - return merge( + let fetch$ = merge( refetch$, filterManager.getFetches$(), timefilter.getFetch$(), @@ -58,4 +60,13 @@ export function getFetch$({ data.query.queryString.getUpdates$(), searchSessionManager.newSearchSessionIdFromURL$.pipe(filter((sessionId) => !!sessionId)) ).pipe(debounceTime(100)); + + /** + * Skip initial fetch when discover:searchOnPageLoad is disabled. + */ + if (initialFetchStatus === FetchStatus.UNINITIALIZED) { + fetch$ = fetch$.pipe(skip(1)); + } + + return fetch$; } diff --git a/src/plugins/discover/public/application/apps/main/utils/get_fetch_observeable.test.ts b/src/plugins/discover/public/application/apps/main/utils/get_fetch_observeable.test.ts index 5f728b115b2e9..39873ff609d64 100644 --- a/src/plugins/discover/public/application/apps/main/utils/get_fetch_observeable.test.ts +++ b/src/plugins/discover/public/application/apps/main/utils/get_fetch_observeable.test.ts @@ -58,6 +58,7 @@ describe('getFetchObservable', () => { data: createDataMock(new Subject(), new Subject(), new Subject(), new Subject()), searchSessionManager: searchSessionManagerMock.searchSessionManager, searchSource: savedSearchMock.searchSource, + initialFetchStatus: FetchStatus.LOADING, }); fetch$.subscribe(() => { @@ -81,6 +82,7 @@ describe('getFetchObservable', () => { data: dataMock, searchSessionManager: searchSessionManagerMock.searchSessionManager, searchSource: savedSearchMockWithTimeField.searchSource, + initialFetchStatus: FetchStatus.LOADING, }); const fetchfnMock = jest.fn(); diff --git a/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.test.ts b/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.test.ts index 554aca6ddb8f1..04ee5f414e7f4 100644 --- a/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.test.ts +++ b/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.test.ts @@ -31,6 +31,7 @@ describe('getStateDefaults', () => { "index": "index-pattern-with-timefield-id", "interval": "auto", "query": undefined, + "savedQuery": undefined, "sort": Array [ Array [ "timestamp", @@ -59,6 +60,7 @@ describe('getStateDefaults', () => { "index": "the-index-pattern-id", "interval": "auto", "query": undefined, + "savedQuery": undefined, "sort": Array [], } `); diff --git a/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.ts b/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.ts index 4061d9a61f0a3..cd23d52022374 100644 --- a/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.ts +++ b/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.ts @@ -47,6 +47,7 @@ export function getStateDefaults({ interval: 'auto', filters: cloneDeep(searchSource.getOwnField('filter')), hideChart: undefined, + savedQuery: undefined, } as AppState; if (savedSearch.grid) { defaultState.grid = savedSearch.grid; diff --git a/test/functional/apps/discover/_discover.ts b/test/functional/apps/discover/_discover.ts index 4edc4d22f0753..0a8f56ee250ea 100644 --- a/test/functional/apps/discover/_discover.ts +++ b/test/functional/apps/discover/_discover.ts @@ -233,11 +233,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('time zone switch', () => { it('should show bars in the correct time zone after switching', async function () { - await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'America/Phoenix' }); + await kibanaServer.uiSettings.update({ 'dateFormat:tz': 'America/Phoenix' }); await PageObjects.common.navigateToApp('discover'); await PageObjects.header.awaitKibanaChrome(); - await queryBar.clearQuery(); await PageObjects.timePicker.setDefaultAbsoluteRange(); + await queryBar.clearQuery(); log.debug( 'check that the newest doc timestamp is now -7 hours from the UTC time in the first test' @@ -246,36 +246,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(rowData.startsWith('Sep 22, 2015 @ 16:50:13.253')).to.be.ok(); }); }); - describe('usage of discover:searchOnPageLoad', () => { - it('should not fetch data from ES initially when discover:searchOnPageLoad is false', async function () { - await kibanaServer.uiSettings.replace({ 'discover:searchOnPageLoad': false }); - await PageObjects.common.navigateToApp('discover'); - await PageObjects.header.awaitKibanaChrome(); - - expect(await PageObjects.discover.getNrOfFetches()).to.be(0); - }); - - it('should fetch data from ES initially when discover:searchOnPageLoad is true', async function () { - await kibanaServer.uiSettings.replace({ 'discover:searchOnPageLoad': true }); - await PageObjects.common.navigateToApp('discover'); - await PageObjects.header.awaitKibanaChrome(); - await retry.waitFor('number of fetches to be 1', async () => { - const nrOfFetches = await PageObjects.discover.getNrOfFetches(); - return nrOfFetches === 1; - }); - }); - }); describe('invalid time range in URL', function () { it('should get the default timerange', async function () { - const prevTime = await PageObjects.timePicker.getTimeConfig(); await PageObjects.common.navigateToUrl('discover', '#/?_g=(time:(from:now-15m,to:null))', { useActualUrl: true, }); await PageObjects.header.awaitKibanaChrome(); const time = await PageObjects.timePicker.getTimeConfig(); - expect(time.start).to.be(prevTime.start); - expect(time.end).to.be(prevTime.end); + expect(time.start).to.be('~ 15 minutes ago'); + expect(time.end).to.be('now'); }); }); diff --git a/test/functional/apps/discover/_saved_queries.ts b/test/functional/apps/discover/_saved_queries.ts index 20f2cab907d9b..832d895fcea3d 100644 --- a/test/functional/apps/discover/_saved_queries.ts +++ b/test/functional/apps/discover/_saved_queries.ts @@ -17,39 +17,83 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); const browser = getService('browser'); - - const defaultSettings = { - defaultIndex: 'logstash-*', - }; const filterBar = getService('filterBar'); const queryBar = getService('queryBar'); const savedQueryManagementComponent = getService('savedQueryManagementComponent'); const testSubjects = getService('testSubjects'); + const defaultSettings = { + defaultIndex: 'logstash-*', + }; + + const setUpQueriesWithFilters = async () => { + // set up a query with filters and a time filter + log.debug('set up a query with filters to save'); + const fromTime = 'Sep 20, 2015 @ 08:00:00.000'; + const toTime = 'Sep 21, 2015 @ 08:00:00.000'; + await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await filterBar.addFilter('extension.raw', 'is one of', 'jpg'); + await queryBar.setQuery('response:200'); + }; describe('saved queries saved objects', function describeIndexTests() { before(async function () { log.debug('load kibana index with default index pattern'); await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover.json'); + await esArchiver.load('test/functional/fixtures/es_archiver/date_nested'); + await esArchiver.load('test/functional/fixtures/es_archiver/logstash_functional'); - // and load a set of makelogs data - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); await kibanaServer.uiSettings.replace(defaultSettings); log.debug('discover'); await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setDefaultAbsoluteRange(); }); - describe('saved query management component functionality', function () { - before(async function () { - // set up a query with filters and a time filter - log.debug('set up a query with filters to save'); - await queryBar.setQuery('response:200'); - await filterBar.addFilter('extension.raw', 'is one of', 'jpg'); - const fromTime = 'Sep 20, 2015 @ 08:00:00.000'; - const toTime = 'Sep 21, 2015 @ 08:00:00.000'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + after(async () => { + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + await esArchiver.unload('test/functional/fixtures/es_archiver/date_nested'); + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + describe('saved query selection', () => { + before(async () => await setUpQueriesWithFilters()); + + it(`should unselect saved query when navigating to a 'new'`, async function () { + await savedQueryManagementComponent.saveNewQuery( + 'test-unselect-saved-query', + 'mock', + true, + true + ); + + await queryBar.submitQuery(); + + expect(await filterBar.hasFilter('extension.raw', 'jpg')).to.be(true); + expect(await queryBar.getQueryString()).to.eql('response:200'); + + await PageObjects.discover.clickNewSearchButton(); + + expect(await filterBar.hasFilter('extension.raw', 'jpg')).to.be(false); + expect(await queryBar.getQueryString()).to.eql(''); + + await PageObjects.discover.selectIndexPattern('date-nested'); + + expect(await filterBar.hasFilter('extension.raw', 'jpg')).to.be(false); + expect(await queryBar.getQueryString()).to.eql(''); + + await PageObjects.discover.selectIndexPattern('logstash-*'); + + expect(await filterBar.hasFilter('extension.raw', 'jpg')).to.be(false); + expect(await queryBar.getQueryString()).to.eql(''); + + // reset state + await savedQueryManagementComponent.deleteSavedQuery('test-unselect-saved-query'); }); + }); + + describe('saved query management component functionality', function () { + before(async () => await setUpQueriesWithFilters()); it('should show the saved query management component when there are no saved queries', async () => { await savedQueryManagementComponent.openSavedQueryManagementComponent(); diff --git a/test/functional/apps/discover/_search_on_page_load.ts b/test/functional/apps/discover/_search_on_page_load.ts new file mode 100644 index 0000000000000..2a66e03c3cbb8 --- /dev/null +++ b/test/functional/apps/discover/_search_on_page_load.ts @@ -0,0 +1,112 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const log = getService('log'); + const retry = getService('retry'); + const esArchiver = getService('esArchiver'); + const queryBar = getService('queryBar'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); + const testSubjects = getService('testSubjects'); + + const defaultSettings = { + defaultIndex: 'logstash-*', + }; + + const initSearchOnPageLoad = async (searchOnPageLoad: boolean) => { + await kibanaServer.uiSettings.replace({ 'discover:searchOnPageLoad': searchOnPageLoad }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.awaitKibanaChrome(); + }; + + const waitForFetches = (fetchesNumber: number) => async () => { + const nrOfFetches = await PageObjects.discover.getNrOfFetches(); + return nrOfFetches === fetchesNumber; + }; + + describe('usage of discover:searchOnPageLoad', () => { + before(async function () { + log.debug('load kibana index with default index pattern'); + + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover.json'); + + // and load a set of data + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.load('test/functional/fixtures/es_archiver/date_nested'); + + await kibanaServer.uiSettings.replace(defaultSettings); + await PageObjects.common.navigateToApp('discover'); + }); + + after(async () => { + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + await esArchiver.load('test/functional/fixtures/es_archiver/date_nested'); + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + describe(`when it's false`, () => { + beforeEach(async () => await initSearchOnPageLoad(false)); + + it('should not fetch data from ES initially', async function () { + expect(await testSubjects.exists('refreshDataButton')).to.be(true); + await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + }); + + it('should not fetch on indexPattern change', async function () { + expect(await testSubjects.exists('refreshDataButton')).to.be(true); + await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + + await PageObjects.discover.selectIndexPattern('date-nested'); + + expect(await testSubjects.exists('refreshDataButton')).to.be(true); + await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + }); + + it('should fetch data from ES after refreshDataButton click', async function () { + expect(await testSubjects.exists('refreshDataButton')).to.be(true); + await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + + await testSubjects.click('refreshDataButton'); + + await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await testSubjects.exists('refreshDataButton')).to.be(false); + }); + + it('should fetch data from ES after submit query', async function () { + expect(await testSubjects.exists('refreshDataButton')).to.be(true); + await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + + await queryBar.submitQuery(); + + await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await testSubjects.exists('refreshDataButton')).to.be(false); + }); + + it('should fetch data from ES after choosing commonly used time range', async function () { + await PageObjects.discover.selectIndexPattern('logstash-*'); + expect(await testSubjects.exists('refreshDataButton')).to.be(true); + await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + + await PageObjects.timePicker.setCommonlyUsedTime('This_week'); + + await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await testSubjects.exists('refreshDataButton')).to.be(false); + }); + }); + + it(`when it's false should fetch data from ES initially`, async function () { + await initSearchOnPageLoad(true); + await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + }); + }); +} diff --git a/test/functional/apps/discover/index.ts b/test/functional/apps/discover/index.ts index 3a18a55fe138b..59191b489f4c7 100644 --- a/test/functional/apps/discover/index.ts +++ b/test/functional/apps/discover/index.ts @@ -51,5 +51,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_runtime_fields_editor')); loadTestFile(require.resolve('./_huge_fields')); loadTestFile(require.resolve('./_date_nested')); + loadTestFile(require.resolve('./_search_on_page_load')); }); } diff --git a/x-pack/test/functional/apps/discover/saved_searches.ts b/x-pack/test/functional/apps/discover/saved_searches.ts index 1d8de9fe9fb6d..5d8c2aff3ed5f 100644 --- a/x-pack/test/functional/apps/discover/saved_searches.ts +++ b/x-pack/test/functional/apps/discover/saved_searches.ts @@ -16,16 +16,31 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const dataGrid = getService('dataGrid'); const panelActions = getService('dashboardPanelActions'); const panelActionsTimeRange = getService('dashboardPanelTimeRange'); + const queryBar = getService('queryBar'); + const filterBar = getService('filterBar'); const ecommerceSOPath = 'x-pack/test/functional/fixtures/kbn_archiver/reporting/ecommerce.json'; + const defaultSettings = { + defaultIndex: 'logstash-*', + 'doc_table:legacy': false, + }; + + const setTimeRange = async () => { + const fromTime = 'Apr 27, 2019 @ 23:56:51.374'; + const toTime = 'Aug 23, 2019 @ 16:18:51.821'; + await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + }; describe('Discover Saved Searches', () => { before('initialize tests', async () => { await esArchiver.load('x-pack/test/functional/es_archives/reporting/ecommerce'); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); await kibanaServer.importExport.load(ecommerceSOPath); - await kibanaServer.uiSettings.update({ 'doc_table:legacy': false }); + await kibanaServer.uiSettings.update(defaultSettings); }); + after('clean up archives', async () => { await esArchiver.unload('x-pack/test/functional/es_archives/reporting/ecommerce'); + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); await kibanaServer.importExport.unload(ecommerceSOPath); await kibanaServer.uiSettings.unset('doc_table:legacy'); }); @@ -34,9 +49,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should be possible to customize time range for saved searches on dashboards', async () => { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); - const fromTime = 'Apr 27, 2019 @ 23:56:51.374'; - const toTime = 'Aug 23, 2019 @ 16:18:51.821'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await setTimeRange(); await dashboardAddPanel.clickOpenAddPanel(); await dashboardAddPanel.addSavedSearch('Ecommerce Data'); expect(await dataGrid.getDocCount()).to.be(500); @@ -49,5 +62,35 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await dataGrid.hasNoResults()).to.be(true); }); }); + + it(`should unselect saved search when navigating to a 'new'`, async function () { + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.selectIndexPattern('ecommerce'); + await setTimeRange(); + await filterBar.addFilter('category', 'is', `Men's Shoes`); + await queryBar.setQuery('customer_gender:MALE'); + + await PageObjects.discover.saveSearch('test-unselect-saved-search'); + + await queryBar.submitQuery(); + + expect(await filterBar.hasFilter('category', `Men's Shoes`)).to.be(true); + expect(await queryBar.getQueryString()).to.eql('customer_gender:MALE'); + + await PageObjects.discover.clickNewSearchButton(); + + expect(await filterBar.hasFilter('category', `Men's Shoes`)).to.be(false); + expect(await queryBar.getQueryString()).to.eql(''); + + await PageObjects.discover.selectIndexPattern('logstash-*'); + + expect(await filterBar.hasFilter('category', `Men's Shoes`)).to.be(false); + expect(await queryBar.getQueryString()).to.eql(''); + + await PageObjects.discover.selectIndexPattern('ecommerce'); + + expect(await filterBar.hasFilter('category', `Men's Shoes`)).to.be(false); + expect(await queryBar.getQueryString()).to.eql(''); + }); }); } From a4b74bd3980cce77d4e9d77b10643bfe76dde126 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 5 Oct 2021 13:30:56 +0200 Subject: [PATCH 94/98] [8.0] Remove legacy logging (#112305) * remove kbn-legacy-logging package * remove legacy service * remove legacy appender * remove LegacyObjectToConfigAdapter * gix types * remove @hapi/good / @hapi/good-squeeze / @hapi/podium * remove `default` appender validation for `root` logger * remove old config key from kibana-docker * fix FTR config * fix dev server * remove reference from readme * fix unit test * clean CLI args and remove quiet option * fix type * fix status test config * remove from test config * fix snapshot * use another regexp * update generated doc * fix createRootWithSettings * fix some integration tests * another IT fix * yet another IT fix * (will be reverted) add assertion for CI failure * Revert "(will be reverted) add assertion for CI failure" This reverts commit 78d5560f9e9cb42030f001919f6ab090dbbbcb3b. * switch back to json layout for test * remove legacy logging config deprecations * address some review comments * update documentation * update kibana.yml config examples * add config example for `metrics.ops` Co-authored-by: Tyler Smalley --- .github/CODEOWNERS | 1 - config/kibana.yml | 30 +- .../logging-configuration-migration.asciidoc | 4 - .../monorepo-packages.asciidoc | 1 - ...a-plugin-core-server.appenderconfigtype.md | 2 +- docs/settings/logging-settings.asciidoc | 10 - .../production.asciidoc | 11 +- package.json | 4 - packages/BUILD.bazel | 1 - packages/kbn-cli-dev-mode/src/bootstrap.ts | 2 +- .../kbn-cli-dev-mode/src/cli_dev_mode.test.ts | 1 - packages/kbn-cli-dev-mode/src/cli_dev_mode.ts | 5 +- .../kbn-cli-dev-mode/src/dev_server.test.ts | 1 - packages/kbn-cli-dev-mode/src/log.ts | 8 +- .../src/using_server_process.ts | 2 +- packages/kbn-config/src/__mocks__/env.ts | 1 - .../src/__snapshots__/env.test.ts.snap | 6 - packages/kbn-config/src/config_service.ts | 4 +- packages/kbn-config/src/env.ts | 2 - packages/kbn-config/src/index.ts | 1 - ...gacy_object_to_config_adapter.test.ts.snap | 95 ----- packages/kbn-config/src/legacy/index.ts | 12 - .../legacy_object_to_config_adapter.test.ts | 161 -------- .../legacy/legacy_object_to_config_adapter.ts | 65 ---- packages/kbn-legacy-logging/BUILD.bazel | 107 ------ packages/kbn-legacy-logging/README.md | 4 - packages/kbn-legacy-logging/jest.config.js | 13 - packages/kbn-legacy-logging/package.json | 8 - .../src/get_logging_config.ts | 85 ----- packages/kbn-legacy-logging/src/index.ts | 14 - .../src/legacy_logging_server.test.ts | 105 ------ .../src/legacy_logging_server.ts | 140 ------- packages/kbn-legacy-logging/src/log_events.ts | 71 ---- packages/kbn-legacy-logging/src/log_format.ts | 176 --------- .../src/log_format_json.test.ts | 281 -------------- .../kbn-legacy-logging/src/log_format_json.ts | 23 -- .../src/log_format_string.test.ts | 64 ---- .../src/log_format_string.ts | 65 ---- .../src/log_interceptor.test.ts | 153 -------- .../kbn-legacy-logging/src/log_interceptor.ts | 144 ------- .../src/log_reporter.test.ts | 131 ------- .../kbn-legacy-logging/src/log_reporter.ts | 49 --- packages/kbn-legacy-logging/src/metadata.ts | 42 --- .../kbn-legacy-logging/src/rotate/index.ts | 41 -- .../src/rotate/log_rotator.test.ts | 261 ------------- .../src/rotate/log_rotator.ts | 352 ------------------ packages/kbn-legacy-logging/src/schema.ts | 97 ----- .../src/setup_logging.test.ts | 35 -- .../kbn-legacy-logging/src/setup_logging.ts | 41 -- .../src/utils/apply_filters_to_keys.test.ts | 49 --- .../src/utils/apply_filters_to_keys.ts | 50 --- .../src/utils/get_payload_size.test.ts | 158 -------- .../src/utils/get_payload_size.ts | 71 ---- .../kbn-legacy-logging/src/utils/index.ts | 10 - packages/kbn-legacy-logging/tsconfig.json | 15 - .../__fixtures__/invalid_config.yml | 10 + .../reload_logging_config/kibana.test.yml | 13 - .../integration_tests/invalid_config.test.ts | 39 +- .../reload_logging_config.test.ts | 76 ---- src/cli/serve/serve.js | 16 +- .../deprecation/core_deprecations.test.ts | 227 +---------- .../config/deprecation/core_deprecations.ts | 251 ------------- src/core/server/config/index.ts | 1 - .../config_deprecation.test.ts | 8 +- .../elasticsearch/elasticsearch_config.ts | 2 +- .../http/integration_tests/logging.test.ts | 4 - src/core/server/legacy/index.ts | 11 - .../legacy/integration_tests/logging.test.ts | 234 ------------ src/core/server/legacy/legacy_service.mock.ts | 21 -- .../legacy/legacy_service.test.mocks.ts | 18 - src/core/server/legacy/legacy_service.test.ts | 197 ---------- src/core/server/legacy/legacy_service.ts | 75 ---- .../legacy_appender.test.ts.snap | 142 ------- .../logging/appenders/legacy_appender.test.ts | 135 ------- .../logging/appenders/legacy_appender.ts | 52 --- src/core/server/logging/README.mdx | 5 - .../logging/appenders/appenders.test.ts | 8 - .../server/logging/appenders/appenders.ts | 8 - .../logging/integration_tests/logging.test.ts | 1 - .../rolling_file_appender.test.ts | 1 - .../server/logging/logging_config.test.ts | 27 +- src/core/server/logging/logging_config.ts | 27 +- .../server/logging/logging_system.test.ts | 5 - src/core/server/server.api.md | 3 +- src/core/server/server.test.mocks.ts | 21 +- src/core/server/server.test.ts | 5 - src/core/server/server.ts | 8 - src/core/test_helpers/kbn_server.ts | 7 +- .../resources/base/bin/kibana-docker | 11 - .../server/collectors/config_usage/README.md | 1 - test/common/config.js | 1 - .../http/platform/config.status.ts | 2 +- x-pack/plugins/security/server/config.test.ts | 2 +- yarn.lock | 30 +- 94 files changed, 108 insertions(+), 4882 deletions(-) delete mode 100644 packages/kbn-config/src/legacy/__snapshots__/legacy_object_to_config_adapter.test.ts.snap delete mode 100644 packages/kbn-config/src/legacy/index.ts delete mode 100644 packages/kbn-config/src/legacy/legacy_object_to_config_adapter.test.ts delete mode 100644 packages/kbn-config/src/legacy/legacy_object_to_config_adapter.ts delete mode 100644 packages/kbn-legacy-logging/BUILD.bazel delete mode 100644 packages/kbn-legacy-logging/README.md delete mode 100644 packages/kbn-legacy-logging/jest.config.js delete mode 100644 packages/kbn-legacy-logging/package.json delete mode 100644 packages/kbn-legacy-logging/src/get_logging_config.ts delete mode 100644 packages/kbn-legacy-logging/src/index.ts delete mode 100644 packages/kbn-legacy-logging/src/legacy_logging_server.test.ts delete mode 100644 packages/kbn-legacy-logging/src/legacy_logging_server.ts delete mode 100644 packages/kbn-legacy-logging/src/log_events.ts delete mode 100644 packages/kbn-legacy-logging/src/log_format.ts delete mode 100644 packages/kbn-legacy-logging/src/log_format_json.test.ts delete mode 100644 packages/kbn-legacy-logging/src/log_format_json.ts delete mode 100644 packages/kbn-legacy-logging/src/log_format_string.test.ts delete mode 100644 packages/kbn-legacy-logging/src/log_format_string.ts delete mode 100644 packages/kbn-legacy-logging/src/log_interceptor.test.ts delete mode 100644 packages/kbn-legacy-logging/src/log_interceptor.ts delete mode 100644 packages/kbn-legacy-logging/src/log_reporter.test.ts delete mode 100644 packages/kbn-legacy-logging/src/log_reporter.ts delete mode 100644 packages/kbn-legacy-logging/src/metadata.ts delete mode 100644 packages/kbn-legacy-logging/src/rotate/index.ts delete mode 100644 packages/kbn-legacy-logging/src/rotate/log_rotator.test.ts delete mode 100644 packages/kbn-legacy-logging/src/rotate/log_rotator.ts delete mode 100644 packages/kbn-legacy-logging/src/schema.ts delete mode 100644 packages/kbn-legacy-logging/src/setup_logging.test.ts delete mode 100644 packages/kbn-legacy-logging/src/setup_logging.ts delete mode 100644 packages/kbn-legacy-logging/src/utils/apply_filters_to_keys.test.ts delete mode 100644 packages/kbn-legacy-logging/src/utils/apply_filters_to_keys.ts delete mode 100644 packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts delete mode 100644 packages/kbn-legacy-logging/src/utils/get_payload_size.ts delete mode 100644 packages/kbn-legacy-logging/src/utils/index.ts delete mode 100644 packages/kbn-legacy-logging/tsconfig.json delete mode 100644 src/cli/serve/integration_tests/__fixtures__/reload_logging_config/kibana.test.yml delete mode 100644 src/core/server/legacy/index.ts delete mode 100644 src/core/server/legacy/integration_tests/logging.test.ts delete mode 100644 src/core/server/legacy/legacy_service.mock.ts delete mode 100644 src/core/server/legacy/legacy_service.test.mocks.ts delete mode 100644 src/core/server/legacy/legacy_service.test.ts delete mode 100644 src/core/server/legacy/legacy_service.ts delete mode 100644 src/core/server/legacy/logging/appenders/__snapshots__/legacy_appender.test.ts.snap delete mode 100644 src/core/server/legacy/logging/appenders/legacy_appender.test.ts delete mode 100644 src/core/server/legacy/logging/appenders/legacy_appender.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 149f5cd74d8c0..244689025173f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -243,7 +243,6 @@ /packages/kbn-std/ @elastic/kibana-core /packages/kbn-config/ @elastic/kibana-core /packages/kbn-logging/ @elastic/kibana-core -/packages/kbn-legacy-logging/ @elastic/kibana-core /packages/kbn-crypto/ @elastic/kibana-core /packages/kbn-http-tools/ @elastic/kibana-core /src/plugins/saved_objects_management/ @elastic/kibana-core diff --git a/config/kibana.yml b/config/kibana.yml index dea9849f17b28..13a4b9bb98e85 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -84,24 +84,32 @@ # Time in milliseconds for Elasticsearch to wait for responses from shards. Set to 0 to disable. #elasticsearch.shardTimeout: 30000 -# Logs queries sent to Elasticsearch. Requires logging.verbose set to true. -#elasticsearch.logQueries: false - # Specifies the path where Kibana creates the process ID file. #pid.file: /run/kibana/kibana.pid +# Set the value of this setting to off to suppress all logging output, or to debug to log everything. +# logging.root.level: debug + # Enables you to specify a file where Kibana stores log output. -#logging.dest: stdout +# logging.appenders.default: +# type: file +# fileName: /var/logs/kibana.log + -# Set the value of this setting to true to suppress all logging output. -#logging.silent: false +# Logs queries sent to Elasticsearch. +# logging.loggers: +# - name: elasticsearch.queries +# level: debug -# Set the value of this setting to true to suppress all logging output other than error messages. -#logging.quiet: false +# Logs http responses. +# logging.loggers: +# - name: http.server.response +# level: debug -# Set the value of this setting to true to log all events, including system usage information -# and all requests. -#logging.verbose: false +# Logs system usage information. +# logging.loggers: +# - name: metrics.ops +# level: debug # Set the interval in milliseconds to sample system and process performance # metrics. Minimum is 100ms. Defaults to 5000. diff --git a/docs/developer/architecture/core/logging-configuration-migration.asciidoc b/docs/developer/architecture/core/logging-configuration-migration.asciidoc index 19f10a881d5e8..db02b4d4e507f 100644 --- a/docs/developer/architecture/core/logging-configuration-migration.asciidoc +++ b/docs/developer/architecture/core/logging-configuration-migration.asciidoc @@ -76,9 +76,5 @@ you can override the flags with: |--verbose| --logging.root.level=debug --logging.root.appenders[0]=default --logging.root.appenders[1]=custom | --verbose -|--quiet| --logging.root.level=error --logging.root.appenders[0]=default --logging.root.appenders[1]=custom | not supported - |--silent| --logging.root.level=off | --silent |=== - -NOTE: To preserve backwards compatibility, you are required to pass the root `default` appender until the legacy logging system is removed in `v8.0`. diff --git a/docs/developer/getting-started/monorepo-packages.asciidoc b/docs/developer/getting-started/monorepo-packages.asciidoc index b42bc980c8758..7754463339771 100644 --- a/docs/developer/getting-started/monorepo-packages.asciidoc +++ b/docs/developer/getting-started/monorepo-packages.asciidoc @@ -74,7 +74,6 @@ yarn kbn watch - @kbn/i18n - @kbn/interpreter - @kbn/io-ts-utils -- @kbn/legacy-logging - @kbn/logging - @kbn/mapbox-gl - @kbn/monaco diff --git a/docs/development/core/server/kibana-plugin-core-server.appenderconfigtype.md b/docs/development/core/server/kibana-plugin-core-server.appenderconfigtype.md index f6de959589eca..7d9772af91c38 100644 --- a/docs/development/core/server/kibana-plugin-core-server.appenderconfigtype.md +++ b/docs/development/core/server/kibana-plugin-core-server.appenderconfigtype.md @@ -8,5 +8,5 @@ Signature: ```typescript -export declare type AppenderConfigType = ConsoleAppenderConfig | FileAppenderConfig | LegacyAppenderConfig | RewriteAppenderConfig | RollingFileAppenderConfig; +export declare type AppenderConfigType = ConsoleAppenderConfig | FileAppenderConfig | RewriteAppenderConfig | RollingFileAppenderConfig; ``` diff --git a/docs/settings/logging-settings.asciidoc b/docs/settings/logging-settings.asciidoc index 77f3bd90a911a..177d1bc8db118 100644 --- a/docs/settings/logging-settings.asciidoc +++ b/docs/settings/logging-settings.asciidoc @@ -12,16 +12,6 @@ Refer to the <> for common configuration use cases. To learn more about possible configuration values, go to {kibana-ref}/logging-service.html[{kib}'s Logging service]. -[[log-settings-compatibility]] -==== Backwards compatibility -Compatibility with the legacy logging system is assured until the end of the `v7` version. -All log messages handled by `root` context (default) are forwarded to the legacy logging service. -The logging configuration is validated against the predefined schema and if there are -any issues with it, {kib} will fail to start with the detailed error message. - -NOTE: When you switch to the new logging configuration, you will start seeing duplicate log entries in both formats. -These will be removed when the `default` appender is no longer required. - [[log-settings-examples]] ==== Examples Here are some configuration examples for the most common logging use cases: diff --git a/docs/user/production-considerations/production.asciidoc b/docs/user/production-considerations/production.asciidoc index 455e07e452807..db8d0738323ff 100644 --- a/docs/user/production-considerations/production.asciidoc +++ b/docs/user/production-considerations/production.asciidoc @@ -32,12 +32,21 @@ server.name Settings unique across each host (for example, running multiple installations on the same virtual machine): [source,js] -------- -logging.dest path.data pid.file server.port -------- +When using a file appender, the target file must also be unique: +[source,yaml] +-------- +logging: + appenders: + default: + type: file + fileName: /unique/path/per/instance +-------- + Settings that must be the same: [source,js] -------- diff --git a/package.json b/package.json index f04a8423196fd..37a5239cf068a 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,6 @@ "@elastic/ems-client": "7.15.0", "@elastic/eui": "38.0.1", "@elastic/filesaver": "1.1.2", - "@elastic/good": "^9.0.1-kibana3", "@elastic/maki": "6.3.0", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", @@ -113,12 +112,10 @@ "@hapi/accept": "^5.0.2", "@hapi/boom": "^9.1.4", "@hapi/cookie": "^11.0.2", - "@hapi/good-squeeze": "6.0.0", "@hapi/h2o2": "^9.1.0", "@hapi/hapi": "^20.2.0", "@hapi/hoek": "^9.2.0", "@hapi/inert": "^6.0.4", - "@hapi/podium": "^4.1.3", "@hapi/wreck": "^17.1.0", "@kbn/ace": "link:bazel-bin/packages/kbn-ace", "@kbn/alerts": "link:bazel-bin/packages/kbn-alerts", @@ -133,7 +130,6 @@ "@kbn/i18n": "link:bazel-bin/packages/kbn-i18n", "@kbn/interpreter": "link:bazel-bin/packages/kbn-interpreter", "@kbn/io-ts-utils": "link:bazel-bin/packages/kbn-io-ts-utils", - "@kbn/legacy-logging": "link:bazel-bin/packages/kbn-legacy-logging", "@kbn/logging": "link:bazel-bin/packages/kbn-logging", "@kbn/mapbox-gl": "link:bazel-bin/packages/kbn-mapbox-gl", "@kbn/monaco": "link:bazel-bin/packages/kbn-monaco", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index 36bdee5303cb7..75c8d700e2843 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -29,7 +29,6 @@ filegroup( "//packages/kbn-i18n:build", "//packages/kbn-interpreter:build", "//packages/kbn-io-ts-utils:build", - "//packages/kbn-legacy-logging:build", "//packages/kbn-logging:build", "//packages/kbn-mapbox-gl:build", "//packages/kbn-monaco:build", diff --git a/packages/kbn-cli-dev-mode/src/bootstrap.ts b/packages/kbn-cli-dev-mode/src/bootstrap.ts index 86a276c64f1f5..0428051b77e31 100644 --- a/packages/kbn-cli-dev-mode/src/bootstrap.ts +++ b/packages/kbn-cli-dev-mode/src/bootstrap.ts @@ -20,7 +20,7 @@ interface BootstrapArgs { } export async function bootstrapDevMode({ configs, cliArgs, applyConfigOverrides }: BootstrapArgs) { - const log = new CliLog(!!cliArgs.quiet, !!cliArgs.silent); + const log = new CliLog(!!cliArgs.silent); const env = Env.createDefault(REPO_ROOT, { configs, diff --git a/packages/kbn-cli-dev-mode/src/cli_dev_mode.test.ts b/packages/kbn-cli-dev-mode/src/cli_dev_mode.test.ts index 8937eadfa4ee3..e5e009e51e69e 100644 --- a/packages/kbn-cli-dev-mode/src/cli_dev_mode.test.ts +++ b/packages/kbn-cli-dev-mode/src/cli_dev_mode.test.ts @@ -74,7 +74,6 @@ const createCliArgs = (parts: Partial = {}): SomeCliArgs => ({ runExamples: false, watch: true, silent: false, - quiet: false, ...parts, }); diff --git a/packages/kbn-cli-dev-mode/src/cli_dev_mode.ts b/packages/kbn-cli-dev-mode/src/cli_dev_mode.ts index 28f38592ff3c4..2396b316aa3a2 100644 --- a/packages/kbn-cli-dev-mode/src/cli_dev_mode.ts +++ b/packages/kbn-cli-dev-mode/src/cli_dev_mode.ts @@ -48,7 +48,6 @@ const GRACEFUL_TIMEOUT = 30000; export type SomeCliArgs = Pick< CliArgs, - | 'quiet' | 'silent' | 'verbose' | 'disableOptimizer' @@ -108,7 +107,7 @@ export class CliDevMode { private subscription?: Rx.Subscription; constructor({ cliArgs, config, log }: { cliArgs: SomeCliArgs; config: CliDevConfig; log?: Log }) { - this.log = log || new CliLog(!!cliArgs.quiet, !!cliArgs.silent); + this.log = log || new CliLog(!!cliArgs.silent); if (cliArgs.basePath) { this.basePathProxy = new BasePathProxyServer(this.log, config.http, config.dev); @@ -163,7 +162,7 @@ export class CliDevMode { runExamples: cliArgs.runExamples, cache: cliArgs.cache, dist: cliArgs.dist, - quiet: !!cliArgs.quiet, + quiet: false, silent: !!cliArgs.silent, verbose: !!cliArgs.verbose, watch: cliArgs.watch, diff --git a/packages/kbn-cli-dev-mode/src/dev_server.test.ts b/packages/kbn-cli-dev-mode/src/dev_server.test.ts index 9962a9a285a42..92dbe484eb005 100644 --- a/packages/kbn-cli-dev-mode/src/dev_server.test.ts +++ b/packages/kbn-cli-dev-mode/src/dev_server.test.ts @@ -130,7 +130,6 @@ describe('#run$', () => { Array [ "foo", "bar", - "--logging.json=false", ], Object { "env": Object { diff --git a/packages/kbn-cli-dev-mode/src/log.ts b/packages/kbn-cli-dev-mode/src/log.ts index 86956abec202a..2cbd02b94a844 100644 --- a/packages/kbn-cli-dev-mode/src/log.ts +++ b/packages/kbn-cli-dev-mode/src/log.ts @@ -21,7 +21,7 @@ export interface Log { export class CliLog implements Log { public toolingLog = new ToolingLog({ - level: this.silent ? 'silent' : this.quiet ? 'error' : 'info', + level: this.silent ? 'silent' : 'info', writeTo: { write: (msg) => { this.write(msg); @@ -29,10 +29,10 @@ export class CliLog implements Log { }, }); - constructor(private readonly quiet: boolean, private readonly silent: boolean) {} + constructor(private readonly silent: boolean) {} good(label: string, ...args: any[]) { - if (this.quiet || this.silent) { + if (this.silent) { return; } @@ -41,7 +41,7 @@ export class CliLog implements Log { } warn(label: string, ...args: any[]) { - if (this.quiet || this.silent) { + if (this.silent) { return; } diff --git a/packages/kbn-cli-dev-mode/src/using_server_process.ts b/packages/kbn-cli-dev-mode/src/using_server_process.ts index 0d0227c63adc2..eb997295035d8 100644 --- a/packages/kbn-cli-dev-mode/src/using_server_process.ts +++ b/packages/kbn-cli-dev-mode/src/using_server_process.ts @@ -25,7 +25,7 @@ export function usingServerProcess( ) { return Rx.using( (): ProcResource => { - const proc = execa.node(script, [...argv, '--logging.json=false'], { + const proc = execa.node(script, argv, { stdio: 'pipe', nodeOptions: [ ...process.execArgv, diff --git a/packages/kbn-config/src/__mocks__/env.ts b/packages/kbn-config/src/__mocks__/env.ts index 6f05f8f1f5a45..124a798501a96 100644 --- a/packages/kbn-config/src/__mocks__/env.ts +++ b/packages/kbn-config/src/__mocks__/env.ts @@ -19,7 +19,6 @@ export function getEnvOptions(options: DeepPartial = {}): EnvOptions configs: options.configs || [], cliArgs: { dev: true, - quiet: false, silent: false, watch: false, basePath: false, diff --git a/packages/kbn-config/src/__snapshots__/env.test.ts.snap b/packages/kbn-config/src/__snapshots__/env.test.ts.snap index 570ed948774cc..a8e2eb62dbedb 100644 --- a/packages/kbn-config/src/__snapshots__/env.test.ts.snap +++ b/packages/kbn-config/src/__snapshots__/env.test.ts.snap @@ -11,7 +11,6 @@ Env { "dist": false, "envName": "development", "oss": false, - "quiet": false, "runExamples": false, "silent": false, "watch": false, @@ -54,7 +53,6 @@ Env { "dist": false, "envName": "production", "oss": false, - "quiet": false, "runExamples": false, "silent": false, "watch": false, @@ -96,7 +94,6 @@ Env { "disableOptimizer": true, "dist": false, "oss": false, - "quiet": false, "runExamples": false, "silent": false, "watch": false, @@ -138,7 +135,6 @@ Env { "disableOptimizer": true, "dist": false, "oss": false, - "quiet": false, "runExamples": false, "silent": false, "watch": false, @@ -180,7 +176,6 @@ Env { "disableOptimizer": true, "dist": false, "oss": false, - "quiet": false, "runExamples": false, "silent": false, "watch": false, @@ -222,7 +217,6 @@ Env { "disableOptimizer": true, "dist": false, "oss": false, - "quiet": false, "runExamples": false, "silent": false, "watch": false, diff --git a/packages/kbn-config/src/config_service.ts b/packages/kbn-config/src/config_service.ts index 5883ce8ab513c..72725fad39610 100644 --- a/packages/kbn-config/src/config_service.ts +++ b/packages/kbn-config/src/config_service.ts @@ -24,7 +24,7 @@ import { DeprecatedConfigDetails, ChangedDeprecatedPaths, } from './deprecation'; -import { LegacyObjectToConfigAdapter } from './legacy'; +import { ObjectToConfigAdapter } from './object_to_config_adapter'; /** @internal */ export type IConfigService = PublicMethodsOf; @@ -71,7 +71,7 @@ export class ConfigService { map(([rawConfig, deprecations]) => { const migrated = applyDeprecations(rawConfig, deprecations); this.deprecatedConfigPaths.next(migrated.changedPaths); - return new LegacyObjectToConfigAdapter(migrated.config); + return new ObjectToConfigAdapter(migrated.config); }), tap((config) => { this.lastConfig = config; diff --git a/packages/kbn-config/src/env.ts b/packages/kbn-config/src/env.ts index 053bb93ce158c..73f32606c463f 100644 --- a/packages/kbn-config/src/env.ts +++ b/packages/kbn-config/src/env.ts @@ -21,8 +21,6 @@ export interface EnvOptions { export interface CliArgs { dev: boolean; envName?: string; - /** @deprecated */ - quiet?: boolean; silent?: boolean; verbose?: boolean; watch: boolean; diff --git a/packages/kbn-config/src/index.ts b/packages/kbn-config/src/index.ts index 08cf12343f459..89f70ab9b6984 100644 --- a/packages/kbn-config/src/index.ts +++ b/packages/kbn-config/src/index.ts @@ -30,5 +30,4 @@ export { Config, ConfigPath, isConfigPath, hasConfigPathIntersection } from './c export { ObjectToConfigAdapter } from './object_to_config_adapter'; export { CliArgs, Env, RawPackageInfo } from './env'; export { EnvironmentMode, PackageInfo } from './types'; -export { LegacyObjectToConfigAdapter, LegacyLoggingConfig } from './legacy'; export { getPluginSearchPaths } from './plugins'; diff --git a/packages/kbn-config/src/legacy/__snapshots__/legacy_object_to_config_adapter.test.ts.snap b/packages/kbn-config/src/legacy/__snapshots__/legacy_object_to_config_adapter.test.ts.snap deleted file mode 100644 index 17ac75e9f3d9e..0000000000000 --- a/packages/kbn-config/src/legacy/__snapshots__/legacy_object_to_config_adapter.test.ts.snap +++ /dev/null @@ -1,95 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`#get correctly handles silent logging config. 1`] = ` -Object { - "appenders": Object { - "default": Object { - "legacyLoggingConfig": Object { - "silent": true, - }, - "type": "legacy-appender", - }, - }, - "loggers": undefined, - "root": Object { - "level": "off", - }, - "silent": true, -} -`; - -exports[`#get correctly handles verbose file logging config with json format. 1`] = ` -Object { - "appenders": Object { - "default": Object { - "legacyLoggingConfig": Object { - "dest": "/some/path.log", - "json": true, - "verbose": true, - }, - "type": "legacy-appender", - }, - }, - "dest": "/some/path.log", - "json": true, - "loggers": undefined, - "root": Object { - "level": "all", - }, - "verbose": true, -} -`; - -exports[`#getFlattenedPaths returns all paths of the underlying object. 1`] = ` -Array [ - "known", - "knownContainer.sub1", - "knownContainer.sub2", - "legacy.known", -] -`; - -exports[`#set correctly sets values for existing paths. 1`] = ` -Object { - "known": "value", - "knownContainer": Object { - "sub1": "sub-value-1", - "sub2": "sub-value-2", - }, -} -`; - -exports[`#set correctly sets values for paths that do not exist. 1`] = ` -Object { - "unknown": Object { - "sub1": "sub-value-1", - "sub2": "sub-value-2", - }, -} -`; - -exports[`#toRaw returns a deep copy of the underlying raw config object. 1`] = ` -Object { - "known": "foo", - "knownContainer": Object { - "sub1": "bar", - "sub2": "baz", - }, - "legacy": Object { - "known": "baz", - }, -} -`; - -exports[`#toRaw returns a deep copy of the underlying raw config object. 2`] = ` -Object { - "known": "bar", - "knownContainer": Object { - "sub1": "baz", - "sub2": "baz", - }, - "legacy": Object { - "known": "baz", - }, -} -`; diff --git a/packages/kbn-config/src/legacy/index.ts b/packages/kbn-config/src/legacy/index.ts deleted file mode 100644 index f6906f81d1821..0000000000000 --- a/packages/kbn-config/src/legacy/index.ts +++ /dev/null @@ -1,12 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { - LegacyObjectToConfigAdapter, - LegacyLoggingConfig, -} from './legacy_object_to_config_adapter'; diff --git a/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.test.ts b/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.test.ts deleted file mode 100644 index 47151503e1634..0000000000000 --- a/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.test.ts +++ /dev/null @@ -1,161 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { LegacyObjectToConfigAdapter } from './legacy_object_to_config_adapter'; - -describe('#get', () => { - test('correctly handles paths that do not exist.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({}); - - expect(configAdapter.get('one')).not.toBeDefined(); - expect(configAdapter.get(['one', 'two'])).not.toBeDefined(); - expect(configAdapter.get(['one.three'])).not.toBeDefined(); - }); - - test('correctly handles paths that do not need to be transformed.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({ - one: 'value-one', - two: { - sub: 'value-two-sub', - }, - container: { - value: 'some', - }, - }); - - expect(configAdapter.get('one')).toEqual('value-one'); - expect(configAdapter.get(['two', 'sub'])).toEqual('value-two-sub'); - expect(configAdapter.get('two.sub')).toEqual('value-two-sub'); - expect(configAdapter.get('container')).toEqual({ value: 'some' }); - }); - - test('correctly handles csp config.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({ - csp: { - rules: ['strict'], - }, - }); - - expect(configAdapter.get('csp')).toMatchInlineSnapshot(` - Object { - "rules": Array [ - "strict", - ], - } - `); - }); - - test('correctly handles silent logging config.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({ - logging: { silent: true }, - }); - - expect(configAdapter.get('logging')).toMatchSnapshot(); - }); - - test('correctly handles verbose file logging config with json format.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({ - logging: { verbose: true, json: true, dest: '/some/path.log' }, - }); - - expect(configAdapter.get('logging')).toMatchSnapshot(); - }); -}); - -describe('#set', () => { - test('correctly sets values for paths that do not exist.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({}); - - configAdapter.set('unknown', 'value'); - configAdapter.set(['unknown', 'sub1'], 'sub-value-1'); - configAdapter.set('unknown.sub2', 'sub-value-2'); - - expect(configAdapter.toRaw()).toMatchSnapshot(); - }); - - test('correctly sets values for existing paths.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({ - known: '', - knownContainer: { - sub1: 'sub-1', - sub2: 'sub-2', - }, - }); - - configAdapter.set('known', 'value'); - configAdapter.set(['knownContainer', 'sub1'], 'sub-value-1'); - configAdapter.set('knownContainer.sub2', 'sub-value-2'); - - expect(configAdapter.toRaw()).toMatchSnapshot(); - }); -}); - -describe('#has', () => { - test('returns false if config is not set', () => { - const configAdapter = new LegacyObjectToConfigAdapter({}); - - expect(configAdapter.has('unknown')).toBe(false); - expect(configAdapter.has(['unknown', 'sub1'])).toBe(false); - expect(configAdapter.has('unknown.sub2')).toBe(false); - }); - - test('returns true if config is set.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({ - known: 'foo', - knownContainer: { - sub1: 'bar', - sub2: 'baz', - }, - }); - - expect(configAdapter.has('known')).toBe(true); - expect(configAdapter.has(['knownContainer', 'sub1'])).toBe(true); - expect(configAdapter.has('knownContainer.sub2')).toBe(true); - }); -}); - -describe('#toRaw', () => { - test('returns a deep copy of the underlying raw config object.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({ - known: 'foo', - knownContainer: { - sub1: 'bar', - sub2: 'baz', - }, - legacy: { known: 'baz' }, - }); - - const firstRawCopy = configAdapter.toRaw(); - - configAdapter.set('known', 'bar'); - configAdapter.set(['knownContainer', 'sub1'], 'baz'); - - const secondRawCopy = configAdapter.toRaw(); - - expect(firstRawCopy).not.toBe(secondRawCopy); - expect(firstRawCopy.knownContainer).not.toBe(secondRawCopy.knownContainer); - - expect(firstRawCopy).toMatchSnapshot(); - expect(secondRawCopy).toMatchSnapshot(); - }); -}); - -describe('#getFlattenedPaths', () => { - test('returns all paths of the underlying object.', () => { - const configAdapter = new LegacyObjectToConfigAdapter({ - known: 'foo', - knownContainer: { - sub1: 'bar', - sub2: 'baz', - }, - legacy: { known: 'baz' }, - }); - - expect(configAdapter.getFlattenedPaths()).toMatchSnapshot(); - }); -}); diff --git a/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.ts b/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.ts deleted file mode 100644 index bc6fd49e2498a..0000000000000 --- a/packages/kbn-config/src/legacy/legacy_object_to_config_adapter.ts +++ /dev/null @@ -1,65 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { ConfigPath } from '../config'; -import { ObjectToConfigAdapter } from '../object_to_config_adapter'; - -/** - * Represents logging config supported by the legacy platform. - */ -export interface LegacyLoggingConfig { - silent?: boolean; - verbose?: boolean; - quiet?: boolean; - dest?: string; - json?: boolean; - events?: Record; -} - -type MixedLoggingConfig = LegacyLoggingConfig & Record; - -/** - * Represents adapter between config provided by legacy platform and `Config` - * supported by the current platform. - * @internal - */ -export class LegacyObjectToConfigAdapter extends ObjectToConfigAdapter { - private static transformLogging(configValue: MixedLoggingConfig = {}) { - const { appenders, root, loggers, ...legacyLoggingConfig } = configValue; - - const loggingConfig = { - appenders: { - ...appenders, - default: { type: 'legacy-appender', legacyLoggingConfig }, - }, - root: { level: 'info', ...root }, - loggers, - ...legacyLoggingConfig, - }; - - if (configValue.silent) { - loggingConfig.root.level = 'off'; - } else if (configValue.quiet) { - loggingConfig.root.level = 'error'; - } else if (configValue.verbose) { - loggingConfig.root.level = 'all'; - } - - return loggingConfig; - } - - public get(configPath: ConfigPath) { - const configValue = super.get(configPath); - switch (configPath) { - case 'logging': - return LegacyObjectToConfigAdapter.transformLogging(configValue as LegacyLoggingConfig); - default: - return configValue; - } - } -} diff --git a/packages/kbn-legacy-logging/BUILD.bazel b/packages/kbn-legacy-logging/BUILD.bazel deleted file mode 100644 index c4927fe076e15..0000000000000 --- a/packages/kbn-legacy-logging/BUILD.bazel +++ /dev/null @@ -1,107 +0,0 @@ -load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project") -load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm") -load("//src/dev/bazel:index.bzl", "jsts_transpiler") - -PKG_BASE_NAME = "kbn-legacy-logging" -PKG_REQUIRE_NAME = "@kbn/legacy-logging" - -SOURCE_FILES = glob( - [ - "src/**/*.ts", - ], - exclude = ["**/*.test.*"], -) - -SRCS = SOURCE_FILES - -filegroup( - name = "srcs", - srcs = SRCS, -) - -NPM_MODULE_EXTRA_FILES = [ - "package.json", - "README.md" -] - -RUNTIME_DEPS = [ - "//packages/kbn-config-schema", - "//packages/kbn-utils", - "@npm//@elastic/numeral", - "@npm//@hapi/hapi", - "@npm//@hapi/podium", - "@npm//chokidar", - "@npm//lodash", - "@npm//moment-timezone", - "@npm//query-string", - "@npm//rxjs", - "@npm//tslib", -] - -TYPES_DEPS = [ - "//packages/kbn-config-schema", - "//packages/kbn-utils", - "@npm//@elastic/numeral", - "@npm//@hapi/podium", - "@npm//chokidar", - "@npm//query-string", - "@npm//rxjs", - "@npm//tslib", - "@npm//@types/hapi__hapi", - "@npm//@types/jest", - "@npm//@types/lodash", - "@npm//@types/moment-timezone", - "@npm//@types/node", -] - -jsts_transpiler( - name = "target_node", - srcs = SRCS, - build_pkg_name = package_name(), -) - -ts_config( - name = "tsconfig", - src = "tsconfig.json", - deps = [ - "//:tsconfig.base.json", - "//:tsconfig.bazel.json", - ], -) - -ts_project( - name = "tsc_types", - args = ['--pretty'], - srcs = SRCS, - deps = TYPES_DEPS, - declaration = True, - declaration_map = True, - emit_declaration_only = True, - out_dir = "target_types", - source_map = True, - root_dir = "src", - tsconfig = ":tsconfig", -) - -js_library( - name = PKG_BASE_NAME, - srcs = NPM_MODULE_EXTRA_FILES, - deps = RUNTIME_DEPS + [":target_node", ":tsc_types"], - package_name = PKG_REQUIRE_NAME, - visibility = ["//visibility:public"], -) - -pkg_npm( - name = "npm_module", - deps = [ - ":%s" % PKG_BASE_NAME, - ] -) - -filegroup( - name = "build", - srcs = [ - ":npm_module", - ], - visibility = ["//visibility:public"], -) diff --git a/packages/kbn-legacy-logging/README.md b/packages/kbn-legacy-logging/README.md deleted file mode 100644 index 4c5989fc892dc..0000000000000 --- a/packages/kbn-legacy-logging/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# @kbn/legacy-logging - -This package contains the implementation of the legacy logging -system, based on `@hapi/good` \ No newline at end of file diff --git a/packages/kbn-legacy-logging/jest.config.js b/packages/kbn-legacy-logging/jest.config.js deleted file mode 100644 index d00b1c56dae81..0000000000000 --- a/packages/kbn-legacy-logging/jest.config.js +++ /dev/null @@ -1,13 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../..', - roots: ['/packages/kbn-legacy-logging'], -}; diff --git a/packages/kbn-legacy-logging/package.json b/packages/kbn-legacy-logging/package.json deleted file mode 100644 index 6e846ffc5bfaf..0000000000000 --- a/packages/kbn-legacy-logging/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@kbn/legacy-logging", - "version": "1.0.0", - "private": true, - "license": "SSPL-1.0 OR Elastic License 2.0", - "main": "./target_node/index.js", - "types": "./target_types/index.d.ts" -} diff --git a/packages/kbn-legacy-logging/src/get_logging_config.ts b/packages/kbn-legacy-logging/src/get_logging_config.ts deleted file mode 100644 index f74bc5904e24b..0000000000000 --- a/packages/kbn-legacy-logging/src/get_logging_config.ts +++ /dev/null @@ -1,85 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import _ from 'lodash'; -import { getLogReporter } from './log_reporter'; -import { LegacyLoggingConfig } from './schema'; - -/** - * Returns the `@hapi/good` plugin configuration to be used for the legacy logging - * @param config - */ -export function getLoggingConfiguration(config: LegacyLoggingConfig, opsInterval: number) { - const events = config.events; - - if (config.silent) { - _.defaults(events, {}); - } else if (config.quiet) { - _.defaults(events, { - log: ['listening', 'error', 'fatal'], - request: ['error'], - error: '*', - }); - } else if (config.verbose) { - _.defaults(events, { - error: '*', - log: '*', - // To avoid duplicate logs, we explicitly disable these in verbose - // mode as they are already provided by the new logging config under - // the `http.server.response` and `metrics.ops` contexts. - ops: '!', - request: '!', - response: '!', - }); - } else { - _.defaults(events, { - log: ['info', 'warning', 'error', 'fatal'], - request: ['info', 'warning', 'error', 'fatal'], - error: '*', - }); - } - - const loggerStream = getLogReporter({ - config: { - json: config.json, - dest: config.dest, - timezone: config.timezone, - - // I'm adding the default here because if you add another filter - // using the commandline it will remove authorization. I want users - // to have to explicitly set --logging.filter.authorization=none or - // --logging.filter.cookie=none to have it show up in the logs. - filter: _.defaults(config.filter, { - authorization: 'remove', - cookie: 'remove', - }), - }, - events: _.transform( - events, - function (filtered: Record, val: string, key: string) { - // provide a string compatible way to remove events - if (val !== '!') filtered[key] = val; - }, - {} - ), - }); - - const options = { - ops: { - interval: opsInterval, - }, - includes: { - request: ['headers', 'payload'], - response: ['headers', 'payload'], - }, - reporters: { - logReporter: [loggerStream], - }, - }; - return options; -} diff --git a/packages/kbn-legacy-logging/src/index.ts b/packages/kbn-legacy-logging/src/index.ts deleted file mode 100644 index 670df4e95f337..0000000000000 --- a/packages/kbn-legacy-logging/src/index.ts +++ /dev/null @@ -1,14 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { LegacyLoggingConfig, legacyLoggingConfigSchema } from './schema'; -export { attachMetaData } from './metadata'; -export { setupLoggingRotate } from './rotate'; -export { setupLogging, reconfigureLogging } from './setup_logging'; -export { getLoggingConfiguration } from './get_logging_config'; -export { LegacyLoggingServer } from './legacy_logging_server'; diff --git a/packages/kbn-legacy-logging/src/legacy_logging_server.test.ts b/packages/kbn-legacy-logging/src/legacy_logging_server.test.ts deleted file mode 100644 index 40019fc90ff42..0000000000000 --- a/packages/kbn-legacy-logging/src/legacy_logging_server.test.ts +++ /dev/null @@ -1,105 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -jest.mock('./setup_logging'); - -import { LegacyLoggingServer, LogRecord } from './legacy_logging_server'; - -test('correctly forwards log records.', () => { - const loggingServer = new LegacyLoggingServer({ events: {} }); - const onLogMock = jest.fn(); - loggingServer.events.on('log', onLogMock); - - const timestamp = 1554433221100; - const firstLogRecord: LogRecord = { - timestamp: new Date(timestamp), - pid: 5355, - level: { - id: 'info', - value: 5, - }, - context: 'some-context', - message: 'some-message', - }; - - const secondLogRecord: LogRecord = { - timestamp: new Date(timestamp), - pid: 5355, - level: { - id: 'error', - value: 3, - }, - context: 'some-context.sub-context', - message: 'some-message', - meta: { unknown: 2 }, - error: new Error('some-error'), - }; - - const thirdLogRecord: LogRecord = { - timestamp: new Date(timestamp), - pid: 5355, - level: { - id: 'trace', - value: 7, - }, - context: 'some-context.sub-context', - message: 'some-message', - meta: { tags: ['important', 'tags'], unknown: 2 }, - }; - - loggingServer.log(firstLogRecord); - loggingServer.log(secondLogRecord); - loggingServer.log(thirdLogRecord); - - expect(onLogMock).toHaveBeenCalledTimes(3); - - const [[firstCall], [secondCall], [thirdCall]] = onLogMock.mock.calls; - expect(firstCall).toMatchInlineSnapshot(` -Object { - "data": "some-message", - "tags": Array [ - "info", - "some-context", - ], - "timestamp": 1554433221100, -} -`); - - expect(secondCall).toMatchInlineSnapshot(` -Object { - "data": [Error: some-error], - "tags": Array [ - "error", - "some-context", - "sub-context", - ], - "timestamp": 1554433221100, -} -`); - - expect(thirdCall).toMatchInlineSnapshot(` -Object { - "data": Object { - Symbol(log message with metadata): Object { - "message": "some-message", - "metadata": Object { - "unknown": 2, - }, - }, - }, - "tags": Array [ - "debug", - "some-context", - "sub-context", - "important", - "tags", - ], - "timestamp": 1554433221100, -} -`); -}); diff --git a/packages/kbn-legacy-logging/src/legacy_logging_server.ts b/packages/kbn-legacy-logging/src/legacy_logging_server.ts deleted file mode 100644 index f6c42dd1b161f..0000000000000 --- a/packages/kbn-legacy-logging/src/legacy_logging_server.ts +++ /dev/null @@ -1,140 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { ServerExtType, Server } from '@hapi/hapi'; -import Podium from '@hapi/podium'; -import { setupLogging } from './setup_logging'; -import { attachMetaData } from './metadata'; -import { legacyLoggingConfigSchema } from './schema'; - -// these LogXXX types are duplicated to avoid a cross dependency with the @kbn/logging package. -// typescript will error if they diverge at some point. -type LogLevelId = 'all' | 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'off'; - -interface LogLevel { - id: LogLevelId; - value: number; -} - -export interface LogRecord { - timestamp: Date; - level: LogLevel; - context: string; - message: string; - error?: Error; - meta?: { [name: string]: any }; - pid: number; -} - -const isEmptyObject = (obj: object) => Object.keys(obj).length === 0; - -function getDataToLog(error: Error | undefined, metadata: object, message: string) { - if (error) { - return error; - } - if (!isEmptyObject(metadata)) { - return attachMetaData(message, metadata); - } - return message; -} - -interface PluginRegisterParams { - plugin: { - register: ( - server: LegacyLoggingServer, - options: PluginRegisterParams['options'] - ) => Promise; - }; - options: Record; -} - -/** - * Converts core log level to a one that's known to the legacy platform. - * @param level Log level from the core. - */ -function getLegacyLogLevel(level: LogLevel) { - const logLevel = level.id.toLowerCase(); - if (logLevel === 'warn') { - return 'warning'; - } - - if (logLevel === 'trace') { - return 'debug'; - } - - return logLevel; -} - -/** - * The "legacy" Kibana uses Hapi server + even-better plugin to log, so we should - * use the same approach here to make log records generated by the core to look the - * same as the rest of the records generated by the "legacy" Kibana. But to reduce - * overhead of having full blown Hapi server instance we create our own "light" version. - * @internal - */ -export class LegacyLoggingServer { - public connections = []; - // Emulates Hapi's usage of the podium event bus. - public events: Podium = new Podium(['log', 'request', 'response']); - - private onPostStopCallback?: () => void; - - constructor(legacyLoggingConfig: any) { - // We set `ops.interval` to max allowed number and `ops` filter to value - // that doesn't exist to avoid logging of ops at all, if turned on it will be - // logged by the "legacy" Kibana. - const loggingConfig = legacyLoggingConfigSchema.validate({ - ...legacyLoggingConfig, - events: { - ...legacyLoggingConfig.events, - ops: '__no-ops__', - }, - }); - - setupLogging(this as unknown as Server, loggingConfig, 2147483647); - } - - public register({ plugin: { register }, options }: PluginRegisterParams): Promise { - return register(this, options); - } - - public log({ level, context, message, error, timestamp, meta = {} }: LogRecord) { - const { tags = [], ...metadata } = meta; - - this.events - .emit('log', { - data: getDataToLog(error, metadata, message), - tags: [getLegacyLogLevel(level), ...context.split('.'), ...tags], - timestamp: timestamp.getTime(), - }) - .catch((err) => { - // eslint-disable-next-line no-console - console.error('An unexpected error occurred while writing to the log:', err.stack); - process.exit(1); - }); - } - - public stop() { - // Tell the plugin we're stopping. - if (this.onPostStopCallback !== undefined) { - this.onPostStopCallback(); - } - } - - public ext(eventName: ServerExtType, callback: () => void) { - // method is called by plugin that's being registered. - if (eventName === 'onPostStop') { - this.onPostStopCallback = callback; - } - // We don't care about any others the plugin registers - } - - public expose() { - // method is called by plugin that's being registered. - } -} diff --git a/packages/kbn-legacy-logging/src/log_events.ts b/packages/kbn-legacy-logging/src/log_events.ts deleted file mode 100644 index 193bfbea42ace..0000000000000 --- a/packages/kbn-legacy-logging/src/log_events.ts +++ /dev/null @@ -1,71 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { ResponseObject } from '@hapi/hapi'; -import { EventData, isEventData } from './metadata'; - -export interface BaseEvent { - event: string; - timestamp: number; - pid: number; - tags?: string[]; -} - -export interface ResponseEvent extends BaseEvent { - event: 'response'; - method: 'GET' | 'POST' | 'PUT' | 'DELETE'; - statusCode: number; - path: string; - headers: Record; - responseHeaders: Record; - responsePayload: ResponseObject['source']; - responseTime: string; - query: Record; -} - -export interface OpsEvent extends BaseEvent { - event: 'ops'; - os: { - load: string[]; - }; - proc: Record; - load: string; -} - -export interface ErrorEvent extends BaseEvent { - event: 'error'; - error: Error; - url: string; -} - -export interface UndeclaredErrorEvent extends BaseEvent { - error: Error; -} - -export interface LogEvent extends BaseEvent { - data: EventData; -} - -export interface UnkownEvent extends BaseEvent { - data: string | Record; -} - -export type AnyEvent = - | ResponseEvent - | OpsEvent - | ErrorEvent - | UndeclaredErrorEvent - | LogEvent - | UnkownEvent; - -export const isResponseEvent = (e: AnyEvent): e is ResponseEvent => e.event === 'response'; -export const isOpsEvent = (e: AnyEvent): e is OpsEvent => e.event === 'ops'; -export const isErrorEvent = (e: AnyEvent): e is ErrorEvent => e.event === 'error'; -export const isLogEvent = (e: AnyEvent): e is LogEvent => isEventData((e as LogEvent).data); -export const isUndeclaredErrorEvent = (e: AnyEvent): e is UndeclaredErrorEvent => - (e as any).error instanceof Error; diff --git a/packages/kbn-legacy-logging/src/log_format.ts b/packages/kbn-legacy-logging/src/log_format.ts deleted file mode 100644 index a0eaf023dff19..0000000000000 --- a/packages/kbn-legacy-logging/src/log_format.ts +++ /dev/null @@ -1,176 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import Stream from 'stream'; -import moment from 'moment-timezone'; -import _ from 'lodash'; -import queryString from 'query-string'; -import numeral from '@elastic/numeral'; -import chalk from 'chalk'; -import { inspect } from 'util'; - -import { applyFiltersToKeys, getResponsePayloadBytes } from './utils'; -import { getLogEventData } from './metadata'; -import { LegacyLoggingConfig } from './schema'; -import { - AnyEvent, - ResponseEvent, - isResponseEvent, - isOpsEvent, - isErrorEvent, - isLogEvent, - isUndeclaredErrorEvent, -} from './log_events'; - -export type LogFormatConfig = Pick; - -function serializeError(err: any = {}) { - return { - message: err.message, - name: err.name, - stack: err.stack, - code: err.code, - signal: err.signal, - }; -} - -const levelColor = function (code: number) { - if (code < 299) return chalk.green(String(code)); - if (code < 399) return chalk.yellow(String(code)); - if (code < 499) return chalk.magentaBright(String(code)); - return chalk.red(String(code)); -}; - -export abstract class BaseLogFormat extends Stream.Transform { - constructor(private readonly config: LogFormatConfig) { - super({ - readableObjectMode: false, - writableObjectMode: true, - }); - } - - abstract format(data: Record): string; - - filter(data: Record) { - if (!this.config.filter) { - return data; - } - return applyFiltersToKeys(data, this.config.filter); - } - - _transform(event: AnyEvent, enc: string, next: Stream.TransformCallback) { - const data = this.filter(this.readEvent(event)); - this.push(this.format(data) + '\n'); - next(); - } - - getContentLength({ responsePayload, responseHeaders }: ResponseEvent): number | undefined { - try { - return getResponsePayloadBytes(responsePayload, responseHeaders); - } catch (e) { - // We intentionally swallow any errors as this information is - // only a nicety for logging purposes, and should not cause the - // server to crash if it cannot be determined. - this.push( - this.format({ - type: 'log', - tags: ['warning', 'logging'], - message: `Failed to calculate response payload bytes. [${e}]`, - }) + '\n' - ); - } - } - - extractAndFormatTimestamp(data: Record, format?: string) { - const { timezone } = this.config; - const date = moment(data['@timestamp']); - if (timezone) { - date.tz(timezone); - } - return date.format(format); - } - - readEvent(event: AnyEvent) { - const data: Record = { - type: event.event, - '@timestamp': event.timestamp, - tags: [...(event.tags || [])], - pid: event.pid, - }; - - if (isResponseEvent(event)) { - _.defaults(data, _.pick(event, ['method', 'statusCode'])); - - const source = _.get(event, 'source', {}); - data.req = { - url: event.path, - method: event.method || '', - headers: event.headers, - remoteAddress: source.remoteAddress, - userAgent: source.userAgent, - referer: source.referer, - }; - - data.res = { - statusCode: event.statusCode, - responseTime: event.responseTime, - contentLength: this.getContentLength(event), - }; - - const query = queryString.stringify(event.query, { sort: false }); - if (query) { - data.req.url += '?' + query; - } - - data.message = data.req.method.toUpperCase() + ' '; - data.message += data.req.url; - data.message += ' '; - data.message += levelColor(data.res.statusCode); - data.message += ' '; - data.message += chalk.gray(data.res.responseTime + 'ms'); - if (data.res.contentLength) { - data.message += chalk.gray(' - ' + numeral(data.res.contentLength).format('0.0b')); - } - } else if (isOpsEvent(event)) { - _.defaults(data, _.pick(event, ['pid', 'os', 'proc', 'load'])); - data.message = chalk.gray('memory: '); - data.message += numeral(_.get(data, 'proc.mem.heapUsed')).format('0.0b'); - data.message += ' '; - data.message += chalk.gray('uptime: '); - data.message += numeral(_.get(data, 'proc.uptime')).format('00:00:00'); - data.message += ' '; - data.message += chalk.gray('load: ['); - data.message += _.get(data, 'os.load', []) - .map((val: number) => { - return numeral(val).format('0.00'); - }) - .join(' '); - data.message += chalk.gray(']'); - data.message += ' '; - data.message += chalk.gray('delay: '); - data.message += numeral(_.get(data, 'proc.delay')).format('0.000'); - } else if (isErrorEvent(event)) { - data.level = 'error'; - data.error = serializeError(event.error); - data.url = event.url; - const message = _.get(event, 'error.message'); - data.message = message || 'Unknown error (no message)'; - } else if (isUndeclaredErrorEvent(event)) { - data.type = 'error'; - data.level = _.includes(event.tags, 'fatal') ? 'fatal' : 'error'; - data.error = serializeError(event.error); - const message = _.get(event, 'error.message'); - data.message = message || 'Unknown error object (no message)'; - } else if (isLogEvent(event)) { - _.assign(data, getLogEventData(event.data)); - } else { - data.message = _.isString(event.data) ? event.data : inspect(event.data); - } - return data; - } -} diff --git a/packages/kbn-legacy-logging/src/log_format_json.test.ts b/packages/kbn-legacy-logging/src/log_format_json.test.ts deleted file mode 100644 index 3255c5d17bb30..0000000000000 --- a/packages/kbn-legacy-logging/src/log_format_json.test.ts +++ /dev/null @@ -1,281 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import moment from 'moment'; - -import { attachMetaData } from './metadata'; -import { createListStream, createPromiseFromStreams } from '@kbn/utils'; -import { KbnLoggerJsonFormat } from './log_format_json'; - -const time = +moment('2010-01-01T05:15:59Z', moment.ISO_8601); - -const makeEvent = (eventType: string) => ({ - event: eventType, - timestamp: time, -}); - -describe('KbnLoggerJsonFormat', () => { - const config: any = {}; - - describe('event types and messages', () => { - let format: KbnLoggerJsonFormat; - beforeEach(() => { - format = new KbnLoggerJsonFormat(config); - }); - - it('log', async () => { - const result = await createPromiseFromStreams([ - createListStream([makeEvent('log')]), - format, - ]); - const { type, message } = JSON.parse(result); - - expect(type).toBe('log'); - expect(message).toBe('undefined'); - }); - - describe('response', () => { - it('handles a response object', async () => { - const event = { - ...makeEvent('response'), - statusCode: 200, - contentLength: 800, - responseTime: 12000, - method: 'GET', - path: '/path/to/resource', - responsePayload: '1234567879890', - source: { - remoteAddress: '127.0.0.1', - userAgent: 'Test Thing', - referer: 'elastic.co', - }, - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { type, method, statusCode, message, req } = JSON.parse(result); - - expect(type).toBe('response'); - expect(method).toBe('GET'); - expect(statusCode).toBe(200); - expect(message).toBe('GET /path/to/resource 200 12000ms - 13.0B'); - expect(req.remoteAddress).toBe('127.0.0.1'); - expect(req.userAgent).toBe('Test Thing'); - }); - - it('leaves payload size empty if not available', async () => { - const event = { - ...makeEvent('response'), - statusCode: 200, - responseTime: 12000, - method: 'GET', - path: '/path/to/resource', - responsePayload: null, - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - expect(JSON.parse(result).message).toBe('GET /path/to/resource 200 12000ms'); - }); - }); - - it('ops', async () => { - const event = { - ...makeEvent('ops'), - os: { - load: [1, 1, 2], - }, - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { type, message } = JSON.parse(result); - - expect(type).toBe('ops'); - expect(message).toBe('memory: 0.0B uptime: 0:00:00 load: [1.00 1.00 2.00] delay: 0.000'); - }); - - describe('with metadata', () => { - it('logs an event with meta data', async () => { - const event = { - data: attachMetaData('message for event', { - prop1: 'value1', - prop2: 'value2', - }), - tags: ['tag1', 'tag2'], - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { level, message, prop1, prop2, tags } = JSON.parse(result); - - expect(level).toBe(undefined); - expect(message).toBe('message for event'); - expect(prop1).toBe('value1'); - expect(prop2).toBe('value2'); - expect(tags).toEqual(['tag1', 'tag2']); - }); - - it('meta data rewrites event fields', async () => { - const event = { - data: attachMetaData('message for event', { - tags: ['meta-data-tag'], - prop1: 'value1', - prop2: 'value2', - }), - tags: ['tag1', 'tag2'], - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { level, message, prop1, prop2, tags } = JSON.parse(result); - - expect(level).toBe(undefined); - expect(message).toBe('message for event'); - expect(prop1).toBe('value1'); - expect(prop2).toBe('value2'); - expect(tags).toEqual(['meta-data-tag']); - }); - - it('logs an event with empty meta data', async () => { - const event = { - data: attachMetaData('message for event'), - tags: ['tag1', 'tag2'], - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { level, message, prop1, prop2, tags } = JSON.parse(result); - - expect(level).toBe(undefined); - expect(message).toBe('message for event'); - expect(prop1).toBe(undefined); - expect(prop2).toBe(undefined); - expect(tags).toEqual(['tag1', 'tag2']); - }); - - it('does not log meta data for an error event', async () => { - const event = { - error: new Error('reason'), - data: attachMetaData('message for event', { - prop1: 'value1', - prop2: 'value2', - }), - tags: ['tag1', 'tag2'], - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { level, message, prop1, prop2, tags } = JSON.parse(result); - - expect(level).toBe('error'); - expect(message).toBe('reason'); - expect(prop1).toBe(undefined); - expect(prop2).toBe(undefined); - expect(tags).toEqual(['tag1', 'tag2']); - }); - }); - - describe('errors', () => { - it('error type', async () => { - const event = { - ...makeEvent('error'), - error: { - message: 'test error 0', - }, - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { level, message, error } = JSON.parse(result); - - expect(level).toBe('error'); - expect(message).toBe('test error 0'); - expect(error).toEqual({ message: 'test error 0' }); - }); - - it('with no message', async () => { - const event = { - event: 'error', - error: {}, - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { level, message, error } = JSON.parse(result); - - expect(level).toBe('error'); - expect(message).toBe('Unknown error (no message)'); - expect(error).toEqual({}); - }); - - it('event error instanceof Error', async () => { - const event = { - error: new Error('test error 2') as any, - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { level, message, error } = JSON.parse(result); - - expect(level).toBe('error'); - expect(message).toBe('test error 2'); - - expect(error.message).toBe(event.error.message); - expect(error.name).toBe(event.error.name); - expect(error.stack).toBe(event.error.stack); - expect(error.code).toBe(event.error.code); - expect(error.signal).toBe(event.error.signal); - }); - - it('event error instanceof Error - fatal', async () => { - const event = { - error: new Error('test error 2') as any, - tags: ['fatal', 'tag2'], - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { tags, level, message, error } = JSON.parse(result); - - expect(tags).toEqual(['fatal', 'tag2']); - expect(level).toBe('fatal'); - expect(message).toBe('test error 2'); - - expect(error.message).toBe(event.error.message); - expect(error.name).toBe(event.error.name); - expect(error.stack).toBe(event.error.stack); - expect(error.code).toBe(event.error.code); - expect(error.signal).toBe(event.error.signal); - }); - - it('event error instanceof Error, no message', async () => { - const event = { - error: new Error('') as any, - }; - const result = await createPromiseFromStreams([createListStream([event]), format]); - const { level, message, error } = JSON.parse(result); - - expect(level).toBe('error'); - expect(message).toBe('Unknown error object (no message)'); - - expect(error.message).toBe(event.error.message); - expect(error.name).toBe(event.error.name); - expect(error.stack).toBe(event.error.stack); - expect(error.code).toBe(event.error.code); - expect(error.signal).toBe(event.error.signal); - }); - }); - }); - - describe('timezone', () => { - it('logs in UTC', async () => { - const format = new KbnLoggerJsonFormat({ - timezone: 'UTC', - } as any); - - const result = await createPromiseFromStreams([ - createListStream([makeEvent('log')]), - format, - ]); - - const { '@timestamp': timestamp } = JSON.parse(result); - expect(timestamp).toBe(moment.utc(time).format()); - }); - - it('logs in local timezone timezone is undefined', async () => { - const format = new KbnLoggerJsonFormat({} as any); - - const result = await createPromiseFromStreams([ - createListStream([makeEvent('log')]), - format, - ]); - - const { '@timestamp': timestamp } = JSON.parse(result); - expect(timestamp).toBe(moment(time).format()); - }); - }); -}); diff --git a/packages/kbn-legacy-logging/src/log_format_json.ts b/packages/kbn-legacy-logging/src/log_format_json.ts deleted file mode 100644 index 427415d1715a6..0000000000000 --- a/packages/kbn-legacy-logging/src/log_format_json.ts +++ /dev/null @@ -1,23 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -// @ts-expect-error missing type def -import stringify from 'json-stringify-safe'; -import { BaseLogFormat } from './log_format'; - -const stripColors = function (string: string) { - return string.replace(/\u001b[^m]+m/g, ''); -}; - -export class KbnLoggerJsonFormat extends BaseLogFormat { - format(data: Record) { - data.message = stripColors(data.message); - data['@timestamp'] = this.extractAndFormatTimestamp(data); - return stringify(data); - } -} diff --git a/packages/kbn-legacy-logging/src/log_format_string.test.ts b/packages/kbn-legacy-logging/src/log_format_string.test.ts deleted file mode 100644 index 3ea02c2cfb286..0000000000000 --- a/packages/kbn-legacy-logging/src/log_format_string.test.ts +++ /dev/null @@ -1,64 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import moment from 'moment'; - -import { attachMetaData } from './metadata'; -import { createListStream, createPromiseFromStreams } from '@kbn/utils'; -import { KbnLoggerStringFormat } from './log_format_string'; - -const time = +moment('2010-01-01T05:15:59Z', moment.ISO_8601); - -const makeEvent = () => ({ - event: 'log', - timestamp: time, - tags: ['tag'], - pid: 1, - data: 'my log message', -}); - -describe('KbnLoggerStringFormat', () => { - it('logs in UTC', async () => { - const format = new KbnLoggerStringFormat({ - timezone: 'UTC', - } as any); - - const result = await createPromiseFromStreams([createListStream([makeEvent()]), format]); - - expect(String(result)).toContain(moment.utc(time).format('HH:mm:ss.SSS')); - }); - - it('logs in local timezone when timezone is undefined', async () => { - const format = new KbnLoggerStringFormat({} as any); - - const result = await createPromiseFromStreams([createListStream([makeEvent()]), format]); - - expect(String(result)).toContain(moment(time).format('HH:mm:ss.SSS')); - }); - describe('with metadata', () => { - it('does not log meta data', async () => { - const format = new KbnLoggerStringFormat({} as any); - const event = { - data: attachMetaData('message for event', { - prop1: 'value1', - }), - tags: ['tag1', 'tag2'], - }; - - const result = await createPromiseFromStreams([createListStream([event]), format]); - - const resultString = String(result); - expect(resultString).toContain('tag1'); - expect(resultString).toContain('tag2'); - expect(resultString).toContain('message for event'); - - expect(resultString).not.toContain('value1'); - expect(resultString).not.toContain('prop1'); - }); - }); -}); diff --git a/packages/kbn-legacy-logging/src/log_format_string.ts b/packages/kbn-legacy-logging/src/log_format_string.ts deleted file mode 100644 index da21e56e00340..0000000000000 --- a/packages/kbn-legacy-logging/src/log_format_string.ts +++ /dev/null @@ -1,65 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import _ from 'lodash'; -import chalk from 'chalk'; - -import { BaseLogFormat } from './log_format'; - -const statuses = ['err', 'info', 'error', 'warning', 'fatal', 'status', 'debug']; - -const typeColors: Record = { - log: 'white', - req: 'green', - res: 'green', - ops: 'cyan', - config: 'cyan', - err: 'red', - info: 'green', - error: 'red', - warning: 'red', - fatal: 'magentaBright', - status: 'yellowBright', - debug: 'gray', - server: 'gray', - optmzr: 'white', - manager: 'green', - optimize: 'magentaBright', - listening: 'magentaBright', - scss: 'magentaBright', -}; - -const color = _.memoize((name: string): ((...text: string[]) => string) => { - // @ts-expect-error couldn't even get rid of the error with an any cast - return chalk[typeColors[name]] || _.identity; -}); - -const type = _.memoize((t: string) => { - return color(t)(_.pad(t, 7).slice(0, 7)); -}); - -const prefix = process.env.isDevCliChild ? `${type('server')} ` : ''; - -export class KbnLoggerStringFormat extends BaseLogFormat { - format(data: Record) { - const time = color('time')(this.extractAndFormatTimestamp(data, 'HH:mm:ss.SSS')); - const msg = data.error ? color('error')(data.error.stack) : color('message')(data.message); - - const tags = _(data.tags) - .sortBy(function (tag) { - if (color(tag) === _.identity) return `2${tag}`; - if (_.includes(statuses, tag)) return `0${tag}`; - return `1${tag}`; - }) - .reduce(function (s, t) { - return s + `[${color(t)(t)}]`; - }, ''); - - return `${prefix}${type(data.type)} [${time}] ${tags} ${msg}`; - } -} diff --git a/packages/kbn-legacy-logging/src/log_interceptor.test.ts b/packages/kbn-legacy-logging/src/log_interceptor.test.ts deleted file mode 100644 index 53d622444ece8..0000000000000 --- a/packages/kbn-legacy-logging/src/log_interceptor.test.ts +++ /dev/null @@ -1,153 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { ErrorEvent } from './log_events'; -import { LogInterceptor } from './log_interceptor'; - -function stubClientErrorEvent(errorMeta: Record): ErrorEvent { - const error = new Error(); - Object.assign(error, errorMeta); - return { - event: 'error', - url: '', - pid: 1234, - timestamp: Date.now(), - tags: ['connection', 'client', 'error'], - error, - }; -} - -const stubEconnresetEvent = () => stubClientErrorEvent({ code: 'ECONNRESET' }); -const stubEpipeEvent = () => stubClientErrorEvent({ errno: 'EPIPE' }); -const stubEcanceledEvent = () => stubClientErrorEvent({ errno: 'ECANCELED' }); - -function assertDowngraded(transformed: Record) { - expect(!!transformed).toBe(true); - expect(transformed).toHaveProperty('event', 'log'); - expect(transformed).toHaveProperty('tags'); - expect(transformed.tags).not.toContain('error'); -} - -describe('server logging LogInterceptor', () => { - describe('#downgradeIfEconnreset()', () => { - it('transforms ECONNRESET events', () => { - const interceptor = new LogInterceptor(); - const event = stubEconnresetEvent(); - assertDowngraded(interceptor.downgradeIfEconnreset(event)!); - }); - - it('does not match if the tags are not in order', () => { - const interceptor = new LogInterceptor(); - const event = stubEconnresetEvent(); - event.tags = [...event.tags!.slice(1), event.tags![0]]; - expect(interceptor.downgradeIfEconnreset(event)).toBe(null); - }); - - it('ignores non ECONNRESET events', () => { - const interceptor = new LogInterceptor(); - const event = stubClientErrorEvent({ errno: 'not ECONNRESET' }); - expect(interceptor.downgradeIfEconnreset(event)).toBe(null); - }); - - it('ignores if tags are wrong', () => { - const interceptor = new LogInterceptor(); - const event = stubEconnresetEvent(); - event.tags = ['different', 'tags']; - expect(interceptor.downgradeIfEconnreset(event)).toBe(null); - }); - }); - - describe('#downgradeIfEpipe()', () => { - it('transforms EPIPE events', () => { - const interceptor = new LogInterceptor(); - const event = stubEpipeEvent(); - assertDowngraded(interceptor.downgradeIfEpipe(event)!); - }); - - it('does not match if the tags are not in order', () => { - const interceptor = new LogInterceptor(); - const event = stubEpipeEvent(); - event.tags = [...event.tags!.slice(1), event.tags![0]]; - expect(interceptor.downgradeIfEpipe(event)).toBe(null); - }); - - it('ignores non EPIPE events', () => { - const interceptor = new LogInterceptor(); - const event = stubClientErrorEvent({ errno: 'not EPIPE' }); - expect(interceptor.downgradeIfEpipe(event)).toBe(null); - }); - - it('ignores if tags are wrong', () => { - const interceptor = new LogInterceptor(); - const event = stubEpipeEvent(); - event.tags = ['different', 'tags']; - expect(interceptor.downgradeIfEpipe(event)).toBe(null); - }); - }); - - describe('#downgradeIfEcanceled()', () => { - it('transforms ECANCELED events', () => { - const interceptor = new LogInterceptor(); - const event = stubEcanceledEvent(); - assertDowngraded(interceptor.downgradeIfEcanceled(event)!); - }); - - it('does not match if the tags are not in order', () => { - const interceptor = new LogInterceptor(); - const event = stubEcanceledEvent(); - event.tags = [...event.tags!.slice(1), event.tags![0]]; - expect(interceptor.downgradeIfEcanceled(event)).toBe(null); - }); - - it('ignores non ECANCELED events', () => { - const interceptor = new LogInterceptor(); - const event = stubClientErrorEvent({ errno: 'not ECANCELLED' }); - expect(interceptor.downgradeIfEcanceled(event)).toBe(null); - }); - - it('ignores if tags are wrong', () => { - const interceptor = new LogInterceptor(); - const event = stubEcanceledEvent(); - event.tags = ['different', 'tags']; - expect(interceptor.downgradeIfEcanceled(event)).toBe(null); - }); - }); - - describe('#downgradeIfHTTPSWhenHTTP', () => { - it('transforms https requests when serving http errors', () => { - const interceptor = new LogInterceptor(); - const event = stubClientErrorEvent({ message: 'Parse Error', code: 'HPE_INVALID_METHOD' }); - assertDowngraded(interceptor.downgradeIfHTTPSWhenHTTP(event)!); - }); - - it('ignores non events', () => { - const interceptor = new LogInterceptor(); - const event = stubClientErrorEvent({ - message: 'Parse Error', - code: 'NOT_HPE_INVALID_METHOD', - }); - expect(interceptor.downgradeIfEcanceled(event)).toBe(null); - }); - }); - - describe('#downgradeIfHTTPWhenHTTPS', () => { - it('transforms http requests when serving https errors', () => { - const message = - '4584650176:error:1408F09C:SSL routines:ssl3_get_record:http request:../deps/openssl/openssl/ssl/record/ssl3_record.c:322:\n'; - const interceptor = new LogInterceptor(); - const event = stubClientErrorEvent({ message }); - assertDowngraded(interceptor.downgradeIfHTTPWhenHTTPS(event)!); - }); - - it('ignores non events', () => { - const interceptor = new LogInterceptor(); - const event = stubClientErrorEvent({ message: 'Not error' }); - expect(interceptor.downgradeIfEcanceled(event)).toBe(null); - }); - }); -}); diff --git a/packages/kbn-legacy-logging/src/log_interceptor.ts b/packages/kbn-legacy-logging/src/log_interceptor.ts deleted file mode 100644 index 1085806135ca6..0000000000000 --- a/packages/kbn-legacy-logging/src/log_interceptor.ts +++ /dev/null @@ -1,144 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import Stream from 'stream'; -import { get, isEqual } from 'lodash'; -import { AnyEvent } from './log_events'; - -/** - * Matches error messages when clients connect via HTTP instead of HTTPS; see unit test for full message. Warning: this can change when Node - * and its bundled OpenSSL binary are upgraded. - */ -const OPENSSL_GET_RECORD_REGEX = /ssl3_get_record:http/; - -function doTagsMatch(event: AnyEvent, tags: string[]) { - return isEqual(event.tags, tags); -} - -function doesMessageMatch(errorMessage: string, match: RegExp | string) { - if (!errorMessage) { - return false; - } - if (match instanceof RegExp) { - return match.test(errorMessage); - } - return errorMessage === match; -} - -// converts the given event into a debug log if it's an error of the given type -function downgradeIfErrorType(errorType: string, event: AnyEvent) { - const isClientError = doTagsMatch(event, ['connection', 'client', 'error']); - if (!isClientError) { - return null; - } - - const matchesErrorType = - get(event, 'error.code') === errorType || get(event, 'error.errno') === errorType; - if (!matchesErrorType) { - return null; - } - - const errorTypeTag = errorType.toLowerCase(); - - return { - event: 'log', - pid: event.pid, - timestamp: event.timestamp, - tags: ['debug', 'connection', errorTypeTag], - data: `${errorType}: Socket was closed by the client (probably the browser) before it could be read completely`, - }; -} - -function downgradeIfErrorMessage(match: RegExp | string, event: AnyEvent) { - const isClientError = doTagsMatch(event, ['connection', 'client', 'error']); - const errorMessage = get(event, 'error.message'); - const matchesErrorMessage = isClientError && doesMessageMatch(errorMessage, match); - - if (!matchesErrorMessage) { - return null; - } - - return { - event: 'log', - pid: event.pid, - timestamp: event.timestamp, - tags: ['debug', 'connection'], - data: errorMessage, - }; -} - -export class LogInterceptor extends Stream.Transform { - constructor() { - super({ - readableObjectMode: true, - writableObjectMode: true, - }); - } - - /** - * Since the upgrade to hapi 14, any socket read - * error is surfaced as a generic "client error" - * but "ECONNRESET" specifically is not useful for the - * logs unless you are trying to debug edge-case behaviors. - * - * For that reason, we downgrade this from error to debug level - * - * @param {object} - log event - */ - downgradeIfEconnreset(event: AnyEvent) { - return downgradeIfErrorType('ECONNRESET', event); - } - - /** - * Since the upgrade to hapi 14, any socket write - * error is surfaced as a generic "client error" - * but "EPIPE" specifically is not useful for the - * logs unless you are trying to debug edge-case behaviors. - * - * For that reason, we downgrade this from error to debug level - * - * @param {object} - log event - */ - downgradeIfEpipe(event: AnyEvent) { - return downgradeIfErrorType('EPIPE', event); - } - - /** - * Since the upgrade to hapi 14, any socket write - * error is surfaced as a generic "client error" - * but "ECANCELED" specifically is not useful for the - * logs unless you are trying to debug edge-case behaviors. - * - * For that reason, we downgrade this from error to debug level - * - * @param {object} - log event - */ - downgradeIfEcanceled(event: AnyEvent) { - return downgradeIfErrorType('ECANCELED', event); - } - - downgradeIfHTTPSWhenHTTP(event: AnyEvent) { - return downgradeIfErrorType('HPE_INVALID_METHOD', event); - } - - downgradeIfHTTPWhenHTTPS(event: AnyEvent) { - return downgradeIfErrorMessage(OPENSSL_GET_RECORD_REGEX, event); - } - - _transform(event: AnyEvent, enc: string, next: Stream.TransformCallback) { - const downgraded = - this.downgradeIfEconnreset(event) || - this.downgradeIfEpipe(event) || - this.downgradeIfEcanceled(event) || - this.downgradeIfHTTPSWhenHTTP(event) || - this.downgradeIfHTTPWhenHTTPS(event); - - this.push(downgraded || event); - next(); - } -} diff --git a/packages/kbn-legacy-logging/src/log_reporter.test.ts b/packages/kbn-legacy-logging/src/log_reporter.test.ts deleted file mode 100644 index a2ad8984ba244..0000000000000 --- a/packages/kbn-legacy-logging/src/log_reporter.test.ts +++ /dev/null @@ -1,131 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import os from 'os'; -import path from 'path'; -import fs from 'fs'; - -import stripAnsi from 'strip-ansi'; - -import { getLogReporter } from './log_reporter'; - -const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); - -describe('getLogReporter', () => { - it('should log to stdout (not json)', async () => { - const lines: string[] = []; - const origWrite = process.stdout.write; - process.stdout.write = (buffer: string | Uint8Array): boolean => { - lines.push(stripAnsi(buffer.toString()).trim()); - return true; - }; - - const loggerStream = getLogReporter({ - config: { - json: false, - dest: 'stdout', - filter: {}, - }, - events: { log: '*' }, - }); - - loggerStream.end({ event: 'log', tags: ['foo'], data: 'hello world' }); - - await sleep(500); - - process.stdout.write = origWrite; - expect(lines.length).toBe(1); - expect(lines[0]).toMatch(/^log \[[^\]]*\] \[foo\] hello world$/); - }); - - it('should log to stdout (as json)', async () => { - const lines: string[] = []; - const origWrite = process.stdout.write; - process.stdout.write = (buffer: string | Uint8Array): boolean => { - lines.push(JSON.parse(buffer.toString().trim())); - return true; - }; - - const loggerStream = getLogReporter({ - config: { - json: true, - dest: 'stdout', - filter: {}, - }, - events: { log: '*' }, - }); - - loggerStream.end({ event: 'log', tags: ['foo'], data: 'hello world' }); - - await sleep(500); - - process.stdout.write = origWrite; - expect(lines.length).toBe(1); - expect(lines[0]).toMatchObject({ - type: 'log', - tags: ['foo'], - message: 'hello world', - }); - }); - - it('should log to custom file (not json)', async () => { - const dir = os.tmpdir(); - const logfile = `dest-${Date.now()}.log`; - const dest = path.join(dir, logfile); - - const loggerStream = getLogReporter({ - config: { - json: false, - dest, - filter: {}, - }, - events: { log: '*' }, - }); - - loggerStream.end({ event: 'log', tags: ['foo'], data: 'hello world' }); - - await sleep(500); - - const lines = stripAnsi(fs.readFileSync(dest, { encoding: 'utf8' })) - .trim() - .split(os.EOL); - expect(lines.length).toBe(1); - expect(lines[0]).toMatch(/^log \[[^\]]*\] \[foo\] hello world$/); - }); - - it('should log to custom file (as json)', async () => { - const dir = os.tmpdir(); - const logfile = `dest-${Date.now()}.log`; - const dest = path.join(dir, logfile); - - const loggerStream = getLogReporter({ - config: { - json: true, - dest, - filter: {}, - }, - events: { log: '*' }, - }); - - loggerStream.end({ event: 'log', tags: ['foo'], data: 'hello world' }); - - await sleep(500); - - const lines = fs - .readFileSync(dest, { encoding: 'utf8' }) - .trim() - .split(os.EOL) - .map((data) => JSON.parse(data)); - expect(lines.length).toBe(1); - expect(lines[0]).toMatchObject({ - type: 'log', - tags: ['foo'], - message: 'hello world', - }); - }); -}); diff --git a/packages/kbn-legacy-logging/src/log_reporter.ts b/packages/kbn-legacy-logging/src/log_reporter.ts deleted file mode 100644 index d42fb78f1647b..0000000000000 --- a/packages/kbn-legacy-logging/src/log_reporter.ts +++ /dev/null @@ -1,49 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { createWriteStream } from 'fs'; -import { pipeline } from 'stream'; - -// @ts-expect-error missing type def -import { Squeeze } from '@hapi/good-squeeze'; - -import { KbnLoggerJsonFormat } from './log_format_json'; -import { KbnLoggerStringFormat } from './log_format_string'; -import { LogInterceptor } from './log_interceptor'; -import { LogFormatConfig } from './log_format'; - -export function getLogReporter({ events, config }: { events: any; config: LogFormatConfig }) { - const squeeze = new Squeeze(events); - const format = config.json ? new KbnLoggerJsonFormat(config) : new KbnLoggerStringFormat(config); - const logInterceptor = new LogInterceptor(); - - if (config.dest === 'stdout') { - pipeline(logInterceptor, squeeze, format, onFinished); - // The `pipeline` function is used to properly close all streams in the - // pipeline in case one of them ends or fails. Since stdout obviously - // shouldn't be closed in case of a failure in one of the other streams, - // we're not including that in the call to `pipeline`, but rely on the old - // `pipe` function instead. - format.pipe(process.stdout); - } else { - const dest = createWriteStream(config.dest, { - flags: 'a', - encoding: 'utf8', - }); - pipeline(logInterceptor, squeeze, format, dest, onFinished); - } - - return logInterceptor; -} - -function onFinished(err: NodeJS.ErrnoException | null) { - if (err) { - // eslint-disable-next-line no-console - console.error('An unexpected error occurred in the logging pipeline:', err.stack); - } -} diff --git a/packages/kbn-legacy-logging/src/metadata.ts b/packages/kbn-legacy-logging/src/metadata.ts deleted file mode 100644 index 0f41673ef6723..0000000000000 --- a/packages/kbn-legacy-logging/src/metadata.ts +++ /dev/null @@ -1,42 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { isPlainObject } from 'lodash'; - -export const metadataSymbol = Symbol('log message with metadata'); - -export interface EventData { - [metadataSymbol]?: EventMetadata; - [key: string]: any; -} - -export interface EventMetadata { - message: string; - metadata: Record; -} - -export const isEventData = (eventData: EventData) => { - return Boolean(isPlainObject(eventData) && eventData[metadataSymbol]); -}; - -export const getLogEventData = (eventData: EventData) => { - const { message, metadata } = eventData[metadataSymbol]!; - return { - ...metadata, - message, - }; -}; - -export const attachMetaData = (message: string, metadata: Record = {}) => { - return { - [metadataSymbol]: { - message, - metadata, - }, - }; -}; diff --git a/packages/kbn-legacy-logging/src/rotate/index.ts b/packages/kbn-legacy-logging/src/rotate/index.ts deleted file mode 100644 index 39305dcccf788..0000000000000 --- a/packages/kbn-legacy-logging/src/rotate/index.ts +++ /dev/null @@ -1,41 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { Server } from '@hapi/hapi'; -import { LogRotator } from './log_rotator'; -import { LegacyLoggingConfig } from '../schema'; - -let logRotator: LogRotator; - -export async function setupLoggingRotate(server: Server, config: LegacyLoggingConfig) { - // If log rotate is not enabled we skip - if (!config.rotate.enabled) { - return; - } - - // We don't want to run logging rotate server if - // we are not logging to a file - if (config.dest === 'stdout') { - server.log( - ['warning', 'logging:rotate'], - 'Log rotation is enabled but logging.dest is configured for stdout. Set logging.dest to a file for this setting to take effect.' - ); - return; - } - - // Enable Logging Rotate Service - // We need the master process and it can - // try to setupLoggingRotate more than once, - // so we'll need to assure it only loads once. - if (!logRotator) { - logRotator = new LogRotator(config, server); - await logRotator.start(); - } - - return logRotator; -} diff --git a/packages/kbn-legacy-logging/src/rotate/log_rotator.test.ts b/packages/kbn-legacy-logging/src/rotate/log_rotator.test.ts deleted file mode 100644 index ce9a24e63455f..0000000000000 --- a/packages/kbn-legacy-logging/src/rotate/log_rotator.test.ts +++ /dev/null @@ -1,261 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import del from 'del'; -import fs, { existsSync, mkdirSync, statSync, writeFileSync } from 'fs'; -import { tmpdir } from 'os'; -import { dirname, join } from 'path'; -import { LogRotator } from './log_rotator'; -import { LegacyLoggingConfig } from '../schema'; - -const mockOn = jest.fn(); -jest.mock('chokidar', () => ({ - watch: jest.fn(() => ({ - on: mockOn, - close: jest.fn(), - })), -})); - -jest.mock('lodash', () => ({ - ...(jest.requireActual('lodash') as any), - throttle: (fn: any) => fn, -})); - -const tempDir = join(tmpdir(), 'kbn_log_rotator_test'); -const testFilePath = join(tempDir, 'log_rotator_test_log_file.log'); - -const createLogRotatorConfig = (logFilePath: string): LegacyLoggingConfig => { - return { - dest: logFilePath, - rotate: { - enabled: true, - keepFiles: 2, - everyBytes: 2, - usePolling: false, - pollingInterval: 10000, - pollingPolicyTestTimeout: 4000, - }, - } as LegacyLoggingConfig; -}; - -const mockServer: any = { - log: jest.fn(), -}; - -const writeBytesToFile = (filePath: string, numberOfBytes: number) => { - writeFileSync(filePath, 'a'.repeat(numberOfBytes), { flag: 'a' }); -}; - -describe('LogRotator', () => { - beforeEach(() => { - mkdirSync(tempDir, { recursive: true }); - writeFileSync(testFilePath, ''); - }); - - afterEach(() => { - del.sync(tempDir, { force: true }); - mockOn.mockClear(); - }); - - it('rotates log file when bigger than set limit on start', async () => { - writeBytesToFile(testFilePath, 3); - - const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer); - jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {}); - - await logRotator.start(); - - expect(logRotator.running).toBe(true); - - await logRotator.stop(); - - expect(existsSync(join(tempDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy(); - }); - - it('rotates log file when equal than set limit over time', async () => { - writeBytesToFile(testFilePath, 1); - - const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer); - jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {}); - await logRotator.start(); - - expect(logRotator.running).toBe(true); - - const testLogFileDir = dirname(testFilePath); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeFalsy(); - - writeBytesToFile(testFilePath, 1); - - // ['change', [asyncFunction]] - const onChangeCb = mockOn.mock.calls[0][1]; - await onChangeCb(testLogFileDir, { size: 2 }); - - await logRotator.stop(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy(); - }); - - it('rotates log file when file size is bigger than limit', async () => { - writeBytesToFile(testFilePath, 1); - - const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer); - jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {}); - await logRotator.start(); - - expect(logRotator.running).toBe(true); - - const testLogFileDir = dirname(testFilePath); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeFalsy(); - - writeBytesToFile(testFilePath, 2); - - // ['change', [asyncFunction]] - const onChangeCb = mockOn.mock.calls[0][1]; - await onChangeCb(testLogFileDir, { size: 3 }); - - await logRotator.stop(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy(); - }); - - it('rotates log file service correctly keeps number of files', async () => { - writeBytesToFile(testFilePath, 3); - - const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer); - jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {}); - await logRotator.start(); - - expect(logRotator.running).toBe(true); - - const testLogFileDir = dirname(testFilePath); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy(); - - writeBytesToFile(testFilePath, 2); - - // ['change', [asyncFunction]] - const onChangeCb = mockOn.mock.calls[0][1]; - await onChangeCb(testLogFileDir, { size: 2 }); - - writeBytesToFile(testFilePath, 5); - await onChangeCb(testLogFileDir, { size: 5 }); - - await logRotator.stop(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.1'))).toBeTruthy(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.2'))).toBeFalsy(); - expect(statSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0')).size).toBe(5); - }); - - it('rotates log file service correctly keeps number of files even when number setting changes', async () => { - writeBytesToFile(testFilePath, 3); - - const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer); - jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {}); - await logRotator.start(); - - expect(logRotator.running).toBe(true); - - const testLogFileDir = dirname(testFilePath); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy(); - - writeBytesToFile(testFilePath, 2); - - // ['change', [asyncFunction]] - const onChangeCb = mockOn.mock.calls[0][1]; - await onChangeCb(testLogFileDir, { size: 2 }); - - writeBytesToFile(testFilePath, 5); - await onChangeCb(testLogFileDir, { size: 5 }); - - await logRotator.stop(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.1'))).toBeTruthy(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.2'))).toBeFalsy(); - expect(statSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0')).size).toBe(5); - - logRotator.keepFiles = 1; - await logRotator.start(); - - writeBytesToFile(testFilePath, 5); - await onChangeCb(testLogFileDir, { size: 5 }); - - await logRotator.stop(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0'))).toBeTruthy(); - expect(existsSync(join(testLogFileDir, 'log_rotator_test_log_file.log.1'))).toBeFalsy(); - expect(statSync(join(testLogFileDir, 'log_rotator_test_log_file.log.0')).size).toBe(5); - }); - - it('rotates log file service correctly detects usePolling when it should be false', async () => { - writeBytesToFile(testFilePath, 1); - - const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer); - jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {}); - await logRotator.start(); - - expect(logRotator.running).toBe(true); - expect(logRotator.usePolling).toBe(false); - - const shouldUsePolling = await logRotator._shouldUsePolling(); - expect(shouldUsePolling).toBe(false); - - await logRotator.stop(); - }); - - it('rotates log file service correctly detects usePolling when it should be true', async () => { - writeBytesToFile(testFilePath, 1); - - const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer); - jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {}); - - jest.spyOn(fs, 'watch').mockImplementation( - () => - ({ - on: jest.fn((eventType, cb) => { - if (eventType === 'error') { - cb(); - } - }), - close: jest.fn(), - } as any) - ); - - await logRotator.start(); - - expect(logRotator.running).toBe(true); - expect(logRotator.usePolling).toBe(false); - expect(logRotator.shouldUsePolling).toBe(true); - - await logRotator.stop(); - }); - - it('rotates log file service correctly fallback to usePolling true after defined timeout', async () => { - jest.useFakeTimers(); - writeBytesToFile(testFilePath, 1); - - const logRotator = new LogRotator(createLogRotatorConfig(testFilePath), mockServer); - jest.spyOn(logRotator, '_sendReloadLogConfigSignal').mockImplementation(() => {}); - jest.spyOn(fs, 'watch').mockImplementation( - () => - ({ - on: jest.fn((ev: string) => { - if (ev === 'error') { - jest.runTimersToTime(15000); - } - }), - close: jest.fn(), - } as any) - ); - - await logRotator.start(); - - expect(logRotator.running).toBe(true); - expect(logRotator.usePolling).toBe(false); - expect(logRotator.shouldUsePolling).toBe(true); - - await logRotator.stop(); - jest.useRealTimers(); - }); -}); diff --git a/packages/kbn-legacy-logging/src/rotate/log_rotator.ts b/packages/kbn-legacy-logging/src/rotate/log_rotator.ts deleted file mode 100644 index 4b1e34839030f..0000000000000 --- a/packages/kbn-legacy-logging/src/rotate/log_rotator.ts +++ /dev/null @@ -1,352 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import * as chokidar from 'chokidar'; -import fs from 'fs'; -import { Server } from '@hapi/hapi'; -import { throttle } from 'lodash'; -import { tmpdir } from 'os'; -import { basename, dirname, join, sep } from 'path'; -import { Observable } from 'rxjs'; -import { first } from 'rxjs/operators'; -import { promisify } from 'util'; -import { LegacyLoggingConfig } from '../schema'; - -const mkdirAsync = promisify(fs.mkdir); -const readdirAsync = promisify(fs.readdir); -const renameAsync = promisify(fs.rename); -const statAsync = promisify(fs.stat); -const unlinkAsync = promisify(fs.unlink); -const writeFileAsync = promisify(fs.writeFile); - -export class LogRotator { - private readonly config: LegacyLoggingConfig; - private readonly log: Server['log']; - public logFilePath: string; - public everyBytes: number; - public keepFiles: number; - public running: boolean; - private logFileSize: number; - public isRotating: boolean; - public throttledRotate: () => void; - public stalker: chokidar.FSWatcher | null; - public usePolling: boolean; - public pollingInterval: number; - private stalkerUsePollingPolicyTestTimeout: NodeJS.Timeout | null; - public shouldUsePolling: boolean; - - constructor(config: LegacyLoggingConfig, server: Server) { - this.config = config; - this.log = server.log.bind(server); - this.logFilePath = config.dest; - this.everyBytes = config.rotate.everyBytes; - this.keepFiles = config.rotate.keepFiles; - this.running = false; - this.logFileSize = 0; - this.isRotating = false; - this.throttledRotate = throttle(async () => await this._rotate(), 5000); - this.stalker = null; - this.usePolling = config.rotate.usePolling; - this.pollingInterval = config.rotate.pollingInterval; - this.shouldUsePolling = false; - this.stalkerUsePollingPolicyTestTimeout = null; - } - - async start() { - if (this.running) { - return; - } - - this.running = true; - - // create exit listener for cleanup purposes - this._createExitListener(); - - // call rotate on startup - await this._callRotateOnStartup(); - - // init log file size monitor - await this._startLogFileSizeMonitor(); - } - - stop = () => { - if (!this.running) { - return; - } - - // cleanup exit listener - this._deleteExitListener(); - - // stop log file size monitor - this._stopLogFileSizeMonitor(); - - this.running = false; - }; - - async _shouldUsePolling() { - try { - // Setup a test file in order to try the fs env - // and understand if we need to usePolling or not - const tempFileDir = tmpdir(); - const tempFile = join(tempFileDir, 'kbn_log_rotation_use_polling_test_file.log'); - - await mkdirAsync(tempFileDir, { recursive: true }); - await writeFileAsync(tempFile, ''); - - // setup fs.watch for the temp test file - const testWatcher = fs.watch(tempFile, { persistent: false }); - - // await writeFileAsync(tempFile, 'test'); - - const usePollingTest$ = new Observable((observer) => { - // observable complete function - const completeFn = (completeStatus: boolean) => { - if (this.stalkerUsePollingPolicyTestTimeout) { - clearTimeout(this.stalkerUsePollingPolicyTestTimeout); - } - testWatcher.close(); - - observer.next(completeStatus); - observer.complete(); - }; - - // setup conditions that would fire the observable - this.stalkerUsePollingPolicyTestTimeout = setTimeout( - () => completeFn(true), - this.config.rotate.pollingPolicyTestTimeout || 15000 - ); - testWatcher.on('change', () => completeFn(false)); - testWatcher.on('error', () => completeFn(true)); - - // fire test watcher events - setTimeout(() => { - fs.writeFileSync(tempFile, 'test'); - }, 0); - }); - - // wait for the first observable result and consider it as the result - // for our use polling test - const usePollingTestResult = await usePollingTest$.pipe(first()).toPromise(); - - // delete the temp file used for the test - await unlinkAsync(tempFile); - - return usePollingTestResult; - } catch { - return true; - } - } - - async _startLogFileSizeMonitor() { - this.usePolling = this.config.rotate.usePolling; - this.shouldUsePolling = await this._shouldUsePolling(); - - if (this.usePolling && !this.shouldUsePolling) { - this.log( - ['warning', 'logging:rotate'], - 'Looks like your current environment support a faster algorithm than polling. You can try to disable `usePolling`' - ); - } - - if (!this.usePolling && this.shouldUsePolling) { - this.log( - ['error', 'logging:rotate'], - 'Looks like within your current environment you need to use polling in order to enable log rotator. Please enable `usePolling`' - ); - } - - this.stalker = chokidar.watch(this.logFilePath, { - ignoreInitial: true, - awaitWriteFinish: false, - useFsEvents: false, - usePolling: this.usePolling, - interval: this.pollingInterval, - binaryInterval: this.pollingInterval, - alwaysStat: true, - atomic: false, - }); - this.stalker.on('change', this._logFileSizeMonitorHandler); - } - - _logFileSizeMonitorHandler = async (filename: string, stats: fs.Stats) => { - if (!filename || !stats) { - return; - } - - this.logFileSize = stats.size || 0; - await this.throttledRotate(); - }; - - _stopLogFileSizeMonitor() { - if (!this.stalker) { - return; - } - - this.stalker.close(); - - if (this.stalkerUsePollingPolicyTestTimeout) { - clearTimeout(this.stalkerUsePollingPolicyTestTimeout); - } - } - - _createExitListener() { - process.on('exit', this.stop); - } - - _deleteExitListener() { - process.removeListener('exit', this.stop); - } - - async _getLogFileSizeAndCreateIfNeeded() { - try { - const logFileStats = await statAsync(this.logFilePath); - return logFileStats.size; - } catch { - // touch the file to make the watcher being able to register - // change events - await writeFileAsync(this.logFilePath, ''); - return 0; - } - } - - async _callRotateOnStartup() { - this.logFileSize = await this._getLogFileSizeAndCreateIfNeeded(); - await this._rotate(); - } - - _shouldRotate() { - // should rotate evaluation - // 1. should rotate if current log size exceeds - // the defined one on everyBytes - // 2. should not rotate if is already rotating or if any - // of the conditions on 1. do not apply - if (this.isRotating) { - return false; - } - - return this.logFileSize >= this.everyBytes; - } - - async _rotate() { - if (!this._shouldRotate()) { - return; - } - - await this._rotateNow(); - } - - async _rotateNow() { - // rotate process - // 1. get rotated files metadata (list of log rotated files present on the log folder, numerical sorted) - // 2. delete last file - // 3. rename all files to the correct index +1 - // 4. rename + compress current log into 1 - // 5. send SIGHUP to reload log config - - // rotate process is starting - this.isRotating = true; - - // get rotated files metadata - const foundRotatedFiles = await this._readRotatedFilesMetadata(); - - // delete number of rotated files exceeding the keepFiles limit setting - const rotatedFiles: string[] = await this._deleteFoundRotatedFilesAboveKeepFilesLimit( - foundRotatedFiles - ); - - // delete last file - await this._deleteLastRotatedFile(rotatedFiles); - - // rename all files to correct index + 1 - // and normalize numbering if by some reason - // (for example log file deletion) that numbering - // was interrupted - await this._renameRotatedFilesByOne(rotatedFiles); - - // rename current log into 0 - await this._rotateCurrentLogFile(); - - // send SIGHUP to reload log configuration - this._sendReloadLogConfigSignal(); - - // Reset log file size - this.logFileSize = 0; - - // rotate process is finished - this.isRotating = false; - } - - async _readRotatedFilesMetadata() { - const logFileBaseName = basename(this.logFilePath); - const logFilesFolder = dirname(this.logFilePath); - const foundLogFiles: string[] = await readdirAsync(logFilesFolder); - - return ( - foundLogFiles - .filter((file) => new RegExp(`${logFileBaseName}\\.\\d`).test(file)) - // we use .slice(-1) here in order to retrieve the last number match in the read filenames - .sort((a, b) => Number(a.match(/(\d+)/g)!.slice(-1)) - Number(b.match(/(\d+)/g)!.slice(-1))) - .map((filename) => `${logFilesFolder}${sep}${filename}`) - ); - } - - async _deleteFoundRotatedFilesAboveKeepFilesLimit(foundRotatedFiles: string[]) { - if (foundRotatedFiles.length <= this.keepFiles) { - return foundRotatedFiles; - } - - const finalRotatedFiles = foundRotatedFiles.slice(0, this.keepFiles); - const rotatedFilesToDelete = foundRotatedFiles.slice( - finalRotatedFiles.length, - foundRotatedFiles.length - ); - - await Promise.all( - rotatedFilesToDelete.map((rotatedFilePath: string) => unlinkAsync(rotatedFilePath)) - ); - - return finalRotatedFiles; - } - - async _deleteLastRotatedFile(rotatedFiles: string[]) { - if (rotatedFiles.length < this.keepFiles) { - return; - } - - const lastFilePath: string = rotatedFiles.pop() as string; - await unlinkAsync(lastFilePath); - } - - async _renameRotatedFilesByOne(rotatedFiles: string[]) { - const logFileBaseName = basename(this.logFilePath); - const logFilesFolder = dirname(this.logFilePath); - - for (let i = rotatedFiles.length - 1; i >= 0; i--) { - const oldFilePath = rotatedFiles[i]; - const newFilePath = `${logFilesFolder}${sep}${logFileBaseName}.${i + 1}`; - await renameAsync(oldFilePath, newFilePath); - } - } - - async _rotateCurrentLogFile() { - const newFilePath = `${this.logFilePath}.0`; - await renameAsync(this.logFilePath, newFilePath); - } - - _sendReloadLogConfigSignal() { - if (!process.env.isDevCliChild || !process.send) { - process.emit('SIGHUP', 'SIGHUP'); - return; - } - - // Send a special message to the cluster manager - // so it can forward it correctly - // It will only run when we are under cluster mode (not under a production environment) - process.send(['RELOAD_LOGGING_CONFIG_FROM_SERVER_WORKER']); - } -} diff --git a/packages/kbn-legacy-logging/src/schema.ts b/packages/kbn-legacy-logging/src/schema.ts deleted file mode 100644 index 0330708e746c0..0000000000000 --- a/packages/kbn-legacy-logging/src/schema.ts +++ /dev/null @@ -1,97 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { schema } from '@kbn/config-schema'; - -/** - * @deprecated - * - * Legacy logging has been deprecated and will be removed in 8.0. - * Set up logging from the platform logging instead - */ -export interface LegacyLoggingConfig { - silent: boolean; - quiet: boolean; - verbose: boolean; - events: Record; - dest: string; - filter: Record; - json: boolean; - timezone?: string; - rotate: { - enabled: boolean; - everyBytes: number; - keepFiles: number; - pollingInterval: number; - usePolling: boolean; - pollingPolicyTestTimeout?: number; - }; -} - -export const legacyLoggingConfigSchema = schema.object({ - silent: schema.boolean({ defaultValue: false }), - quiet: schema.conditional( - schema.siblingRef('silent'), - true, - schema.boolean({ - defaultValue: true, - validate: (quiet) => { - if (!quiet) { - return 'must be true when `silent` is true'; - } - }, - }), - schema.boolean({ defaultValue: false }) - ), - verbose: schema.conditional( - schema.siblingRef('quiet'), - true, - schema.boolean({ - defaultValue: false, - validate: (verbose) => { - if (verbose) { - return 'must be false when `quiet` is true'; - } - }, - }), - schema.boolean({ defaultValue: false }) - ), - events: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - dest: schema.string({ defaultValue: 'stdout' }), - filter: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - json: schema.conditional( - schema.siblingRef('dest'), - 'stdout', - schema.boolean({ - defaultValue: !process.stdout.isTTY, - }), - schema.boolean({ - defaultValue: true, - }) - ), - timezone: schema.maybe(schema.string()), - rotate: schema.object({ - enabled: schema.boolean({ defaultValue: false }), - everyBytes: schema.number({ - min: 1048576, // > 1MB - max: 1073741825, // < 1GB - defaultValue: 10485760, // 10MB - }), - keepFiles: schema.number({ - min: 2, - max: 1024, - defaultValue: 7, - }), - pollingInterval: schema.number({ - min: 5000, - max: 3600000, - defaultValue: 10000, - }), - usePolling: schema.boolean({ defaultValue: false }), - }), -}); diff --git a/packages/kbn-legacy-logging/src/setup_logging.test.ts b/packages/kbn-legacy-logging/src/setup_logging.test.ts deleted file mode 100644 index 8e1d76477f64a..0000000000000 --- a/packages/kbn-legacy-logging/src/setup_logging.test.ts +++ /dev/null @@ -1,35 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { Server } from '@hapi/hapi'; -import { reconfigureLogging, setupLogging } from './setup_logging'; -import { LegacyLoggingConfig } from './schema'; - -describe('reconfigureLogging', () => { - test(`doesn't throw an error`, () => { - const server = new Server(); - const config: LegacyLoggingConfig = { - silent: false, - quiet: false, - verbose: true, - events: {}, - dest: '/tmp/foo', - filter: {}, - json: true, - rotate: { - enabled: false, - everyBytes: 0, - keepFiles: 0, - pollingInterval: 0, - usePolling: false, - }, - }; - setupLogging(server, config, 10); - reconfigureLogging(server, { ...config, dest: '/tmp/bar' }, 0); - }); -}); diff --git a/packages/kbn-legacy-logging/src/setup_logging.ts b/packages/kbn-legacy-logging/src/setup_logging.ts deleted file mode 100644 index a045469e81251..0000000000000 --- a/packages/kbn-legacy-logging/src/setup_logging.ts +++ /dev/null @@ -1,41 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -// @ts-expect-error missing typedef -import { plugin as good } from '@elastic/good'; -import { Server } from '@hapi/hapi'; -import { LegacyLoggingConfig } from './schema'; -import { getLoggingConfiguration } from './get_logging_config'; - -export async function setupLogging( - server: Server, - config: LegacyLoggingConfig, - opsInterval: number -) { - // NOTE: legacy logger creates a new stream for each new access - // In https://github.com/elastic/kibana/pull/55937 we reach the max listeners - // default limit of 10 for process.stdout which starts a long warning/error - // thrown every time we start the server. - // In order to keep using the legacy logger until we remove it I'm just adding - // a new hard limit here. - process.stdout.setMaxListeners(60); - - return await server.register({ - plugin: good, - options: getLoggingConfiguration(config, opsInterval), - }); -} - -export function reconfigureLogging( - server: Server, - config: LegacyLoggingConfig, - opsInterval: number -) { - const loggingOptions = getLoggingConfiguration(config, opsInterval); - (server.plugins as any).good.reconfigure(loggingOptions); -} diff --git a/packages/kbn-legacy-logging/src/utils/apply_filters_to_keys.test.ts b/packages/kbn-legacy-logging/src/utils/apply_filters_to_keys.test.ts deleted file mode 100644 index b662c88eba7b7..0000000000000 --- a/packages/kbn-legacy-logging/src/utils/apply_filters_to_keys.test.ts +++ /dev/null @@ -1,49 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { applyFiltersToKeys } from './apply_filters_to_keys'; - -describe('applyFiltersToKeys(obj, actionsByKey)', function () { - it('applies for each key+prop in actionsByKey', function () { - const data = applyFiltersToKeys( - { - a: { - b: { - c: 1, - }, - d: { - e: 'foobar', - }, - }, - req: { - headers: { - authorization: 'Basic dskd939k2i', - }, - }, - }, - { - b: 'remove', - e: 'censor', - authorization: '/([^\\s]+)$/', - } - ); - - expect(data).toEqual({ - a: { - d: { - e: 'XXXXXX', - }, - }, - req: { - headers: { - authorization: 'Basic XXXXXXXXXX', - }, - }, - }); - }); -}); diff --git a/packages/kbn-legacy-logging/src/utils/apply_filters_to_keys.ts b/packages/kbn-legacy-logging/src/utils/apply_filters_to_keys.ts deleted file mode 100644 index 578fa3a835129..0000000000000 --- a/packages/kbn-legacy-logging/src/utils/apply_filters_to_keys.ts +++ /dev/null @@ -1,50 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -function toPojo(obj: Record) { - return JSON.parse(JSON.stringify(obj)); -} - -function replacer(match: string, group: any[]) { - return new Array(group.length + 1).join('X'); -} - -function apply(obj: Record, key: string, action: string) { - for (const k in obj) { - if (obj.hasOwnProperty(k)) { - let val = obj[k]; - if (k === key) { - if (action === 'remove') { - delete obj[k]; - } else if (action === 'censor' && typeof val === 'object') { - delete obj[key]; - } else if (action === 'censor') { - obj[k] = ('' + val).replace(/./g, 'X'); - } else if (/\/.+\//.test(action)) { - const matches = action.match(/\/(.+)\//); - if (matches) { - const regex = new RegExp(matches[1]); - obj[k] = ('' + val).replace(regex, replacer); - } - } - } else if (typeof val === 'object') { - val = apply(val as Record, key, action); - } - } - } - return obj; -} - -export function applyFiltersToKeys( - obj: Record, - actionsByKey: Record -) { - return Object.keys(actionsByKey).reduce((output, key) => { - return apply(output, key, actionsByKey[key]); - }, toPojo(obj)); -} diff --git a/packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts b/packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts deleted file mode 100644 index 01d2cf29758db..0000000000000 --- a/packages/kbn-legacy-logging/src/utils/get_payload_size.test.ts +++ /dev/null @@ -1,158 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import mockFs from 'mock-fs'; -import { createReadStream } from 'fs'; -import { PassThrough } from 'stream'; -import { createGzip, createGunzip } from 'zlib'; - -import { getResponsePayloadBytes } from './get_payload_size'; - -describe('getPayloadSize', () => { - describe('handles Buffers', () => { - test('with ascii characters', () => { - const payload = 'heya'; - const result = getResponsePayloadBytes(Buffer.from(payload)); - expect(result).toBe(4); - }); - - test('with special characters', () => { - const payload = '¡hola!'; - const result = getResponsePayloadBytes(Buffer.from(payload)); - expect(result).toBe(7); - }); - }); - - describe('handles streams', () => { - afterEach(() => mockFs.restore()); - - test('ignores streams that are not fs or zlib streams', async () => { - const result = getResponsePayloadBytes(new PassThrough()); - expect(result).toBe(undefined); - }); - - describe('fs streams', () => { - test('with ascii characters', async () => { - mockFs({ 'test.txt': 'heya' }); - const readStream = createReadStream('test.txt'); - - let data = ''; - for await (const chunk of readStream) { - data += chunk; - } - - const result = getResponsePayloadBytes(readStream); - expect(result).toBe(Buffer.byteLength(data)); - }); - - test('with special characters', async () => { - mockFs({ 'test.txt': '¡hola!' }); - const readStream = createReadStream('test.txt'); - - let data = ''; - for await (const chunk of readStream) { - data += chunk; - } - - const result = getResponsePayloadBytes(readStream); - expect(result).toBe(Buffer.byteLength(data)); - }); - - describe('zlib streams', () => { - test('with ascii characters', async () => { - mockFs({ 'test.txt': 'heya' }); - const readStream = createReadStream('test.txt'); - const source = readStream.pipe(createGzip()).pipe(createGunzip()); - - let data = ''; - for await (const chunk of source) { - data += chunk; - } - - const result = getResponsePayloadBytes(source); - - expect(data).toBe('heya'); - expect(result).toBe(source.bytesWritten); - }); - - test('with special characters', async () => { - mockFs({ 'test.txt': '¡hola!' }); - const readStream = createReadStream('test.txt'); - const source = readStream.pipe(createGzip()).pipe(createGunzip()); - - let data = ''; - for await (const chunk of source) { - data += chunk; - } - - const result = getResponsePayloadBytes(source); - - expect(data).toBe('¡hola!'); - expect(result).toBe(source.bytesWritten); - }); - }); - }); - }); - - describe('handles plain responses', () => { - test('when source is text', () => { - const result = getResponsePayloadBytes('heya'); - expect(result).toBe(4); - }); - - test('when source contains special characters', () => { - const result = getResponsePayloadBytes('¡hola!'); - expect(result).toBe(7); - }); - - test('when source is object', () => { - const payload = { message: 'heya' }; - const result = getResponsePayloadBytes(payload); - expect(result).toBe(JSON.stringify(payload).length); - }); - - test('when source is array object', () => { - const payload = [{ message: 'hey' }, { message: 'ya' }]; - const result = getResponsePayloadBytes(payload); - expect(result).toBe(JSON.stringify(payload).length); - }); - - test('returns undefined when source is not plain object', () => { - class TestClass { - constructor() {} - } - const result = getResponsePayloadBytes(new TestClass()); - expect(result).toBe(undefined); - }); - }); - - describe('handles content-length header', () => { - test('always provides content-length header if available', () => { - const headers = { 'content-length': '123' }; - const result = getResponsePayloadBytes('heya', headers); - expect(result).toBe(123); - }); - - test('uses first value when hapi header is an array', () => { - const headers = { 'content-length': ['123', '456'] }; - const result = getResponsePayloadBytes(null, headers); - expect(result).toBe(123); - }); - - test('returns undefined if length is NaN', () => { - const headers = { 'content-length': 'oops' }; - const result = getResponsePayloadBytes(null, headers); - expect(result).toBeUndefined(); - }); - }); - - test('defaults to undefined', () => { - const result = getResponsePayloadBytes(null); - expect(result).toBeUndefined(); - }); -}); diff --git a/packages/kbn-legacy-logging/src/utils/get_payload_size.ts b/packages/kbn-legacy-logging/src/utils/get_payload_size.ts deleted file mode 100644 index acc517c74c2d4..0000000000000 --- a/packages/kbn-legacy-logging/src/utils/get_payload_size.ts +++ /dev/null @@ -1,71 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { isPlainObject } from 'lodash'; -import { ReadStream } from 'fs'; -import { Zlib } from 'zlib'; -import type { ResponseObject } from '@hapi/hapi'; - -const isBuffer = (obj: unknown): obj is Buffer => Buffer.isBuffer(obj); -const isFsReadStream = (obj: unknown): obj is ReadStream => - typeof obj === 'object' && obj !== null && 'bytesRead' in obj && obj instanceof ReadStream; -const isZlibStream = (obj: unknown): obj is Zlib => { - return typeof obj === 'object' && obj !== null && 'bytesWritten' in obj; -}; -const isString = (obj: unknown): obj is string => typeof obj === 'string'; - -/** - * Attempts to determine the size (in bytes) of a hapi/good - * responsePayload based on the payload type. Falls back to - * `undefined` if the size cannot be determined. - * - * This is similar to the implementation in `core/server/http/logging`, - * however it uses more duck typing as we do not have access to the - * entire hapi request object like we do in the HttpServer. - * - * @param headers responseHeaders from hapi/good event - * @param payload responsePayload from hapi/good event - * - * @internal - */ -export function getResponsePayloadBytes( - payload: ResponseObject['source'], - headers: Record = {} -): number | undefined { - const contentLength = headers['content-length']; - if (contentLength) { - const val = parseInt( - // hapi response headers can be `string | string[]`, so we need to handle both cases - Array.isArray(contentLength) ? String(contentLength) : contentLength, - 10 - ); - return !isNaN(val) ? val : undefined; - } - - if (isBuffer(payload)) { - return payload.byteLength; - } - - if (isFsReadStream(payload)) { - return payload.bytesRead; - } - - if (isZlibStream(payload)) { - return payload.bytesWritten; - } - - if (isString(payload)) { - return Buffer.byteLength(payload); - } - - if (isPlainObject(payload) || Array.isArray(payload)) { - return Buffer.byteLength(JSON.stringify(payload)); - } - - return undefined; -} diff --git a/packages/kbn-legacy-logging/src/utils/index.ts b/packages/kbn-legacy-logging/src/utils/index.ts deleted file mode 100644 index 3036671121fe0..0000000000000 --- a/packages/kbn-legacy-logging/src/utils/index.ts +++ /dev/null @@ -1,10 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { applyFiltersToKeys } from './apply_filters_to_keys'; -export { getResponsePayloadBytes } from './get_payload_size'; diff --git a/packages/kbn-legacy-logging/tsconfig.json b/packages/kbn-legacy-logging/tsconfig.json deleted file mode 100644 index 55047dbcadc91..0000000000000 --- a/packages/kbn-legacy-logging/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../../tsconfig.bazel.json", - "compilerOptions": { - "declaration": true, - "declarationMap": true, - "emitDeclarationOnly": true, - "outDir": "target_types", - "rootDir": "src", - "sourceMap": true, - "sourceRoot": "../../../../packages/kbn-legacy-logging/src", - "stripInternal": false, - "types": ["jest", "node"] - }, - "include": ["src/**/*"] -} diff --git a/src/cli/serve/integration_tests/__fixtures__/invalid_config.yml b/src/cli/serve/integration_tests/__fixtures__/invalid_config.yml index df9ea641cd3fe..d8e59ced89c80 100644 --- a/src/cli/serve/integration_tests/__fixtures__/invalid_config.yml +++ b/src/cli/serve/integration_tests/__fixtures__/invalid_config.yml @@ -1,3 +1,13 @@ +logging: + root: + level: fatal + appenders: [console-json] + appenders: + console-json: + type: console + layout: + type: json + unknown: key: 1 diff --git a/src/cli/serve/integration_tests/__fixtures__/reload_logging_config/kibana.test.yml b/src/cli/serve/integration_tests/__fixtures__/reload_logging_config/kibana.test.yml deleted file mode 100644 index 1761a7984e0e7..0000000000000 --- a/src/cli/serve/integration_tests/__fixtures__/reload_logging_config/kibana.test.yml +++ /dev/null @@ -1,13 +0,0 @@ -server: - autoListen: false - port: 8274 -logging: - json: true -optimize: - enabled: false -plugins: - initialize: false -migrations: - skip: true -elasticsearch: - skipStartupConnectionCheck: true diff --git a/src/cli/serve/integration_tests/invalid_config.test.ts b/src/cli/serve/integration_tests/invalid_config.test.ts index 724998699da85..2de902582a548 100644 --- a/src/cli/serve/integration_tests/invalid_config.test.ts +++ b/src/cli/serve/integration_tests/invalid_config.test.ts @@ -14,14 +14,15 @@ const INVALID_CONFIG_PATH = require.resolve('./__fixtures__/invalid_config.yml') interface LogEntry { message: string; - tags?: string[]; - type: string; + log: { + level: string; + }; } -describe('cli invalid config support', function () { +describe('cli invalid config support', () => { it( - 'exits with statusCode 64 and logs a single line when config is invalid', - function () { + 'exits with statusCode 64 and logs an error when config is invalid', + () => { // Unused keys only throw once LegacyService starts, so disable migrations so that Core // will finish the start lifecycle without a running Elasticsearch instance. const { error, status, stdout, stderr } = spawnSync( @@ -31,41 +32,27 @@ describe('cli invalid config support', function () { cwd: REPO_ROOT, } ); + expect(error).toBe(undefined); - let fatalLogLine; + let fatalLogEntries; try { - [fatalLogLine] = stdout + fatalLogEntries = stdout .toString('utf8') .split('\n') .filter(Boolean) .map((line) => JSON.parse(line) as LogEntry) - .filter((line) => line.tags?.includes('fatal')) - .map((obj) => ({ - ...obj, - pid: '## PID ##', - '@timestamp': '## @timestamp ##', - error: '## Error with stack trace ##', - })); + .filter((line) => line.log.level === 'FATAL'); } catch (e) { throw new Error( `error parsing log output:\n\n${e.stack}\n\nstdout: \n${stdout}\n\nstderr:\n${stderr}` ); } - expect(error).toBe(undefined); - - if (!fatalLogLine) { - throw new Error( - `cli did not log the expected fatal error message:\n\nstdout: \n${stdout}\n\nstderr:\n${stderr}` - ); - } - - expect(fatalLogLine.message).toContain( - 'Error: Unknown configuration key(s): "unknown.key", "other.unknown.key", "other.third", "some.flat.key", ' + + expect(fatalLogEntries).toHaveLength(1); + expect(fatalLogEntries[0].message).toContain( + 'Unknown configuration key(s): "unknown.key", "other.unknown.key", "other.third", "some.flat.key", ' + '"some.array". Check for spelling errors and ensure that expected plugins are installed.' ); - expect(fatalLogLine.tags).toEqual(['fatal', 'root']); - expect(fatalLogLine.type).toEqual('log'); expect(status).toBe(64); }, diff --git a/src/cli/serve/integration_tests/reload_logging_config.test.ts b/src/cli/serve/integration_tests/reload_logging_config.test.ts index 80ce52661565c..4cee7dfae4126 100644 --- a/src/cli/serve/integration_tests/reload_logging_config.test.ts +++ b/src/cli/serve/integration_tests/reload_logging_config.test.ts @@ -17,7 +17,6 @@ import { map, filter, take } from 'rxjs/operators'; import { safeDump } from 'js-yaml'; import { getConfigFromFiles } from '@kbn/config'; -const legacyConfig = follow('__fixtures__/reload_logging_config/kibana.test.yml'); const configFileLogConsole = follow( '__fixtures__/reload_logging_config/kibana_log_console.test.yml' ); @@ -96,81 +95,6 @@ describe.skip('Server logging configuration', function () { return; } - describe('legacy logging', () => { - it( - 'should be reloadable via SIGHUP process signaling', - async function () { - const configFilePath = Path.resolve(tempDir, 'kibana.yml'); - Fs.copyFileSync(legacyConfig, configFilePath); - - child = Child.spawn(process.execPath, [ - kibanaPath, - '--oss', - '--config', - configFilePath, - '--verbose', - ]); - - // TypeScript note: As long as the child stdio[1] is 'pipe', then stdout will not be null - const message$ = Rx.fromEvent(child.stdout!, 'data').pipe( - map((messages) => String(messages).split('\n').filter(Boolean)) - ); - - await message$ - .pipe( - // We know the sighup handler will be registered before this message logged - filter((messages: string[]) => messages.some((m) => m.includes('setting up root'))), - take(1) - ) - .toPromise(); - - const lastMessage = await message$.pipe(take(1)).toPromise(); - expect(containsJsonOnly(lastMessage)).toBe(true); - - createConfigManager(configFilePath).modify((oldConfig) => { - oldConfig.logging.json = false; - return oldConfig; - }); - - child.kill('SIGHUP'); - - await message$ - .pipe( - filter((messages) => !containsJsonOnly(messages)), - take(1) - ) - .toPromise(); - }, - minute - ); - - it( - 'should recreate file handle on SIGHUP', - async function () { - const logPath = Path.resolve(tempDir, 'kibana.log'); - const logPathArchived = Path.resolve(tempDir, 'kibana_archive.log'); - - child = Child.spawn(process.execPath, [ - kibanaPath, - '--oss', - '--config', - legacyConfig, - '--logging.dest', - logPath, - '--verbose', - ]); - - await watchFileUntil(logPath, /setting up root/, 30 * second); - // once the server is running, archive the log file and issue SIGHUP - Fs.renameSync(logPath, logPathArchived); - child.kill('SIGHUP'); - - await watchFileUntil(logPath, /Reloaded logging configuration due to SIGHUP/, 30 * second); - }, - minute - ); - }); - describe('platform logging', () => { it( 'should be reloadable via SIGHUP process signaling', diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index 705acfe4fdf54..8b346d38cfea8 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -124,17 +124,12 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) { if (opts.elasticsearch) set('elasticsearch.hosts', opts.elasticsearch.split(',')); if (opts.port) set('server.port', opts.port); if (opts.host) set('server.host', opts.host); + if (opts.silent) { - set('logging.silent', true); set('logging.root.level', 'off'); } if (opts.verbose) { - if (has('logging.root.appenders')) { - set('logging.root.level', 'all'); - } else { - // Only set logging.verbose to true for legacy logging when KP logging isn't configured. - set('logging.verbose', true); - } + set('logging.root.level', 'all'); } set('plugins.paths', _.compact([].concat(get('plugins.paths'), opts.pluginPath))); @@ -159,9 +154,8 @@ export default function (program) { [getConfigPath()] ) .option('-p, --port ', 'The port to bind to', parseInt) - .option('-q, --quiet', 'Deprecated, set logging level in your configuration') - .option('-Q, --silent', 'Prevent all logging') - .option('--verbose', 'Turns on verbose logging') + .option('-Q, --silent', 'Set the root logger level to off') + .option('--verbose', 'Set the root logger level to all') .option('-H, --host ', 'The host to bind to') .option( '-l, --log-file ', @@ -217,8 +211,6 @@ export default function (program) { const cliArgs = { dev: !!opts.dev, envName: unknownOptions.env ? unknownOptions.env.name : undefined, - // no longer supported - quiet: !!opts.quiet, silent: !!opts.silent, verbose: !!opts.verbose, watch: !!opts.watch, diff --git a/src/core/server/config/deprecation/core_deprecations.test.ts b/src/core/server/config/deprecation/core_deprecations.test.ts index d3a4d7f997062..4e99f46ea05ff 100644 --- a/src/core/server/config/deprecation/core_deprecations.test.ts +++ b/src/core/server/config/deprecation/core_deprecations.test.ts @@ -8,6 +8,7 @@ import { getDeprecationsForGlobalSettings } from '../test_utils'; import { coreDeprecationProvider } from './core_deprecations'; + const initialEnv = { ...process.env }; const applyCoreDeprecations = (settings?: Record) => @@ -203,230 +204,4 @@ describe('core deprecations', () => { ).toEqual([`worker-src blob:`]); }); }); - - describe('logging.events.ops', () => { - it('warns when ops events are used', () => { - const { messages } = applyCoreDeprecations({ - logging: { events: { ops: '*' } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.events.ops\\" has been deprecated and will be removed in 8.0. To access ops data moving forward, please enable debug logs for the \\"metrics.ops\\" context in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", - ] - `); - }); - }); - - describe('logging.events.request and logging.events.response', () => { - it('warns when request and response events are used', () => { - const { messages } = applyCoreDeprecations({ - logging: { events: { request: '*', response: '*' } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.events.request\\" and \\"logging.events.response\\" have been deprecated and will be removed in 8.0. To access request and/or response data moving forward, please enable debug logs for the \\"http.server.response\\" context in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", - ] - `); - }); - - it('warns when only request event is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { events: { request: '*' } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.events.request\\" and \\"logging.events.response\\" have been deprecated and will be removed in 8.0. To access request and/or response data moving forward, please enable debug logs for the \\"http.server.response\\" context in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", - ] - `); - }); - - it('warns when only response event is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { events: { response: '*' } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.events.request\\" and \\"logging.events.response\\" have been deprecated and will be removed in 8.0. To access request and/or response data moving forward, please enable debug logs for the \\"http.server.response\\" context in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", - ] - `); - }); - }); - - describe('logging.timezone', () => { - it('warns when ops events are used', () => { - const { messages } = applyCoreDeprecations({ - logging: { timezone: 'GMT' }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.timezone\\" has been deprecated and will be removed in 8.0. To set the timezone moving forward, please add a timezone date modifier to the log pattern in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", - ] - `); - }); - }); - - describe('logging.dest', () => { - it('warns when dest is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { dest: 'stdout' }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", - ] - `); - }); - it('warns when dest path is given', () => { - const { messages } = applyCoreDeprecations({ - logging: { dest: '/log-log.txt' }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.dest\\" has been deprecated and will be removed in 8.0. To set the destination moving forward, you can use the \\"console\\" appender in your logging configuration or define a custom one. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", - ] - `); - }); - }); - - describe('logging.quiet, logging.silent and logging.verbose', () => { - it('warns when quiet is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { quiet: true }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.quiet\\" has been deprecated and will be removed in 8.0. Moving forward, you can use \\"logging.root.level:error\\" in your logging configuration. ", - ] - `); - }); - it('warns when silent is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { silent: true }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.silent\\" has been deprecated and will be removed in 8.0. Moving forward, you can use \\"logging.root.level:off\\" in your logging configuration. ", - ] - `); - }); - it('warns when verbose is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { verbose: true }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.verbose\\" has been deprecated and will be removed in 8.0. Moving forward, you can use \\"logging.root.level:all\\" in your logging configuration. ", - ] - `); - }); - }); - - describe('logging.json', () => { - it('warns when json is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { json: true }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.json\\" has been deprecated and will be removed in 8.0. To specify log message format moving forward, you can configure the \\"appender.layout\\" property for every custom appender in your logging configuration. There is currently no default layout for custom appenders and each one must be declared explicitly. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx", - ] - `); - }); - }); - - describe('logging.rotate.enabled, logging.rotate.usePolling, logging.rotate.pollingInterval, logging.rotate.everyBytes and logging.rotate.keepFiles', () => { - it('warns when logging.rotate configurations are used', () => { - const { messages } = applyCoreDeprecations({ - logging: { rotate: { enabled: true } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.rotate\\" and sub-options have been deprecated and will be removed in 8.0. Moving forward, you can enable log rotation using the \\"rolling-file\\" appender for a logger in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender", - ] - `); - }); - - it('warns when logging.rotate polling configurations are used', () => { - const { messages } = applyCoreDeprecations({ - logging: { rotate: { enabled: true, usePolling: true, pollingInterval: 5000 } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.rotate\\" and sub-options have been deprecated and will be removed in 8.0. Moving forward, you can enable log rotation using the \\"rolling-file\\" appender for a logger in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender", - ] - `); - }); - - it('warns when logging.rotate.everyBytes configurations are used', () => { - const { messages } = applyCoreDeprecations({ - logging: { rotate: { enabled: true, everyBytes: 1048576 } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.rotate\\" and sub-options have been deprecated and will be removed in 8.0. Moving forward, you can enable log rotation using the \\"rolling-file\\" appender for a logger in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender", - ] - `); - }); - - it('warns when logging.rotate.keepFiles is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { rotate: { enabled: true, keepFiles: 1024 } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.rotate\\" and sub-options have been deprecated and will be removed in 8.0. Moving forward, you can enable log rotation using the \\"rolling-file\\" appender for a logger in your logging configuration. For more details, see https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender", - ] - `); - }); - }); - - describe('logging.events.log', () => { - it('warns when events.log is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { events: { log: ['info'] } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.events.log\\" has been deprecated and will be removed in 8.0. Moving forward, log levels can be customized on a per-logger basis using the new logging configuration.", - ] - `); - }); - }); - - describe('logging.events.error', () => { - it('warns when events.error is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { events: { error: ['some error'] } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.events.error\\" has been deprecated and will be removed in 8.0. Moving forward, you can use \\"logging.root.level: error\\" in your logging configuration.", - ] - `); - }); - }); - - describe('logging.filter', () => { - it('warns when filter.cookie is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { filter: { cookie: 'none' } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.filter\\" has been deprecated and will be removed in 8.0.", - ] - `); - }); - - it('warns when filter.authorization is used', () => { - const { messages } = applyCoreDeprecations({ - logging: { filter: { authorization: 'none' } }, - }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"logging.filter\\" has been deprecated and will be removed in 8.0.", - ] - `); - }); - }); }); diff --git a/src/core/server/config/deprecation/core_deprecations.ts b/src/core/server/config/deprecation/core_deprecations.ts index 6e7365d0d5cbf..674812bd0957b 100644 --- a/src/core/server/config/deprecation/core_deprecations.ts +++ b/src/core/server/config/deprecation/core_deprecations.ts @@ -113,245 +113,6 @@ const cspRulesDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecati } }; -const opsLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.events?.ops) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', - message: - '"logging.events.ops" has been deprecated and will be removed ' + - 'in 8.0. To access ops data moving forward, please enable debug logs for the ' + - '"metrics.ops" context in your logging configuration. For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', - correctiveActions: { - manualSteps: [ - `Remove "logging.events.ops" from your kibana settings.`, - `Enable debug logs for the "metrics.ops" context in your logging configuration`, - ], - }, - }); - } -}; - -const requestLoggingEventDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.events?.request || settings.logging?.events?.response) { - const removeConfigsSteps = []; - - if (settings.logging?.events?.request) { - removeConfigsSteps.push(`Remove "logging.events.request" from your kibana configs.`); - } - - if (settings.logging?.events?.response) { - removeConfigsSteps.push(`Remove "logging.events.response" from your kibana configs.`); - } - - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', - message: - '"logging.events.request" and "logging.events.response" have been deprecated and will be removed ' + - 'in 8.0. To access request and/or response data moving forward, please enable debug logs for the ' + - '"http.server.response" context in your logging configuration. For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', - correctiveActions: { - manualSteps: [ - ...removeConfigsSteps, - `enable debug logs for the "http.server.response" context in your logging configuration.`, - ], - }, - }); - } -}; - -const timezoneLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.timezone) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingtimezone', - message: - '"logging.timezone" has been deprecated and will be removed ' + - 'in 8.0. To set the timezone moving forward, please add a timezone date modifier to the log pattern ' + - 'in your logging configuration. For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', - correctiveActions: { - manualSteps: [ - `Remove "logging.timezone" from your kibana configs.`, - `To set the timezone add a timezone date modifier to the log pattern in your logging configuration.`, - ], - }, - }); - } -}; - -const destLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.dest) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingdest', - message: - '"logging.dest" has been deprecated and will be removed ' + - 'in 8.0. To set the destination moving forward, you can use the "console" appender ' + - 'in your logging configuration or define a custom one. For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', - correctiveActions: { - manualSteps: [ - `Remove "logging.dest" from your kibana configs.`, - `To set the destination use the "console" appender in your logging configuration or define a custom one.`, - ], - }, - }); - } -}; - -const quietLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.quiet) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingquiet', - message: - '"logging.quiet" has been deprecated and will be removed ' + - 'in 8.0. Moving forward, you can use "logging.root.level:error" in your logging configuration. ', - correctiveActions: { - manualSteps: [ - `Remove "logging.quiet" from your kibana configs.`, - `Use "logging.root.level:error" in your logging configuration.`, - ], - }, - }); - } -}; - -const silentLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.silent) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingsilent', - message: - '"logging.silent" has been deprecated and will be removed ' + - 'in 8.0. Moving forward, you can use "logging.root.level:off" in your logging configuration. ', - correctiveActions: { - manualSteps: [ - `Remove "logging.silent" from your kibana configs.`, - `Use "logging.root.level:off" in your logging configuration.`, - ], - }, - }); - } -}; - -const verboseLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.verbose) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingverbose', - message: - '"logging.verbose" has been deprecated and will be removed ' + - 'in 8.0. Moving forward, you can use "logging.root.level:all" in your logging configuration. ', - correctiveActions: { - manualSteps: [ - `Remove "logging.verbose" from your kibana configs.`, - `Use "logging.root.level:all" in your logging configuration.`, - ], - }, - }); - } -}; - -const jsonLoggingDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - // We silence the deprecation warning when running in development mode because - // the dev CLI code in src/dev/cli_dev_mode/using_server_process.ts manually - // specifies `--logging.json=false`. Since it's executed in a child process, the - // ` legacyLoggingConfigSchema` returns `true` for the TTY check on `process.stdout.isTTY` - if (settings.logging?.json && settings.env !== 'development') { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', - message: - '"logging.json" has been deprecated and will be removed ' + - 'in 8.0. To specify log message format moving forward, ' + - 'you can configure the "appender.layout" property for every custom appender in your logging configuration. ' + - 'There is currently no default layout for custom appenders and each one must be declared explicitly. ' + - 'For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx', - correctiveActions: { - manualSteps: [ - `Remove "logging.json" from your kibana configs.`, - `Configure the "appender.layout" property for every custom appender in your logging configuration.`, - ], - }, - }); - } -}; - -const logRotateDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.rotate) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender', - message: - '"logging.rotate" and sub-options have been deprecated and will be removed in 8.0. ' + - 'Moving forward, you can enable log rotation using the "rolling-file" appender for a logger ' + - 'in your logging configuration. For more details, see ' + - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#rolling-file-appender', - correctiveActions: { - manualSteps: [ - `Remove "logging.rotate" from your kibana configs.`, - `Enable log rotation using the "rolling-file" appender for a logger in your logging configuration.`, - ], - }, - }); - } -}; - -const logEventsLogDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.events?.log) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', - message: - '"logging.events.log" has been deprecated and will be removed ' + - 'in 8.0. Moving forward, log levels can be customized on a per-logger basis using the new logging configuration.', - correctiveActions: { - manualSteps: [ - `Remove "logging.events.log" from your kibana configs.`, - `Customize log levels can be per-logger using the new logging configuration.`, - ], - }, - }); - } -}; - -const logEventsErrorDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.events?.error) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingevents', - message: - '"logging.events.error" has been deprecated and will be removed ' + - 'in 8.0. Moving forward, you can use "logging.root.level: error" in your logging configuration.', - correctiveActions: { - manualSteps: [ - `Remove "logging.events.error" from your kibana configs.`, - `Use "logging.root.level: error" in your logging configuration.`, - ], - }, - }); - } -}; - -const logFilterDeprecation: ConfigDeprecation = (settings, fromPath, addDeprecation) => { - if (settings.logging?.filter) { - addDeprecation({ - documentationUrl: - 'https://github.com/elastic/kibana/blob/master/src/core/server/logging/README.mdx#loggingfilter', - message: '"logging.filter" has been deprecated and will be removed in 8.0.', - correctiveActions: { - manualSteps: [`Remove "logging.filter" from your kibana configs.`], - }, - }); - } -}; - export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unusedFromRoot }) => [ rename('cpu.cgroup.path.override', 'ops.cGroupOverrides.cpuPath'), rename('cpuacct.cgroup.path.override', 'ops.cGroupOverrides.cpuAcctPath'), @@ -360,16 +121,4 @@ export const coreDeprecationProvider: ConfigDeprecationProvider = ({ rename, unu kibanaPathConf, rewriteBasePathDeprecation, cspRulesDeprecation, - opsLoggingEventDeprecation, - requestLoggingEventDeprecation, - timezoneLoggingDeprecation, - destLoggingDeprecation, - quietLoggingDeprecation, - silentLoggingDeprecation, - verboseLoggingDeprecation, - jsonLoggingDeprecation, - logRotateDeprecation, - logEventsLogDeprecation, - logEventsErrorDeprecation, - logFilterDeprecation, ]; diff --git a/src/core/server/config/index.ts b/src/core/server/config/index.ts index 686564c6d678a..7254dd5222b84 100644 --- a/src/core/server/config/index.ts +++ b/src/core/server/config/index.ts @@ -30,5 +30,4 @@ export type { ConfigDeprecationFactory, EnvironmentMode, PackageInfo, - LegacyObjectToConfigAdapter, } from '@kbn/config'; diff --git a/src/core/server/config/integration_tests/config_deprecation.test.ts b/src/core/server/config/integration_tests/config_deprecation.test.ts index 0138c6e7ef154..5036fa4742b59 100644 --- a/src/core/server/config/integration_tests/config_deprecation.test.ts +++ b/src/core/server/config/integration_tests/config_deprecation.test.ts @@ -23,17 +23,13 @@ describe('configuration deprecations', () => { } }); - it('should not log deprecation warnings for default configuration that is not one of `logging.verbose`, `logging.quiet` or `logging.silent`', async () => { + it('should not log deprecation warnings for default configuration', async () => { root = kbnTestServer.createRoot(); await root.preboot(); await root.setup(); const logs = loggingSystemMock.collect(mockLoggingSystem); - expect(logs.warn.flat()).toMatchInlineSnapshot(` - Array [ - "\\"logging.silent\\" has been deprecated and will be removed in 8.0. Moving forward, you can use \\"logging.root.level:off\\" in your logging configuration. ", - ] - `); + expect(logs.warn.flat()).toHaveLength(0); }); }); diff --git a/src/core/server/elasticsearch/elasticsearch_config.ts b/src/core/server/elasticsearch/elasticsearch_config.ts index 995b3ffbd947d..7470ff7081717 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.ts @@ -211,7 +211,7 @@ const deprecations: ConfigDeprecationProvider = () => [ }); } else if (es.logQueries === true) { addDeprecation({ - message: `Setting [${fromPath}.logQueries] is deprecated and no longer used. You should set the log level to "debug" for the "elasticsearch.queries" context in "logging.loggers" or use "logging.verbose: true".`, + message: `Setting [${fromPath}.logQueries] is deprecated and no longer used. You should set the log level to "debug" for the "elasticsearch.queries" context in "logging.loggers".`, correctiveActions: { manualSteps: [ `Remove Setting [${fromPath}.logQueries] from your kibana configs`, diff --git a/src/core/server/http/integration_tests/logging.test.ts b/src/core/server/http/integration_tests/logging.test.ts index 12d555a240cde..20e0175d4b19d 100644 --- a/src/core/server/http/integration_tests/logging.test.ts +++ b/src/core/server/http/integration_tests/logging.test.ts @@ -51,7 +51,6 @@ describe('request logging', () => { it('logs at the correct level and with the correct context', async () => { const root = kbnTestServer.createRoot({ logging: { - silent: true, appenders: { 'test-console': { type: 'console', @@ -99,7 +98,6 @@ describe('request logging', () => { let root: ReturnType; const config = { logging: { - silent: true, appenders: { 'test-console': { type: 'console', @@ -300,7 +298,6 @@ describe('request logging', () => { it('filters sensitive request headers when RewriteAppender is configured', async () => { root = kbnTestServer.createRoot({ logging: { - silent: true, appenders: { 'test-console': { type: 'console', @@ -402,7 +399,6 @@ describe('request logging', () => { it('filters sensitive response headers when RewriteAppender is configured', async () => { root = kbnTestServer.createRoot({ logging: { - silent: true, appenders: { 'test-console': { type: 'console', diff --git a/src/core/server/legacy/index.ts b/src/core/server/legacy/index.ts deleted file mode 100644 index 39ffef501a9ec..0000000000000 --- a/src/core/server/legacy/index.ts +++ /dev/null @@ -1,11 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -/** @internal */ -export type { ILegacyService } from './legacy_service'; -export { LegacyService } from './legacy_service'; diff --git a/src/core/server/legacy/integration_tests/logging.test.ts b/src/core/server/legacy/integration_tests/logging.test.ts deleted file mode 100644 index a79e434ce4576..0000000000000 --- a/src/core/server/legacy/integration_tests/logging.test.ts +++ /dev/null @@ -1,234 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { LegacyLoggingConfig } from '@kbn/config'; -import * as kbnTestServer from '../../../test_helpers/kbn_server'; - -import { - getPlatformLogsFromMock, - getLegacyPlatformLogsFromMock, -} from '../../logging/integration_tests/utils'; - -function createRoot(legacyLoggingConfig: LegacyLoggingConfig = {}) { - return kbnTestServer.createRoot({ - migrations: { skip: true }, // otherwise stuck in polling ES - plugins: { initialize: false }, - elasticsearch: { skipStartupConnectionCheck: true }, - logging: { - // legacy platform config - silent: false, - json: false, - ...legacyLoggingConfig, - events: { - log: ['test-file-legacy'], - }, - // platform config - appenders: { - 'test-console': { - type: 'console', - layout: { - highlight: false, - type: 'pattern', - }, - }, - }, - loggers: [ - { - name: 'test-file', - appenders: ['test-console'], - level: 'info', - }, - ], - }, - }); -} - -describe('logging service', () => { - let mockConsoleLog: jest.SpyInstance; - let mockStdout: jest.SpyInstance; - - beforeAll(async () => { - mockConsoleLog = jest.spyOn(global.console, 'log'); - mockStdout = jest.spyOn(global.process.stdout, 'write'); - }); - - afterAll(async () => { - mockConsoleLog.mockRestore(); - mockStdout.mockRestore(); - }); - - describe('compatibility', () => { - describe('uses configured loggers', () => { - let root: ReturnType; - beforeAll(async () => { - root = createRoot(); - - await root.preboot(); - await root.setup(); - await root.start(); - }, 30000); - - afterAll(async () => { - await root.shutdown(); - }); - - beforeEach(() => { - mockConsoleLog.mockClear(); - mockStdout.mockClear(); - }); - - it('when context matches', async () => { - root.logger.get('test-file').info('handled by NP'); - - expect(mockConsoleLog).toHaveBeenCalledTimes(1); - const loggedString = getPlatformLogsFromMock(mockConsoleLog); - expect(loggedString).toMatchInlineSnapshot(` - Array [ - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][INFO ][test-file] handled by NP", - ] - `); - }); - - it('falls back to the root legacy logger otherwise', async () => { - root.logger.get('test-file-legacy').info('handled by LP'); - - expect(mockStdout).toHaveBeenCalledTimes(1); - - const loggedString = getLegacyPlatformLogsFromMock(mockStdout); - expect(loggedString).toMatchInlineSnapshot(` - Array [ - " log [xx:xx:xx.xxx] [info][test-file-legacy] handled by LP - ", - ] - `); - }); - }); - - describe('logging config respects legacy logging settings', () => { - let root: ReturnType; - - afterEach(async () => { - mockConsoleLog.mockClear(); - mockStdout.mockClear(); - await root.shutdown(); - }); - - it('"silent": true', async () => { - root = createRoot({ silent: true }); - - await root.preboot(); - await root.setup(); - await root.start(); - - const platformLogger = root.logger.get('test-file'); - platformLogger.info('info'); - platformLogger.warn('warn'); - platformLogger.error('error'); - - expect(mockConsoleLog).toHaveBeenCalledTimes(3); - - expect(getPlatformLogsFromMock(mockConsoleLog)).toMatchInlineSnapshot(` - Array [ - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][INFO ][test-file] info", - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][WARN ][test-file] warn", - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][ERROR][test-file] error", - ] - `); - - mockStdout.mockClear(); - - const legacyPlatformLogger = root.logger.get('test-file-legacy'); - legacyPlatformLogger.info('info'); - legacyPlatformLogger.warn('warn'); - legacyPlatformLogger.error('error'); - - expect(mockStdout).toHaveBeenCalledTimes(0); - }); - - it('"quiet": true', async () => { - root = createRoot({ quiet: true }); - - await root.preboot(); - await root.setup(); - await root.start(); - - const platformLogger = root.logger.get('test-file'); - platformLogger.info('info'); - platformLogger.warn('warn'); - platformLogger.error('error'); - - expect(mockConsoleLog).toHaveBeenCalledTimes(3); - - expect(getPlatformLogsFromMock(mockConsoleLog)).toMatchInlineSnapshot(` - Array [ - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][INFO ][test-file] info", - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][WARN ][test-file] warn", - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][ERROR][test-file] error", - ] - `); - - mockStdout.mockClear(); - - const legacyPlatformLogger = root.logger.get('test-file-legacy'); - legacyPlatformLogger.info('info'); - legacyPlatformLogger.warn('warn'); - legacyPlatformLogger.error('error'); - - expect(mockStdout).toHaveBeenCalledTimes(1); - expect(getLegacyPlatformLogsFromMock(mockStdout)).toMatchInlineSnapshot(` - Array [ - " log [xx:xx:xx.xxx] [error][test-file-legacy] error - ", - ] - `); - }); - - it('"verbose": true', async () => { - root = createRoot({ verbose: true }); - - await root.preboot(); - await root.setup(); - await root.start(); - - const platformLogger = root.logger.get('test-file'); - platformLogger.info('info'); - platformLogger.warn('warn'); - platformLogger.error('error'); - - expect(mockConsoleLog).toHaveBeenCalledTimes(3); - - expect(getPlatformLogsFromMock(mockConsoleLog)).toMatchInlineSnapshot(` - Array [ - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][INFO ][test-file] info", - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][WARN ][test-file] warn", - "[xxxx-xx-xxTxx:xx:xx.xxx-xx:xx][ERROR][test-file] error", - ] - `); - - mockStdout.mockClear(); - - const legacyPlatformLogger = root.logger.get('test-file-legacy'); - legacyPlatformLogger.info('info'); - legacyPlatformLogger.warn('warn'); - legacyPlatformLogger.error('error'); - - expect(mockStdout).toHaveBeenCalledTimes(3); - expect(getLegacyPlatformLogsFromMock(mockStdout)).toMatchInlineSnapshot(` - Array [ - " log [xx:xx:xx.xxx] [info][test-file-legacy] info - ", - " log [xx:xx:xx.xxx] [warning][test-file-legacy] warn - ", - " log [xx:xx:xx.xxx] [error][test-file-legacy] error - ", - ] - `); - }); - }); - }); -}); diff --git a/src/core/server/legacy/legacy_service.mock.ts b/src/core/server/legacy/legacy_service.mock.ts deleted file mode 100644 index 0d72318a630e0..0000000000000 --- a/src/core/server/legacy/legacy_service.mock.ts +++ /dev/null @@ -1,21 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import type { PublicMethodsOf } from '@kbn/utility-types'; -import { LegacyService } from './legacy_service'; - -type LegacyServiceMock = jest.Mocked>; - -const createLegacyServiceMock = (): LegacyServiceMock => ({ - setup: jest.fn(), - stop: jest.fn(), -}); - -export const legacyServiceMock = { - create: createLegacyServiceMock, -}; diff --git a/src/core/server/legacy/legacy_service.test.mocks.ts b/src/core/server/legacy/legacy_service.test.mocks.ts deleted file mode 100644 index 506f0fd6f96d3..0000000000000 --- a/src/core/server/legacy/legacy_service.test.mocks.ts +++ /dev/null @@ -1,18 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export const reconfigureLoggingMock = jest.fn(); -export const setupLoggingMock = jest.fn(); -export const setupLoggingRotateMock = jest.fn(); - -jest.doMock('@kbn/legacy-logging', () => ({ - ...(jest.requireActual('@kbn/legacy-logging') as any), - reconfigureLogging: reconfigureLoggingMock, - setupLogging: setupLoggingMock, - setupLoggingRotate: setupLoggingRotateMock, -})); diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts deleted file mode 100644 index 6b20bd7434baf..0000000000000 --- a/src/core/server/legacy/legacy_service.test.ts +++ /dev/null @@ -1,197 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - setupLoggingMock, - setupLoggingRotateMock, - reconfigureLoggingMock, -} from './legacy_service.test.mocks'; - -import { BehaviorSubject } from 'rxjs'; -import moment from 'moment'; -import { REPO_ROOT } from '@kbn/dev-utils'; - -import { Config, Env, ObjectToConfigAdapter } from '../config'; - -import { getEnvOptions, configServiceMock } from '../config/mocks'; -import { loggingSystemMock } from '../logging/logging_system.mock'; -import { httpServiceMock } from '../http/http_service.mock'; -import { LegacyService, LegacyServiceSetupDeps } from './legacy_service'; - -let coreId: symbol; -let env: Env; -let config$: BehaviorSubject; - -let setupDeps: LegacyServiceSetupDeps; - -const logger = loggingSystemMock.create(); -let configService: ReturnType; - -beforeEach(() => { - coreId = Symbol(); - env = Env.createDefault(REPO_ROOT, getEnvOptions()); - configService = configServiceMock.create(); - - setupDeps = { - http: httpServiceMock.createInternalSetupContract(), - }; - - config$ = new BehaviorSubject( - new ObjectToConfigAdapter({ - elasticsearch: { hosts: ['http://127.0.0.1'] }, - server: { autoListen: true }, - }) - ); - - configService.getConfig$.mockReturnValue(config$); -}); - -afterEach(() => { - jest.clearAllMocks(); - setupLoggingMock.mockReset(); - setupLoggingRotateMock.mockReset(); - reconfigureLoggingMock.mockReset(); -}); - -describe('#setup', () => { - it('initializes legacy logging', async () => { - const opsConfig = { - interval: moment.duration(5, 'second'), - }; - const opsConfig$ = new BehaviorSubject(opsConfig); - - const loggingConfig = { - foo: 'bar', - }; - const loggingConfig$ = new BehaviorSubject(loggingConfig); - - configService.atPath.mockImplementation((path) => { - if (path === 'ops') { - return opsConfig$; - } - if (path === 'logging') { - return loggingConfig$; - } - return new BehaviorSubject({}); - }); - - const legacyService = new LegacyService({ - coreId, - env, - logger, - configService: configService as any, - }); - - await legacyService.setup(setupDeps); - - expect(setupLoggingMock).toHaveBeenCalledTimes(1); - expect(setupLoggingMock).toHaveBeenCalledWith( - setupDeps.http.server, - loggingConfig, - opsConfig.interval.asMilliseconds() - ); - - expect(setupLoggingRotateMock).toHaveBeenCalledTimes(1); - expect(setupLoggingRotateMock).toHaveBeenCalledWith(setupDeps.http.server, loggingConfig); - }); - - it('reloads the logging config when the config changes', async () => { - const opsConfig = { - interval: moment.duration(5, 'second'), - }; - const opsConfig$ = new BehaviorSubject(opsConfig); - - const loggingConfig = { - foo: 'bar', - }; - const loggingConfig$ = new BehaviorSubject(loggingConfig); - - configService.atPath.mockImplementation((path) => { - if (path === 'ops') { - return opsConfig$; - } - if (path === 'logging') { - return loggingConfig$; - } - return new BehaviorSubject({}); - }); - - const legacyService = new LegacyService({ - coreId, - env, - logger, - configService: configService as any, - }); - - await legacyService.setup(setupDeps); - - expect(reconfigureLoggingMock).toHaveBeenCalledTimes(1); - expect(reconfigureLoggingMock).toHaveBeenCalledWith( - setupDeps.http.server, - loggingConfig, - opsConfig.interval.asMilliseconds() - ); - - loggingConfig$.next({ - foo: 'changed', - }); - - expect(reconfigureLoggingMock).toHaveBeenCalledTimes(2); - expect(reconfigureLoggingMock).toHaveBeenCalledWith( - setupDeps.http.server, - { foo: 'changed' }, - opsConfig.interval.asMilliseconds() - ); - }); - - it('stops reloading logging config once the service is stopped', async () => { - const opsConfig = { - interval: moment.duration(5, 'second'), - }; - const opsConfig$ = new BehaviorSubject(opsConfig); - - const loggingConfig = { - foo: 'bar', - }; - const loggingConfig$ = new BehaviorSubject(loggingConfig); - - configService.atPath.mockImplementation((path) => { - if (path === 'ops') { - return opsConfig$; - } - if (path === 'logging') { - return loggingConfig$; - } - return new BehaviorSubject({}); - }); - - const legacyService = new LegacyService({ - coreId, - env, - logger, - configService: configService as any, - }); - - await legacyService.setup(setupDeps); - - expect(reconfigureLoggingMock).toHaveBeenCalledTimes(1); - expect(reconfigureLoggingMock).toHaveBeenCalledWith( - setupDeps.http.server, - loggingConfig, - opsConfig.interval.asMilliseconds() - ); - - await legacyService.stop(); - - loggingConfig$.next({ - foo: 'changed', - }); - - expect(reconfigureLoggingMock).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts deleted file mode 100644 index 1d5343ff5311d..0000000000000 --- a/src/core/server/legacy/legacy_service.ts +++ /dev/null @@ -1,75 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { combineLatest, Observable, Subscription } from 'rxjs'; -import { first } from 'rxjs/operators'; -import { Server } from '@hapi/hapi'; -import type { PublicMethodsOf } from '@kbn/utility-types'; -import { - reconfigureLogging, - setupLogging, - setupLoggingRotate, - LegacyLoggingConfig, -} from '@kbn/legacy-logging'; - -import { CoreContext } from '../core_context'; -import { config as loggingConfig } from '../logging'; -import { opsConfig, OpsConfigType } from '../metrics'; -import { Logger } from '../logging'; -import { InternalHttpServiceSetup } from '../http'; - -export interface LegacyServiceSetupDeps { - http: InternalHttpServiceSetup; -} - -/** @internal */ -export type ILegacyService = PublicMethodsOf; - -/** @internal */ -export class LegacyService { - private readonly log: Logger; - private readonly opsConfig$: Observable; - private readonly legacyLoggingConfig$: Observable; - private configSubscription?: Subscription; - - constructor(coreContext: CoreContext) { - const { logger, configService } = coreContext; - - this.log = logger.get('legacy-service'); - this.legacyLoggingConfig$ = configService.atPath(loggingConfig.path); - this.opsConfig$ = configService.atPath(opsConfig.path); - } - - public async setup(setupDeps: LegacyServiceSetupDeps) { - this.log.debug('setting up legacy service'); - await this.setupLegacyLogging(setupDeps.http.server); - } - - private async setupLegacyLogging(server: Server) { - const legacyLoggingConfig = await this.legacyLoggingConfig$.pipe(first()).toPromise(); - const currentOpsConfig = await this.opsConfig$.pipe(first()).toPromise(); - - await setupLogging(server, legacyLoggingConfig, currentOpsConfig.interval.asMilliseconds()); - await setupLoggingRotate(server, legacyLoggingConfig); - - this.configSubscription = combineLatest([this.legacyLoggingConfig$, this.opsConfig$]).subscribe( - ([newLoggingConfig, newOpsConfig]) => { - reconfigureLogging(server, newLoggingConfig, newOpsConfig.interval.asMilliseconds()); - } - ); - } - - public async stop() { - this.log.debug('stopping legacy service'); - - if (this.configSubscription !== undefined) { - this.configSubscription.unsubscribe(); - this.configSubscription = undefined; - } - } -} diff --git a/src/core/server/legacy/logging/appenders/__snapshots__/legacy_appender.test.ts.snap b/src/core/server/legacy/logging/appenders/__snapshots__/legacy_appender.test.ts.snap deleted file mode 100644 index 3c40362e8211e..0000000000000 --- a/src/core/server/legacy/logging/appenders/__snapshots__/legacy_appender.test.ts.snap +++ /dev/null @@ -1,142 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`\`append()\` correctly pushes records to legacy platform. 1`] = ` -Object { - "context": "context-1", - "level": LogLevel { - "id": "trace", - "value": 7, - }, - "message": "message-1", - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 2`] = ` -Object { - "context": "context-2", - "level": LogLevel { - "id": "debug", - "value": 6, - }, - "message": "message-2", - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 3`] = ` -Object { - "context": "context-3.sub-context-3", - "level": LogLevel { - "id": "info", - "value": 5, - }, - "message": "message-3", - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 4`] = ` -Object { - "context": "context-4.sub-context-4", - "level": LogLevel { - "id": "warn", - "value": 4, - }, - "message": "message-4", - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 5`] = ` -Object { - "context": "context-5", - "error": [Error: Some Error], - "level": LogLevel { - "id": "error", - "value": 3, - }, - "message": "message-5-with-error", - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 6`] = ` -Object { - "context": "context-6", - "level": LogLevel { - "id": "error", - "value": 3, - }, - "message": "message-6-with-message", - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 7`] = ` -Object { - "context": "context-7.sub-context-7.sub-sub-context-7", - "error": [Error: Some Fatal Error], - "level": LogLevel { - "id": "fatal", - "value": 2, - }, - "message": "message-7-with-error", - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 8`] = ` -Object { - "context": "context-8.sub-context-8.sub-sub-context-8", - "level": LogLevel { - "id": "fatal", - "value": 2, - }, - "message": "message-8-with-message", - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 9`] = ` -Object { - "context": "context-9.sub-context-9", - "level": LogLevel { - "id": "info", - "value": 5, - }, - "message": "message-9-with-message", - "meta": Object { - "someValue": 3, - }, - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; - -exports[`\`append()\` correctly pushes records to legacy platform. 10`] = ` -Object { - "context": "context-10.sub-context-10", - "level": LogLevel { - "id": "info", - "value": 5, - }, - "message": "message-10-with-message", - "meta": Object { - "tags": Array [ - "tag1", - "tag2", - ], - }, - "pid": Any, - "timestamp": 2012-02-01T11:22:33.044Z, -} -`; diff --git a/src/core/server/legacy/logging/appenders/legacy_appender.test.ts b/src/core/server/legacy/logging/appenders/legacy_appender.test.ts deleted file mode 100644 index 9213403d72d07..0000000000000 --- a/src/core/server/legacy/logging/appenders/legacy_appender.test.ts +++ /dev/null @@ -1,135 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -jest.mock('@kbn/legacy-logging'); - -import { LogRecord, LogLevel } from '../../../logging'; -import { LegacyLoggingServer } from '@kbn/legacy-logging'; -import { LegacyAppender } from './legacy_appender'; - -afterEach(() => (LegacyLoggingServer as any).mockClear()); - -test('`configSchema` creates correct schema.', () => { - const appenderSchema = LegacyAppender.configSchema; - const validConfig = { type: 'legacy-appender', legacyLoggingConfig: { verbose: true } }; - expect(appenderSchema.validate(validConfig)).toEqual({ - type: 'legacy-appender', - legacyLoggingConfig: { verbose: true }, - }); - - const wrongConfig = { type: 'not-legacy-appender' }; - expect(() => appenderSchema.validate(wrongConfig)).toThrow(); -}); - -test('`append()` correctly pushes records to legacy platform.', () => { - const timestamp = new Date(Date.UTC(2012, 1, 1, 11, 22, 33, 44)); - const records: LogRecord[] = [ - { - context: 'context-1', - level: LogLevel.Trace, - message: 'message-1', - timestamp, - pid: 5355, - }, - { - context: 'context-2', - level: LogLevel.Debug, - message: 'message-2', - timestamp, - pid: 5355, - }, - { - context: 'context-3.sub-context-3', - level: LogLevel.Info, - message: 'message-3', - timestamp, - pid: 5355, - }, - { - context: 'context-4.sub-context-4', - level: LogLevel.Warn, - message: 'message-4', - timestamp, - pid: 5355, - }, - { - context: 'context-5', - error: new Error('Some Error'), - level: LogLevel.Error, - message: 'message-5-with-error', - timestamp, - pid: 5355, - }, - { - context: 'context-6', - level: LogLevel.Error, - message: 'message-6-with-message', - timestamp, - pid: 5355, - }, - { - context: 'context-7.sub-context-7.sub-sub-context-7', - error: new Error('Some Fatal Error'), - level: LogLevel.Fatal, - message: 'message-7-with-error', - timestamp, - pid: 5355, - }, - { - context: 'context-8.sub-context-8.sub-sub-context-8', - level: LogLevel.Fatal, - message: 'message-8-with-message', - timestamp, - pid: 5355, - }, - { - context: 'context-9.sub-context-9', - level: LogLevel.Info, - message: 'message-9-with-message', - timestamp, - pid: 5355, - meta: { someValue: 3 }, - }, - { - context: 'context-10.sub-context-10', - level: LogLevel.Info, - message: 'message-10-with-message', - timestamp, - pid: 5355, - meta: { tags: ['tag1', 'tag2'] }, - }, - ]; - - const appender = new LegacyAppender({ verbose: true }); - for (const record of records) { - appender.append(record); - } - - const [mockLegacyLoggingServerInstance] = (LegacyLoggingServer as any).mock.instances; - expect(mockLegacyLoggingServerInstance.log.mock.calls).toHaveLength(records.length); - records.forEach((r, idx) => { - expect(mockLegacyLoggingServerInstance.log.mock.calls[idx][0]).toMatchSnapshot({ - pid: expect.any(Number), - }); - }); -}); - -test('legacy logging server is correctly created and disposed.', async () => { - const mockRawLegacyLoggingConfig = { verbose: true }; - const appender = new LegacyAppender(mockRawLegacyLoggingConfig); - - expect(LegacyLoggingServer).toHaveBeenCalledTimes(1); - expect(LegacyLoggingServer).toHaveBeenCalledWith(mockRawLegacyLoggingConfig); - - const [mockLegacyLoggingServerInstance] = (LegacyLoggingServer as any).mock.instances; - expect(mockLegacyLoggingServerInstance.stop).not.toHaveBeenCalled(); - - await appender.dispose(); - - expect(mockLegacyLoggingServerInstance.stop).toHaveBeenCalledTimes(1); -}); diff --git a/src/core/server/legacy/logging/appenders/legacy_appender.ts b/src/core/server/legacy/logging/appenders/legacy_appender.ts deleted file mode 100644 index 7e02d00c7b234..0000000000000 --- a/src/core/server/legacy/logging/appenders/legacy_appender.ts +++ /dev/null @@ -1,52 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { schema } from '@kbn/config-schema'; -import { LegacyLoggingServer } from '@kbn/legacy-logging'; -import { DisposableAppender, LogRecord } from '@kbn/logging'; - -export interface LegacyAppenderConfig { - type: 'legacy-appender'; - legacyLoggingConfig?: Record; -} - -/** - * Simple appender that just forwards `LogRecord` to the legacy KbnServer log. - * @internal - */ -export class LegacyAppender implements DisposableAppender { - public static configSchema = schema.object({ - type: schema.literal('legacy-appender'), - legacyLoggingConfig: schema.recordOf(schema.string(), schema.any()), - }); - - /** - * Sets {@link Appender.receiveAllLevels} because legacy does its own filtering based on the legacy logging - * configuration. - */ - public readonly receiveAllLevels = true; - - private readonly loggingServer: LegacyLoggingServer; - - constructor(legacyLoggingConfig: any) { - this.loggingServer = new LegacyLoggingServer(legacyLoggingConfig); - } - - /** - * Forwards `LogRecord` to the legacy platform that will layout and - * write record to the configured destination. - * @param record `LogRecord` instance to forward to. - */ - public append(record: LogRecord) { - this.loggingServer.log(record); - } - - public dispose() { - this.loggingServer.stop(); - } -} diff --git a/src/core/server/logging/README.mdx b/src/core/server/logging/README.mdx index 08e4ed34204c0..11437d1e8df20 100644 --- a/src/core/server/logging/README.mdx +++ b/src/core/server/logging/README.mdx @@ -562,11 +562,6 @@ The log will be less verbose with `warn` level for the `server` context name: ``` ### Logging config migration -Compatibility with the legacy logging system is assured until the end of the `v7` version. -All log messages handled by `root` context are forwarded to the legacy logging service using a `default` appender. If you re-write -root appenders, make sure that it contains `default` appender to provide backward compatibility. -**Note**: If you define an appender for a context name, the log messages for that specific context aren't handled by the -`root` context anymore and not forwarded to the legacy logging service. #### logging.dest By default logs in *stdout*. With new Kibana logging you can use pre-existing `console` appender or diff --git a/src/core/server/logging/appenders/appenders.test.ts b/src/core/server/logging/appenders/appenders.test.ts index bd32e4061049b..759fcb9546f09 100644 --- a/src/core/server/logging/appenders/appenders.test.ts +++ b/src/core/server/logging/appenders/appenders.test.ts @@ -9,7 +9,6 @@ import { mockCreateLayout } from './appenders.test.mocks'; import { ByteSizeValue } from '@kbn/config-schema'; -import { LegacyAppender } from '../../legacy/logging/appenders/legacy_appender'; import { Appenders } from './appenders'; import { ConsoleAppender } from './console/console_appender'; import { FileAppender } from './file/file_appender'; @@ -68,13 +67,6 @@ test('`create()` creates correct appender.', () => { }); expect(fileAppender).toBeInstanceOf(FileAppender); - const legacyAppender = Appenders.create({ - type: 'legacy-appender', - legacyLoggingConfig: { verbose: true }, - }); - - expect(legacyAppender).toBeInstanceOf(LegacyAppender); - const rollingFileAppender = Appenders.create({ type: 'rolling-file', fileName: 'path', diff --git a/src/core/server/logging/appenders/appenders.ts b/src/core/server/logging/appenders/appenders.ts index 88df355bd5ebe..3e867739aa1c7 100644 --- a/src/core/server/logging/appenders/appenders.ts +++ b/src/core/server/logging/appenders/appenders.ts @@ -10,10 +10,6 @@ import { schema } from '@kbn/config-schema'; import { assertNever } from '@kbn/std'; import { DisposableAppender } from '@kbn/logging'; -import { - LegacyAppender, - LegacyAppenderConfig, -} from '../../legacy/logging/appenders/legacy_appender'; import { Layouts } from '../layouts/layouts'; import { ConsoleAppender, ConsoleAppenderConfig } from './console/console_appender'; import { FileAppender, FileAppenderConfig } from './file/file_appender'; @@ -32,7 +28,6 @@ import { export const appendersSchema = schema.oneOf([ ConsoleAppender.configSchema, FileAppender.configSchema, - LegacyAppender.configSchema, RewriteAppender.configSchema, RollingFileAppender.configSchema, ]); @@ -41,7 +36,6 @@ export const appendersSchema = schema.oneOf([ export type AppenderConfigType = | ConsoleAppenderConfig | FileAppenderConfig - | LegacyAppenderConfig | RewriteAppenderConfig | RollingFileAppenderConfig; @@ -64,8 +58,6 @@ export class Appenders { return new RewriteAppender(config); case 'rolling-file': return new RollingFileAppender(config); - case 'legacy-appender': - return new LegacyAppender(config.legacyLoggingConfig); default: return assertNever(config); diff --git a/src/core/server/logging/integration_tests/logging.test.ts b/src/core/server/logging/integration_tests/logging.test.ts index ade10fc1c0257..ff681222c4f30 100644 --- a/src/core/server/logging/integration_tests/logging.test.ts +++ b/src/core/server/logging/integration_tests/logging.test.ts @@ -14,7 +14,6 @@ import { Subject } from 'rxjs'; function createRoot() { return kbnTestServer.createRoot({ logging: { - silent: true, // set "true" in kbnTestServer appenders: { 'test-console': { type: 'console', diff --git a/src/core/server/logging/integration_tests/rolling_file_appender.test.ts b/src/core/server/logging/integration_tests/rolling_file_appender.test.ts index 83533e29ad12e..dc6a01b80e951 100644 --- a/src/core/server/logging/integration_tests/rolling_file_appender.test.ts +++ b/src/core/server/logging/integration_tests/rolling_file_appender.test.ts @@ -19,7 +19,6 @@ const flush = async () => delay(flushDelay); function createRoot(appenderConfig: any) { return kbnTestServer.createRoot({ logging: { - silent: true, // set "true" in kbnTestServer appenders: { 'rolling-file': appenderConfig, }, diff --git a/src/core/server/logging/logging_config.test.ts b/src/core/server/logging/logging_config.test.ts index e0004ba992c17..41acd072b295d 100644 --- a/src/core/server/logging/logging_config.test.ts +++ b/src/core/server/logging/logging_config.test.ts @@ -9,35 +9,18 @@ import { LoggingConfig, config } from './logging_config'; test('`schema` creates correct schema with defaults.', () => { - expect(config.schema.validate({})).toMatchInlineSnapshot( - { json: expect.any(Boolean) }, // default value depends on TTY - ` + expect(config.schema.validate({})).toMatchInlineSnapshot(` Object { "appenders": Map {}, - "dest": "stdout", - "events": Object {}, - "filter": Object {}, - "json": Any, "loggers": Array [], - "quiet": false, "root": Object { "appenders": Array [ "default", ], "level": "info", }, - "rotate": Object { - "enabled": false, - "everyBytes": 10485760, - "keepFiles": 7, - "pollingInterval": 10000, - "usePolling": false, - }, - "silent": false, - "verbose": false, } - ` - ); + `); }); test('`schema` throws if `root` logger does not have appenders configured.', () => { @@ -52,16 +35,14 @@ test('`schema` throws if `root` logger does not have appenders configured.', () ); }); -test('`schema` throws if `root` logger does not have "default" appender configured.', () => { +test('`schema` does not throw if `root` logger does not have "default" appender configured.', () => { expect(() => config.schema.validate({ root: { appenders: ['console'], }, }) - ).toThrowErrorMatchingInlineSnapshot( - `"[root]: \\"default\\" appender required for migration period till the next major release"` - ); + ).not.toThrow(); }); test('`getParentLoggerContext()` returns correct parent context name.', () => { diff --git a/src/core/server/logging/logging_config.ts b/src/core/server/logging/logging_config.ts index f5b75d7bb739c..a04506ad9c0f6 100644 --- a/src/core/server/logging/logging_config.ts +++ b/src/core/server/logging/logging_config.ts @@ -7,7 +7,6 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; -import { legacyLoggingConfigSchema } from '@kbn/legacy-logging'; import { AppenderConfigType, Appenders } from './appenders/appenders'; // We need this helper for the types to be correct @@ -58,31 +57,23 @@ export const loggerSchema = schema.object({ /** @public */ export type LoggerConfigType = TypeOf; + export const config = { path: 'logging', - schema: legacyLoggingConfigSchema.extends({ + schema: schema.object({ appenders: schema.mapOf(schema.string(), Appenders.configSchema, { defaultValue: new Map(), }), loggers: schema.arrayOf(loggerSchema, { defaultValue: [], }), - root: schema.object( - { - appenders: schema.arrayOf(schema.string(), { - defaultValue: [DEFAULT_APPENDER_NAME], - minSize: 1, - }), - level: levelSchema, - }, - { - validate(rawConfig) { - if (!rawConfig.appenders.includes(DEFAULT_APPENDER_NAME)) { - return `"${DEFAULT_APPENDER_NAME}" appender required for migration period till the next major release`; - } - }, - } - ), + root: schema.object({ + appenders: schema.arrayOf(schema.string(), { + defaultValue: [DEFAULT_APPENDER_NAME], + minSize: 1, + }), + level: levelSchema, + }), }), }; diff --git a/src/core/server/logging/logging_system.test.ts b/src/core/server/logging/logging_system.test.ts index dd546d4e7eaca..ebe06326f499d 100644 --- a/src/core/server/logging/logging_system.test.ts +++ b/src/core/server/logging/logging_system.test.ts @@ -15,11 +15,6 @@ jest.mock('fs', () => ({ const dynamicProps = { process: { pid: expect.any(Number) } }; -jest.mock('@kbn/legacy-logging', () => ({ - ...(jest.requireActual('@kbn/legacy-logging') as any), - setupLoggingRotate: jest.fn().mockImplementation(() => Promise.resolve({})), -})); - const timestamp = new Date(Date.UTC(2012, 1, 1, 14, 33, 22, 11)); let mockConsoleLog: jest.SpyInstance; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 1ef845730e1f3..770f18d1f7e7a 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -71,12 +71,11 @@ export interface AppCategory { // Warning: (ae-forgotten-export) The symbol "ConsoleAppenderConfig" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "FileAppenderConfig" needs to be exported by the entry point index.d.ts -// Warning: (ae-forgotten-export) The symbol "LegacyAppenderConfig" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RewriteAppenderConfig" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RollingFileAppenderConfig" needs to be exported by the entry point index.d.ts // // @public (undocumented) -export type AppenderConfigType = ConsoleAppenderConfig | FileAppenderConfig | LegacyAppenderConfig | RewriteAppenderConfig | RollingFileAppenderConfig; +export type AppenderConfigType = ConsoleAppenderConfig | FileAppenderConfig | RewriteAppenderConfig | RollingFileAppenderConfig; // @public @deprecated export interface AsyncPlugin { diff --git a/src/core/server/server.test.mocks.ts b/src/core/server/server.test.mocks.ts index 47899043dc5a5..c4f420f75b5d1 100644 --- a/src/core/server/server.test.mocks.ts +++ b/src/core/server/server.test.mocks.ts @@ -7,32 +7,30 @@ */ import { httpServiceMock } from './http/http_service.mock'; + export const mockHttpService = httpServiceMock.create(); jest.doMock('./http/http_service', () => ({ HttpService: jest.fn(() => mockHttpService), })); import { pluginServiceMock } from './plugins/plugins_service.mock'; + export const mockPluginsService = pluginServiceMock.create(); jest.doMock('./plugins/plugins_service', () => ({ PluginsService: jest.fn(() => mockPluginsService), })); import { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock'; + export const mockElasticsearchService = elasticsearchServiceMock.create(); jest.doMock('./elasticsearch/elasticsearch_service', () => ({ ElasticsearchService: jest.fn(() => mockElasticsearchService), })); -import { legacyServiceMock } from './legacy/legacy_service.mock'; -export const mockLegacyService = legacyServiceMock.create(); -jest.mock('./legacy/legacy_service', () => ({ - LegacyService: jest.fn(() => mockLegacyService), -})); - const realKbnConfig = jest.requireActual('@kbn/config'); import { configServiceMock } from './config/mocks'; + export const mockConfigService = configServiceMock.create(); jest.doMock('@kbn/config', () => ({ ...realKbnConfig, @@ -40,18 +38,21 @@ jest.doMock('@kbn/config', () => ({ })); import { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; + export const mockSavedObjectsService = savedObjectsServiceMock.create(); jest.doMock('./saved_objects/saved_objects_service', () => ({ SavedObjectsService: jest.fn(() => mockSavedObjectsService), })); import { contextServiceMock } from './context/context_service.mock'; + export const mockContextService = contextServiceMock.create(); jest.doMock('./context/context_service', () => ({ ContextService: jest.fn(() => mockContextService), })); import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; + export const mockUiSettingsService = uiSettingsServiceMock.create(); jest.doMock('./ui_settings/ui_settings_service', () => ({ UiSettingsService: jest.fn(() => mockUiSettingsService), @@ -63,46 +64,54 @@ jest.doMock('./config/ensure_valid_configuration', () => ({ })); import { RenderingService, mockRenderingService } from './rendering/__mocks__/rendering_service'; + export { mockRenderingService }; jest.doMock('./rendering/rendering_service', () => ({ RenderingService })); import { environmentServiceMock } from './environment/environment_service.mock'; + export const mockEnvironmentService = environmentServiceMock.create(); jest.doMock('./environment/environment_service', () => ({ EnvironmentService: jest.fn(() => mockEnvironmentService), })); import { metricsServiceMock } from './metrics/metrics_service.mock'; + export const mockMetricsService = metricsServiceMock.create(); jest.doMock('./metrics/metrics_service', () => ({ MetricsService: jest.fn(() => mockMetricsService), })); import { statusServiceMock } from './status/status_service.mock'; + export const mockStatusService = statusServiceMock.create(); jest.doMock('./status/status_service', () => ({ StatusService: jest.fn(() => mockStatusService), })); import { loggingServiceMock } from './logging/logging_service.mock'; + export const mockLoggingService = loggingServiceMock.create(); jest.doMock('./logging/logging_service', () => ({ LoggingService: jest.fn(() => mockLoggingService), })); import { i18nServiceMock } from './i18n/i18n_service.mock'; + export const mockI18nService = i18nServiceMock.create(); jest.doMock('./i18n/i18n_service', () => ({ I18nService: jest.fn(() => mockI18nService), })); import { prebootServiceMock } from './preboot/preboot_service.mock'; + export const mockPrebootService = prebootServiceMock.create(); jest.doMock('./preboot/preboot_service', () => ({ PrebootService: jest.fn(() => mockPrebootService), })); import { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; + export const mockDeprecationService = deprecationsServiceMock.create(); jest.doMock('./deprecations/deprecations_service', () => ({ DeprecationsService: jest.fn(() => mockDeprecationService), diff --git a/src/core/server/server.test.ts b/src/core/server/server.test.ts index b27c8fa769c48..112693aae0279 100644 --- a/src/core/server/server.test.ts +++ b/src/core/server/server.test.ts @@ -9,7 +9,6 @@ import { mockElasticsearchService, mockHttpService, - mockLegacyService, mockPluginsService, mockConfigService, mockSavedObjectsService, @@ -95,7 +94,6 @@ test('sets up services on "setup"', async () => { expect(mockHttpService.setup).not.toHaveBeenCalled(); expect(mockElasticsearchService.setup).not.toHaveBeenCalled(); expect(mockPluginsService.setup).not.toHaveBeenCalled(); - expect(mockLegacyService.setup).not.toHaveBeenCalled(); expect(mockSavedObjectsService.setup).not.toHaveBeenCalled(); expect(mockUiSettingsService.setup).not.toHaveBeenCalled(); expect(mockRenderingService.setup).not.toHaveBeenCalled(); @@ -111,7 +109,6 @@ test('sets up services on "setup"', async () => { expect(mockHttpService.setup).toHaveBeenCalledTimes(1); expect(mockElasticsearchService.setup).toHaveBeenCalledTimes(1); expect(mockPluginsService.setup).toHaveBeenCalledTimes(1); - expect(mockLegacyService.setup).toHaveBeenCalledTimes(1); expect(mockSavedObjectsService.setup).toHaveBeenCalledTimes(1); expect(mockUiSettingsService.setup).toHaveBeenCalledTimes(1); expect(mockRenderingService.setup).toHaveBeenCalledTimes(1); @@ -199,7 +196,6 @@ test('stops services on "stop"', async () => { expect(mockHttpService.stop).not.toHaveBeenCalled(); expect(mockElasticsearchService.stop).not.toHaveBeenCalled(); expect(mockPluginsService.stop).not.toHaveBeenCalled(); - expect(mockLegacyService.stop).not.toHaveBeenCalled(); expect(mockSavedObjectsService.stop).not.toHaveBeenCalled(); expect(mockUiSettingsService.stop).not.toHaveBeenCalled(); expect(mockMetricsService.stop).not.toHaveBeenCalled(); @@ -211,7 +207,6 @@ test('stops services on "stop"', async () => { expect(mockHttpService.stop).toHaveBeenCalledTimes(1); expect(mockElasticsearchService.stop).toHaveBeenCalledTimes(1); expect(mockPluginsService.stop).toHaveBeenCalledTimes(1); - expect(mockLegacyService.stop).toHaveBeenCalledTimes(1); expect(mockSavedObjectsService.stop).toHaveBeenCalledTimes(1); expect(mockUiSettingsService.stop).toHaveBeenCalledTimes(1); expect(mockMetricsService.stop).toHaveBeenCalledTimes(1); diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 867446484a230..8b0714e899139 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -21,7 +21,6 @@ import { ElasticsearchService } from './elasticsearch'; import { HttpService } from './http'; import { HttpResourcesService } from './http_resources'; import { RenderingService } from './rendering'; -import { LegacyService } from './legacy'; import { Logger, LoggerFactory, LoggingService, ILoggingSystem } from './logging'; import { UiSettingsService } from './ui_settings'; import { PluginsService, config as pluginsConfig } from './plugins'; @@ -69,7 +68,6 @@ export class Server { private readonly elasticsearch: ElasticsearchService; private readonly http: HttpService; private readonly rendering: RenderingService; - private readonly legacy: LegacyService; private readonly log: Logger; private readonly plugins: PluginsService; private readonly savedObjects: SavedObjectsService; @@ -108,7 +106,6 @@ export class Server { this.http = new HttpService(core); this.rendering = new RenderingService(core); this.plugins = new PluginsService(core); - this.legacy = new LegacyService(core); this.elasticsearch = new ElasticsearchService(core); this.savedObjects = new SavedObjectsService(core); this.uiSettings = new UiSettingsService(core); @@ -286,10 +283,6 @@ export class Server { const pluginsSetup = await this.plugins.setup(coreSetup); this.#pluginsInitialized = pluginsSetup.initialized; - await this.legacy.setup({ - http: httpSetup, - }); - this.registerCoreContext(coreSetup); this.coreApp.setup(coreSetup, uiPlugins); @@ -348,7 +341,6 @@ export class Server { public async stop() { this.log.debug('stopping server'); - await this.legacy.stop(); await this.http.stop(); // HTTP server has to stop before savedObjects and ES clients are closed to be able to gracefully attempt to resolve any pending requests await this.plugins.stop(); await this.savedObjects.stop(); diff --git a/src/core/test_helpers/kbn_server.ts b/src/core/test_helpers/kbn_server.ts index 67bd6c7455d6d..58720be637e2f 100644 --- a/src/core/test_helpers/kbn_server.ts +++ b/src/core/test_helpers/kbn_server.ts @@ -32,7 +32,11 @@ const DEFAULTS_SETTINGS = { port: 0, xsrf: { disableProtection: true }, }, - logging: { silent: true }, + logging: { + root: { + level: 'off', + }, + }, plugins: {}, migrations: { skip: false }, }; @@ -45,7 +49,6 @@ export function createRootWithSettings( configs: [], cliArgs: { dev: false, - silent: false, watch: false, basePath: false, runExamples: false, diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index cee43fd85c90f..f671fa963079f 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -82,24 +82,13 @@ kibana_vars=( logging.appenders logging.appenders.console logging.appenders.file - logging.dest - logging.json logging.loggers logging.loggers.appenders logging.loggers.level logging.loggers.name - logging.quiet logging.root logging.root.appenders logging.root.level - logging.rotate.enabled - logging.rotate.everyBytes - logging.rotate.keepFiles - logging.rotate.pollingInterval - logging.rotate.usePolling - logging.silent - logging.useUTC - logging.verbose map.includeElasticMapsService map.proxyElasticMapsServiceInMaps map.regionmap diff --git a/src/plugins/kibana_usage_collection/server/collectors/config_usage/README.md b/src/plugins/kibana_usage_collection/server/collectors/config_usage/README.md index b476244e5082f..954b12dba00f7 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/config_usage/README.md +++ b/src/plugins/kibana_usage_collection/server/collectors/config_usage/README.md @@ -55,7 +55,6 @@ when setting an exact config or its parent path to `false`. "server.port": 5603, "server.basePath": "[redacted]", "server.rewriteBasePath": true, - "logging.json": false, "usageCollection.uiCounters.debug": true } } diff --git a/test/common/config.js b/test/common/config.js index eb110fad55ea8..b9ab24450ac82 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -28,7 +28,6 @@ export default function () { buildArgs: [], sourceArgs: ['--no-base-path', '--env.name=development'], serverArgs: [ - '--logging.json=false', `--server.port=${kbnTestConfig.getPort()}`, '--status.allowAnonymous=true', // We shouldn't embed credentials into the URL since Kibana requests to Elasticsearch should diff --git a/test/server_integration/http/platform/config.status.ts b/test/server_integration/http/platform/config.status.ts index 8cc76c901f47c..20ffc917f8244 100644 --- a/test/server_integration/http/platform/config.status.ts +++ b/test/server_integration/http/platform/config.status.ts @@ -51,7 +51,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { runOptions: { ...httpConfig.get('kbnTestServer.runOptions'), // Don't wait for Kibana to be completely ready so that we can test the status timeouts - wait: /\[Kibana\]\[http\] http server running/, + wait: /Kibana is now unavailable/, }, }, }; diff --git a/x-pack/plugins/security/server/config.test.ts b/x-pack/plugins/security/server/config.test.ts index 3be565d59a11f..98f11d56853b2 100644 --- a/x-pack/plugins/security/server/config.test.ts +++ b/x-pack/plugins/security/server/config.test.ts @@ -1729,7 +1729,7 @@ describe('createConfig()', () => { }, }, }) - ).toThrow('[audit.appender.2.type]: expected value to equal [legacy-appender]'); + ).toThrow('[audit.appender.1.layout]: expected at least one defined value but got [undefined]'); }); it('rejects an ignore_filter when no appender is configured', () => { diff --git a/yarn.lock b/yarn.lock index 416d9c6b8ba5e..9f6ccfffb8113 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2404,15 +2404,6 @@ async-retry "^1.2.3" strip-ansi "^5.2.0" -"@elastic/good@^9.0.1-kibana3": - version "9.0.1-kibana3" - resolved "https://registry.yarnpkg.com/@elastic/good/-/good-9.0.1-kibana3.tgz#a70c2b30cbb4f44d1cf4a464562e0680322eac9b" - integrity sha512-UtPKr0TmlkL1abJfO7eEVUTqXWzLKjMkz+65FvxU/Ub9kMAr4No8wHLRfDHFzBkWoDIbDWygwld011WzUnea1Q== - dependencies: - "@hapi/hoek" "9.x.x" - "@hapi/oppsy" "3.x.x" - "@hapi/validate" "1.x.x" - "@elastic/makelogs@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@elastic/makelogs/-/makelogs-6.0.0.tgz#d6d74d5d0f020123c54160370d49ca5e0aab1fe1" @@ -2897,14 +2888,6 @@ resolved "https://registry.yarnpkg.com/@hapi/file/-/file-2.0.0.tgz#2ecda37d1ae9d3078a67c13b7da86e8c3237dfb9" integrity sha512-WSrlgpvEqgPWkI18kkGELEZfXr0bYLtr16iIN4Krh9sRnzBZN6nnWxHFxtsnP684wueEySBbXPDg/WfA9xJdBQ== -"@hapi/good-squeeze@6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@hapi/good-squeeze/-/good-squeeze-6.0.0.tgz#bb72d6869cd7398b615a6b7270f630dc4f76aebf" - integrity sha512-UgHAF9Lm8fJPzgf2HymtowOwNc1+IL+p08YTVR+XA4d8nmyE1t9x3RLA4riqldnOKHkVqGakJ1jGqUG7jk77Cg== - dependencies: - "@hapi/hoek" "9.x.x" - fast-safe-stringify "2.x.x" - "@hapi/h2o2@^9.1.0": version "9.1.0" resolved "https://registry.yarnpkg.com/@hapi/h2o2/-/h2o2-9.1.0.tgz#b223f4978b6f2b0d7d9db10a84a567606c4c3551" @@ -2992,13 +2975,6 @@ "@hapi/hoek" "^9.0.4" "@hapi/vise" "^4.0.0" -"@hapi/oppsy@3.x.x": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@hapi/oppsy/-/oppsy-3.0.0.tgz#1ae397e200e86d0aa41055f103238ed8652947ca" - integrity sha512-0kfUEAqIi21GzFVK2snMO07znMEBiXb+/pOx1dmgOO9TuvFstcfmHU5i56aDfiFP2DM5WzQCU2UWc2gK1lMDhQ== - dependencies: - "@hapi/hoek" "9.x.x" - "@hapi/pez@^5.0.1": version "5.0.3" resolved "https://registry.yarnpkg.com/@hapi/pez/-/pez-5.0.3.tgz#b75446e6fef8cbb16816573ab7da1b0522e7a2a1" @@ -3750,10 +3726,6 @@ version "0.0.0" uid "" -"@kbn/legacy-logging@link:bazel-bin/packages/kbn-legacy-logging": - version "0.0.0" - uid "" - "@kbn/logging@link:bazel-bin/packages/kbn-logging": version "0.0.0" uid "" @@ -14493,7 +14465,7 @@ fast-redact@^3.0.0: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.0.0.tgz#ac2f9e36c9f4976f5db9fb18c6ffbaf308cf316d" integrity sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w== -fast-safe-stringify@2.x.x, fast-safe-stringify@^2.0.4, fast-safe-stringify@^2.0.7: +fast-safe-stringify@^2.0.4, fast-safe-stringify@^2.0.7: version "2.0.8" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz#dc2af48c46cf712b683e849b2bbd446b32de936f" integrity sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag== From 699de6b6039120c8665355310c36164b253f1244 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 5 Oct 2021 13:34:44 +0200 Subject: [PATCH 95/98] [Security Solution] Minimizes the number of environment variables used in Cypress (#113854) * cleans parameters * updates readme Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../security_solution/cypress/README.md | 4 +- .../security_solution/cypress/tasks/login.ts | 18 +++--- .../test/security_solution_cypress/runner.ts | 59 +++---------------- 3 files changed, 21 insertions(+), 60 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/README.md b/x-pack/plugins/security_solution/cypress/README.md index d70011f864860..b500091aacc2d 100644 --- a/x-pack/plugins/security_solution/cypress/README.md +++ b/x-pack/plugins/security_solution/cypress/README.md @@ -207,7 +207,7 @@ node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solut # launch the cypress test runner with overridden environment variables cd x-pack/plugins/security_solution -CYPRESS_base_url=http(s)://:@ CYPRESS_ELASTICSEARCH_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_USERNAME= CYPRESS_ELASTICSEARCH_PASSWORD= CYPRESS_protocol= CYPRESS_hostname= CYPRESS_configport= CYPRESS_KIBANA_URL= yarn cypress:run +CYPRESS_BASE_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_USERNAME= CYPRESS_ELASTICSEARCH_PASSWORD= yarn cypress:run ``` #### Custom Target + Headless (Firefox) @@ -225,7 +225,7 @@ node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solut # launch the cypress test runner with overridden environment variables cd x-pack/plugins/security_solution -CYPRESS_base_url=http(s)://:@ CYPRESS_ELASTICSEARCH_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_USERNAME= CYPRESS_ELASTICSEARCH_PASSWORD= CYPRESS_protocol= CYPRESS_hostname= CYPRESS_configport= CYPRESS_KIBANA_URL= yarn cypress:run:firefox +CYPRESS_BASE_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_URL=http(s)://:@ CYPRESS_ELASTICSEARCH_USERNAME= CYPRESS_ELASTICSEARCH_PASSWORD= yarn cypress:run:firefox ``` #### CCS Custom Target + Headless diff --git a/x-pack/plugins/security_solution/cypress/tasks/login.ts b/x-pack/plugins/security_solution/cypress/tasks/login.ts index 243bfd113bfd2..5a935702131d6 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/login.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/login.ts @@ -56,13 +56,15 @@ const LOGIN_API_ENDPOINT = '/internal/security/login'; * @param route string route to visit */ export const getUrlWithRoute = (role: ROLES, route: string) => { + const url = Cypress.config().baseUrl; + const kibana = new URL(url!); const theUrl = `${Url.format({ auth: `${role}:changeme`, username: role, password: 'changeme', - protocol: Cypress.env('protocol'), - hostname: Cypress.env('hostname'), - port: Cypress.env('configport'), + protocol: kibana.protocol.replace(':', ''), + hostname: kibana.hostname, + port: kibana.port, } as UrlObject)}${route.startsWith('/') ? '' : '/'}${route}`; cy.log(`origin: ${theUrl}`); return theUrl; @@ -80,11 +82,13 @@ interface User { * @param route string route to visit */ export const constructUrlWithUser = (user: User, route: string) => { - const hostname = Cypress.env('hostname'); + const url = Cypress.config().baseUrl; + const kibana = new URL(url!); + const hostname = kibana.hostname; const username = user.username; const password = user.password; - const protocol = Cypress.env('protocol'); - const port = Cypress.env('configport'); + const protocol = kibana.protocol.replace(':', ''); + const port = kibana.port; const path = `${route.startsWith('/') ? '' : '/'}${route}`; const strUrl = `${protocol}://${username}:${password}@${hostname}:${port}${path}`; @@ -98,7 +102,7 @@ export const getCurlScriptEnvVars = () => ({ ELASTICSEARCH_URL: Cypress.env('ELASTICSEARCH_URL'), ELASTICSEARCH_USERNAME: Cypress.env('ELASTICSEARCH_USERNAME'), ELASTICSEARCH_PASSWORD: Cypress.env('ELASTICSEARCH_PASSWORD'), - KIBANA_URL: Cypress.env('KIBANA_URL'), + KIBANA_URL: Cypress.config().baseUrl, }); export const postRoleAndUser = (role: ROLES) => { diff --git a/x-pack/test/security_solution_cypress/runner.ts b/x-pack/test/security_solution_cypress/runner.ts index f93e20ec382cd..4283b85af0c17 100644 --- a/x-pack/test/security_solution_cypress/runner.ts +++ b/x-pack/test/security_solution_cypress/runner.ts @@ -26,22 +26,10 @@ export async function SecuritySolutionCypressCliTestRunner({ getService }: FtrPr cwd: resolve(__dirname, '../../plugins/security_solution'), env: { FORCE_COLOR: '1', - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_baseUrl: Url.format(config.get('servers.kibana')), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_protocol: config.get('servers.kibana.protocol'), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_hostname: config.get('servers.kibana.hostname'), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_configport: config.get('servers.kibana.port'), + CYPRESS_BASE_URL: Url.format(config.get('servers.kibana')), CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')), CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'), CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'), - CYPRESS_KIBANA_URL: Url.format({ - protocol: config.get('servers.kibana.protocol'), - hostname: config.get('servers.kibana.hostname'), - port: config.get('servers.kibana.port'), - }), ...process.env, }, wait: true, @@ -65,22 +53,10 @@ export async function SecuritySolutionCypressCliFirefoxTestRunner({ cwd: resolve(__dirname, '../../plugins/security_solution'), env: { FORCE_COLOR: '1', - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_baseUrl: Url.format(config.get('servers.kibana')), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_protocol: config.get('servers.kibana.protocol'), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_hostname: config.get('servers.kibana.hostname'), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_configport: config.get('servers.kibana.port'), + CYPRESS_BASE_URL: Url.format(config.get('servers.kibana')), CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')), CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'), CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'), - CYPRESS_KIBANA_URL: Url.format({ - protocol: config.get('servers.kibana.protocol'), - hostname: config.get('servers.kibana.hostname'), - port: config.get('servers.kibana.port'), - }), ...process.env, }, wait: true, @@ -126,22 +102,10 @@ export async function SecuritySolutionCypressVisualTestRunner({ getService }: Ft cwd: resolve(__dirname, '../../plugins/security_solution'), env: { FORCE_COLOR: '1', - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_baseUrl: Url.format(config.get('servers.kibana')), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_protocol: config.get('servers.kibana.protocol'), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_hostname: config.get('servers.kibana.hostname'), - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_configport: config.get('servers.kibana.port'), + CYPRESS_BASE_URL: Url.format(config.get('servers.kibana')), CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')), CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'), CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'), - CYPRESS_KIBANA_URL: Url.format({ - protocol: config.get('servers.kibana.protocol'), - hostname: config.get('servers.kibana.hostname'), - port: config.get('servers.kibana.port'), - }), ...process.env, }, wait: true, @@ -153,6 +117,7 @@ export async function SecuritySolutionCypressUpgradeCliTestRunner({ getService, }: FtrProviderContext) { const log = getService('log'); + const config = getService('config'); await withProcRunner(log, async (procs) => { await procs.run('cypress', { @@ -161,18 +126,10 @@ export async function SecuritySolutionCypressUpgradeCliTestRunner({ cwd: resolve(__dirname, '../../plugins/security_solution'), env: { FORCE_COLOR: '1', - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_baseUrl: process.env.TEST_KIBANA_URL, - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_protocol: process.env.TEST_KIBANA_PROTOCOL, - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_hostname: process.env.TEST_KIBANA_HOSTNAME, - // eslint-disable-next-line @typescript-eslint/naming-convention - CYPRESS_configport: process.env.TEST_KIBANA_PORT, - CYPRESS_ELASTICSEARCH_URL: process.env.TEST_ES_URL, - CYPRESS_ELASTICSEARCH_USERNAME: process.env.TEST_ES_USER, - CYPRESS_ELASTICSEARCH_PASSWORD: process.env.TEST_ES_PASS, - CYPRESS_KIBANA_URL: process.env.TEST_KIBANA_URL, + CYPRESS_BASE_URL: Url.format(config.get('servers.kibana')), + CYPRESS_ELASTICSEARCH_URL: Url.format(config.get('servers.elasticsearch')), + CYPRESS_ELASTICSEARCH_USERNAME: config.get('servers.elasticsearch.username'), + CYPRESS_ELASTICSEARCH_PASSWORD: config.get('servers.elasticsearch.password'), ...process.env, }, wait: true, From 79f841e5d39989107d8ac93aec6a905ef60b857b Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Tue, 5 Oct 2021 13:38:51 +0200 Subject: [PATCH 96/98] [APM] Display all properties by default in flyout (#113221) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/core/types/elasticsearch/search.ts | 2 +- .../elasticsearch_fieldnames.test.ts.snap | 6 + .../apm/common/elasticsearch_fieldnames.ts | 1 + x-pack/plugins/apm/common/processor_event.ts | 9 + .../components/shared/KeyValueTable/index.tsx | 38 ++-- .../ErrorMetadata/ErrorMetadata.test.tsx | 139 -------------- .../MetadataTable/ErrorMetadata/index.tsx | 34 +++- .../MetadataTable/ErrorMetadata/sections.ts | 39 ---- .../MetadataTable/MetadataTable.test.tsx | 25 +-- .../shared/MetadataTable/Section.test.tsx | 2 +- .../shared/MetadataTable/Section.tsx | 16 +- .../SpanMetadata/SpanMetadata.test.tsx | 107 ----------- .../MetadataTable/SpanMetadata/index.tsx | 34 +++- .../MetadataTable/SpanMetadata/sections.ts | 29 --- .../TransactionMetadata.test.tsx | 164 ----------------- .../TransactionMetadata/index.tsx | 33 +++- .../TransactionMetadata/sections.ts | 47 ----- .../shared/MetadataTable/helper.test.ts | 69 +++---- .../components/shared/MetadataTable/helper.ts | 84 +++++---- .../components/shared/MetadataTable/index.tsx | 18 +- .../shared/MetadataTable/sections.ts | 173 ------------------ .../components/shared/MetadataTable/types.ts | 13 ++ .../lib/event_metadata/get_event_metadata.ts | 66 +++++++ .../apm/server/routes/event_metadata.ts | 44 +++++ .../get_global_apm_server_route_repository.ts | 4 +- .../translations/translations/ja-JP.json | 18 -- .../translations/translations/zh-CN.json | 18 -- .../test/apm_api_integration/tests/index.ts | 4 + .../tests/metadata/event_metadata.ts | 129 +++++++++++++ 29 files changed, 505 insertions(+), 860 deletions(-) delete mode 100644 x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/ErrorMetadata.test.tsx delete mode 100644 x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts delete mode 100644 x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/SpanMetadata.test.tsx delete mode 100644 x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts delete mode 100644 x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/TransactionMetadata.test.tsx delete mode 100644 x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts delete mode 100644 x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts create mode 100644 x-pack/plugins/apm/public/components/shared/MetadataTable/types.ts create mode 100644 x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts create mode 100644 x-pack/plugins/apm/server/routes/event_metadata.ts create mode 100644 x-pack/test/apm_api_integration/tests/metadata/event_metadata.ts diff --git a/src/core/types/elasticsearch/search.ts b/src/core/types/elasticsearch/search.ts index 88d6cda3777dd..a54f5f3758ce3 100644 --- a/src/core/types/elasticsearch/search.ts +++ b/src/core/types/elasticsearch/search.ts @@ -48,7 +48,7 @@ type ValueTypeOfField = T extends Record type MaybeArray = T | T[]; -type Fields = Exclude['body']['fields'], undefined>; +type Fields = Required['body']>['fields']; type DocValueFields = MaybeArray; export type SearchHit< diff --git a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap index c4658ae2ac22c..2d1433324858b 100644 --- a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap +++ b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap @@ -53,6 +53,8 @@ exports[`Error ERROR_EXC_TYPE 1`] = `undefined`; exports[`Error ERROR_GROUP_ID 1`] = `"grouping key"`; +exports[`Error ERROR_ID 1`] = `"error id"`; + exports[`Error ERROR_LOG_LEVEL 1`] = `undefined`; exports[`Error ERROR_LOG_MESSAGE 1`] = `undefined`; @@ -298,6 +300,8 @@ exports[`Span ERROR_EXC_TYPE 1`] = `undefined`; exports[`Span ERROR_GROUP_ID 1`] = `undefined`; +exports[`Span ERROR_ID 1`] = `undefined`; + exports[`Span ERROR_LOG_LEVEL 1`] = `undefined`; exports[`Span ERROR_LOG_MESSAGE 1`] = `undefined`; @@ -535,6 +539,8 @@ exports[`Transaction ERROR_EXC_TYPE 1`] = `undefined`; exports[`Transaction ERROR_GROUP_ID 1`] = `undefined`; +exports[`Transaction ERROR_ID 1`] = `undefined`; + exports[`Transaction ERROR_LOG_LEVEL 1`] = `undefined`; exports[`Transaction ERROR_LOG_MESSAGE 1`] = `undefined`; diff --git a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts index d1f07c28bc808..4a4cad5454c4b 100644 --- a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts +++ b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts @@ -78,6 +78,7 @@ export const SPAN_DESTINATION_SERVICE_RESPONSE_TIME_SUM = // Parent ID for a transaction or span export const PARENT_ID = 'parent.id'; +export const ERROR_ID = 'error.id'; export const ERROR_GROUP_ID = 'error.grouping_key'; export const ERROR_CULPRIT = 'error.culprit'; export const ERROR_LOG_LEVEL = 'error.log.level'; diff --git a/x-pack/plugins/apm/common/processor_event.ts b/x-pack/plugins/apm/common/processor_event.ts index 57705e7ed4ce0..fe0d9abfa0e51 100644 --- a/x-pack/plugins/apm/common/processor_event.ts +++ b/x-pack/plugins/apm/common/processor_event.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import * as t from 'io-ts'; export enum ProcessorEvent { transaction = 'transaction', @@ -12,6 +13,14 @@ export enum ProcessorEvent { span = 'span', profile = 'profile', } + +export const processorEventRt = t.union([ + t.literal(ProcessorEvent.transaction), + t.literal(ProcessorEvent.error), + t.literal(ProcessorEvent.metric), + t.literal(ProcessorEvent.span), + t.literal(ProcessorEvent.profile), +]); /** * Processor events that are searchable in the UI via the query bar. * diff --git a/x-pack/plugins/apm/public/components/shared/KeyValueTable/index.tsx b/x-pack/plugins/apm/public/components/shared/KeyValueTable/index.tsx index 13aa3696eda42..e9525728bc3c5 100644 --- a/x-pack/plugins/apm/public/components/shared/KeyValueTable/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/KeyValueTable/index.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { castArray } from 'lodash'; import React, { TableHTMLAttributes } from 'react'; import { EuiTable, @@ -26,16 +26,32 @@ export function KeyValueTable({ return ( - {keyValuePairs.map(({ key, value }) => ( - - - {key} - - - - - - ))} + {keyValuePairs.map(({ key, value }) => { + const asArray = castArray(value); + const valueList = + asArray.length <= 1 ? ( + + ) : ( +
      + {asArray.map((val, index) => ( +
    • + +
    • + ))} +
    + ); + + return ( + + + {key} + + + {valueList} + + + ); + })}
    ); diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/ErrorMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/ErrorMetadata.test.tsx deleted file mode 100644 index f936941923e41..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/ErrorMetadata.test.tsx +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { render } from '@testing-library/react'; -import React, { ReactNode } from 'react'; -import { MemoryRouter } from 'react-router-dom'; -import { ErrorMetadata } from '.'; -import { APMError } from '../../../../../typings/es_schemas/ui/apm_error'; -import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; -import { - expectTextsInDocument, - expectTextsNotInDocument, -} from '../../../../utils/testHelpers'; - -function Wrapper({ children }: { children?: ReactNode }) { - return ( - - {children} - - ); -} - -const renderOptions = { - wrapper: Wrapper, -}; - -function getError() { - return { - labels: { someKey: 'labels value' }, - http: { someKey: 'http value' }, - host: { someKey: 'host value' }, - container: { someKey: 'container value' }, - service: { someKey: 'service value' }, - process: { someKey: 'process value' }, - agent: { someKey: 'agent value' }, - url: { someKey: 'url value' }, - user: { someKey: 'user value' }, - notIncluded: 'not included value', - error: { - id: '7efbc7056b746fcb', - notIncluded: 'error not included value', - custom: { - someKey: 'custom value', - }, - }, - } as unknown as APMError; -} - -describe('ErrorMetadata', () => { - it('should render a error with all sections', () => { - const error = getError(); - const output = render(, renderOptions); - - // sections - expectTextsInDocument(output, [ - 'Labels', - 'HTTP', - 'Host', - 'Container', - 'Service', - 'Process', - 'Agent', - 'URL', - 'User', - 'Custom', - ]); - }); - - it('should render a error with all included dot notation keys', () => { - const error = getError(); - const output = render(, renderOptions); - - // included keys - expectTextsInDocument(output, [ - 'labels.someKey', - 'http.someKey', - 'host.someKey', - 'container.someKey', - 'service.someKey', - 'process.someKey', - 'agent.someKey', - 'url.someKey', - 'user.someKey', - 'error.custom.someKey', - ]); - - // excluded keys - expectTextsNotInDocument(output, ['notIncluded', 'error.notIncluded']); - }); - - it('should render a error with all included values', () => { - const error = getError(); - const output = render(, renderOptions); - - // included values - expectTextsInDocument(output, [ - 'labels value', - 'http value', - 'host value', - 'container value', - 'service value', - 'process value', - 'agent value', - 'url value', - 'user value', - 'custom value', - ]); - - // excluded values - expectTextsNotInDocument(output, [ - 'not included value', - 'error not included value', - ]); - }); - - it('should render a error with only the required sections', () => { - const error = {} as APMError; - const output = render(, renderOptions); - - // required sections should be found - expectTextsInDocument(output, ['Labels', 'User']); - - // optional sections should NOT be found - expectTextsNotInDocument(output, [ - 'HTTP', - 'Host', - 'Container', - 'Service', - 'Process', - 'Agent', - 'URL', - 'Custom', - ]); - }); -}); diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx index 196a8706d5132..f6ffc34ecee02 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx @@ -6,19 +6,41 @@ */ import React, { useMemo } from 'react'; -import { ERROR_METADATA_SECTIONS } from './sections'; import { APMError } from '../../../../../typings/es_schemas/ui/apm_error'; -import { getSectionsWithRows } from '../helper'; +import { getSectionsFromFields } from '../helper'; import { MetadataTable } from '..'; +import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; +import { ProcessorEvent } from '../../../../../common/processor_event'; interface Props { error: APMError; } export function ErrorMetadata({ error }: Props) { - const sectionsWithRows = useMemo( - () => getSectionsWithRows(ERROR_METADATA_SECTIONS, error), - [error] + const { data: errorEvent, status } = useFetcher( + (callApmApi) => { + return callApmApi({ + endpoint: 'GET /api/apm/event_metadata/{processorEvent}/{id}', + params: { + path: { + processorEvent: ProcessorEvent.error, + id: error.error.id, + }, + }, + }); + }, + [error.error.id] + ); + + const sections = useMemo( + () => getSectionsFromFields(errorEvent?.metadata || {}), + [errorEvent?.metadata] + ); + + return ( + ); - return ; } diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts deleted file mode 100644 index 28a64ac36660e..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - Section, - ERROR, - LABELS, - HTTP, - HOST, - CONTAINER, - SERVICE, - PROCESS, - AGENT, - URL, - USER, - CUSTOM_ERROR, - TRACE, - TRANSACTION, -} from '../sections'; - -export const ERROR_METADATA_SECTIONS: Section[] = [ - { ...LABELS, required: true }, - TRACE, - TRANSACTION, - ERROR, - HTTP, - HOST, - CONTAINER, - SERVICE, - PROCESS, - AGENT, - URL, - { ...USER, required: true }, - CUSTOM_ERROR, -]; diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/MetadataTable.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/MetadataTable.test.tsx index 7ccde6a9a74d6..5d5976866ba24 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/MetadataTable.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/MetadataTable.test.tsx @@ -11,7 +11,7 @@ import { MemoryRouter } from 'react-router-dom'; import { MetadataTable } from '.'; import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context'; import { expectTextsInDocument } from '../../../utils/testHelpers'; -import { SectionsWithRows } from './helper'; +import type { SectionDescriptor } from './types'; function Wrapper({ children }: { children?: ReactNode }) { return ( @@ -27,21 +27,20 @@ const renderOptions = { describe('MetadataTable', () => { it('shows sections', () => { - const sectionsWithRows = [ - { key: 'foo', label: 'Foo', required: true }, + const sections: SectionDescriptor[] = [ + { key: 'foo', label: 'Foo', required: true, properties: [] }, { key: 'bar', label: 'Bar', required: false, - properties: ['props.A', 'props.B'], - rows: [ - { key: 'props.A', value: 'A' }, - { key: 'props.B', value: 'B' }, + properties: [ + { field: 'props.A', value: ['A'] }, + { field: 'props.B', value: ['B'] }, ], }, - ] as unknown as SectionsWithRows; + ]; const output = render( - , + , renderOptions ); expectTextsInDocument(output, [ @@ -56,15 +55,17 @@ describe('MetadataTable', () => { }); describe('required sections', () => { it('shows "empty state message" if no data is available', () => { - const sectionsWithRows = [ + const sectionsWithRows: SectionDescriptor[] = [ { key: 'foo', label: 'Foo', required: true, + properties: [], }, - ] as unknown as SectionsWithRows; + ]; + const output = render( - , + , renderOptions ); expectTextsInDocument(output, ['Foo', 'No data available']); diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/Section.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/Section.test.tsx index d44464e2160d3..ed816b1c7a337 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/Section.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/Section.test.tsx @@ -12,7 +12,7 @@ import { expectTextsInDocument } from '../../../utils/testHelpers'; describe('Section', () => { it('shows "empty state message" if no data is available', () => { - const component = render(
    ); + const component = render(
    ); expectTextsInDocument(component, ['No data available']); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/Section.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/Section.tsx index ff86083b8612d..03ae237f470c3 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/Section.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/Section.tsx @@ -10,15 +10,21 @@ import { isEmpty } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiText } from '@elastic/eui'; import { KeyValueTable } from '../KeyValueTable'; -import { KeyValuePair } from '../../../utils/flattenObject'; interface Props { - keyValuePairs: KeyValuePair[]; + properties: Array<{ field: string; value: string[] | number[] }>; } -export function Section({ keyValuePairs }: Props) { - if (!isEmpty(keyValuePairs)) { - return ; +export function Section({ properties }: Props) { + if (!isEmpty(properties)) { + return ( + ({ + key: property.field, + value: property.value, + }))} + /> + ); } return ( diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/SpanMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/SpanMetadata.test.tsx deleted file mode 100644 index 46eaba1e9e11d..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/SpanMetadata.test.tsx +++ /dev/null @@ -1,107 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { render } from '@testing-library/react'; -import React, { ReactNode } from 'react'; -import { MemoryRouter } from 'react-router-dom'; -import { SpanMetadata } from '.'; -import { Span } from '../../../../../typings/es_schemas/ui/span'; -import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; -import { - expectTextsInDocument, - expectTextsNotInDocument, -} from '../../../../utils/testHelpers'; - -function Wrapper({ children }: { children?: ReactNode }) { - return ( - - {children} - - ); -} - -const renderOptions = { - wrapper: Wrapper, -}; - -describe('SpanMetadata', () => { - describe('render', () => { - it('renders', () => { - const span = { - agent: { - ephemeral_id: 'ed8e3a4f-21d2-4a1f-bbc7-fa2064d94225', - name: 'java', - version: '1.9.1-SNAPSHOT', - }, - service: { - name: 'opbeans-java', - }, - span: { - id: '7efbc7056b746fcb', - message: { - age: { ms: 1577958057123 }, - queue: { name: 'queue name' }, - }, - }, - } as unknown as Span; - const output = render(, renderOptions); - expectTextsInDocument(output, ['Service', 'Agent', 'Message']); - }); - }); - describe('when a span is presented', () => { - it('renders the span', () => { - const span = { - agent: { - ephemeral_id: 'ed8e3a4f-21d2-4a1f-bbc7-fa2064d94225', - name: 'java', - version: '1.9.1-SNAPSHOT', - }, - service: { - name: 'opbeans-java', - }, - span: { - id: '7efbc7056b746fcb', - http: { - response: { status_code: 200 }, - }, - subtype: 'http', - type: 'external', - message: { - age: { ms: 1577958057123 }, - queue: { name: 'queue name' }, - }, - }, - } as unknown as Span; - const output = render(, renderOptions); - expectTextsInDocument(output, ['Service', 'Agent', 'Span', 'Message']); - }); - }); - describe('when there is no id inside span', () => { - it('does not show the section', () => { - const span = { - agent: { - ephemeral_id: 'ed8e3a4f-21d2-4a1f-bbc7-fa2064d94225', - name: 'java', - version: '1.9.1-SNAPSHOT', - }, - service: { - name: 'opbeans-java', - }, - span: { - http: { - response: { status_code: 200 }, - }, - subtype: 'http', - type: 'external', - }, - } as unknown as Span; - const output = render(, renderOptions); - expectTextsInDocument(output, ['Service', 'Agent']); - expectTextsNotInDocument(output, ['Span', 'Message']); - }); - }); -}); diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/index.tsx index feefcea9d38a0..bf5702b4acf3e 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/index.tsx @@ -6,19 +6,41 @@ */ import React, { useMemo } from 'react'; -import { SPAN_METADATA_SECTIONS } from './sections'; import { Span } from '../../../../../typings/es_schemas/ui/span'; -import { getSectionsWithRows } from '../helper'; +import { getSectionsFromFields } from '../helper'; import { MetadataTable } from '..'; +import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; +import { ProcessorEvent } from '../../../../../common/processor_event'; interface Props { span: Span; } export function SpanMetadata({ span }: Props) { - const sectionsWithRows = useMemo( - () => getSectionsWithRows(SPAN_METADATA_SECTIONS, span), - [span] + const { data: spanEvent, status } = useFetcher( + (callApmApi) => { + return callApmApi({ + endpoint: 'GET /api/apm/event_metadata/{processorEvent}/{id}', + params: { + path: { + processorEvent: ProcessorEvent.span, + id: span.span.id, + }, + }, + }); + }, + [span.span.id] + ); + + const sections = useMemo( + () => getSectionsFromFields(spanEvent?.metadata || {}), + [spanEvent?.metadata] + ); + + return ( + ); - return ; } diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts deleted file mode 100644 index f19aef8e0bd8a..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts +++ /dev/null @@ -1,29 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - Section, - AGENT, - SERVICE, - SPAN, - LABELS, - EVENT, - TRANSACTION, - TRACE, - MESSAGE_SPAN, -} from '../sections'; - -export const SPAN_METADATA_SECTIONS: Section[] = [ - LABELS, - TRACE, - TRANSACTION, - EVENT, - SPAN, - SERVICE, - MESSAGE_SPAN, - AGENT, -]; diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/TransactionMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/TransactionMetadata.test.tsx deleted file mode 100644 index 08253f04777d9..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/TransactionMetadata.test.tsx +++ /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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { render } from '@testing-library/react'; -import React, { ReactNode } from 'react'; -import { MemoryRouter } from 'react-router-dom'; -import { TransactionMetadata } from '.'; -import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; -import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; -import { - expectTextsInDocument, - expectTextsNotInDocument, -} from '../../../../utils/testHelpers'; - -function Wrapper({ children }: { children?: ReactNode }) { - return ( - - {children} - - ); -} - -const renderOptions = { - wrapper: Wrapper, -}; - -function getTransaction() { - return { - labels: { someKey: 'labels value' }, - http: { someKey: 'http value' }, - host: { someKey: 'host value' }, - container: { someKey: 'container value' }, - service: { someKey: 'service value' }, - process: { someKey: 'process value' }, - agent: { someKey: 'agent value' }, - url: { someKey: 'url value' }, - user: { someKey: 'user value' }, - notIncluded: 'not included value', - transaction: { - id: '7efbc7056b746fcb', - notIncluded: 'transaction not included value', - custom: { - someKey: 'custom value', - }, - message: { - age: { ms: 1577958057123 }, - queue: { name: 'queue name' }, - }, - }, - } as unknown as Transaction; -} - -describe('TransactionMetadata', () => { - it('should render a transaction with all sections', () => { - const transaction = getTransaction(); - const output = render( - , - renderOptions - ); - - // sections - expectTextsInDocument(output, [ - 'Labels', - 'HTTP', - 'Host', - 'Container', - 'Service', - 'Process', - 'Agent', - 'URL', - 'User', - 'Custom', - 'Message', - ]); - }); - - it('should render a transaction with all included dot notation keys', () => { - const transaction = getTransaction(); - const output = render( - , - renderOptions - ); - - // included keys - expectTextsInDocument(output, [ - 'labels.someKey', - 'http.someKey', - 'host.someKey', - 'container.someKey', - 'service.someKey', - 'process.someKey', - 'agent.someKey', - 'url.someKey', - 'user.someKey', - 'transaction.custom.someKey', - 'transaction.message.age.ms', - 'transaction.message.queue.name', - ]); - - // excluded keys - expectTextsNotInDocument(output, [ - 'notIncluded', - 'transaction.notIncluded', - ]); - }); - - it('should render a transaction with all included values', () => { - const transaction = getTransaction(); - const output = render( - , - renderOptions - ); - - // included values - expectTextsInDocument(output, [ - 'labels value', - 'http value', - 'host value', - 'container value', - 'service value', - 'process value', - 'agent value', - 'url value', - 'user value', - 'custom value', - '1577958057123', - 'queue name', - ]); - - // excluded values - expectTextsNotInDocument(output, [ - 'not included value', - 'transaction not included value', - ]); - }); - - it('should render a transaction with only the required sections', () => { - const transaction = {} as Transaction; - const output = render( - , - renderOptions - ); - - // required sections should be found - expectTextsInDocument(output, ['Labels', 'User']); - - // optional sections should NOT be found - expectTextsNotInDocument(output, [ - 'HTTP', - 'Host', - 'Container', - 'Service', - 'Process', - 'Agent', - 'URL', - 'Custom', - 'Message', - ]); - }); -}); diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx index b3a53472f0815..32c0101c73b4d 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx @@ -6,19 +6,40 @@ */ import React, { useMemo } from 'react'; -import { TRANSACTION_METADATA_SECTIONS } from './sections'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; -import { getSectionsWithRows } from '../helper'; +import { getSectionsFromFields } from '../helper'; import { MetadataTable } from '..'; +import { ProcessorEvent } from '../../../../../common/processor_event'; +import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; interface Props { transaction: Transaction; } export function TransactionMetadata({ transaction }: Props) { - const sectionsWithRows = useMemo( - () => getSectionsWithRows(TRANSACTION_METADATA_SECTIONS, transaction), - [transaction] + const { data: transactionEvent, status } = useFetcher( + (callApmApi) => { + return callApmApi({ + endpoint: 'GET /api/apm/event_metadata/{processorEvent}/{id}', + params: { + path: { + processorEvent: ProcessorEvent.transaction, + id: transaction.transaction.id, + }, + }, + }); + }, + [transaction.transaction.id] + ); + + const sections = useMemo( + () => getSectionsFromFields(transactionEvent?.metadata || {}), + [transactionEvent?.metadata] + ); + return ( + ); - return ; } diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts deleted file mode 100644 index 2f4a3d3229857..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts +++ /dev/null @@ -1,47 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - Section, - TRANSACTION, - LABELS, - EVENT, - HTTP, - HOST, - CLIENT, - CONTAINER, - SERVICE, - PROCESS, - AGENT, - URL, - PAGE, - USER, - USER_AGENT, - CUSTOM_TRANSACTION, - MESSAGE_TRANSACTION, - TRACE, -} from '../sections'; - -export const TRANSACTION_METADATA_SECTIONS: Section[] = [ - { ...LABELS, required: true }, - TRACE, - TRANSACTION, - EVENT, - HTTP, - HOST, - CLIENT, - CONTAINER, - SERVICE, - PROCESS, - MESSAGE_TRANSACTION, - AGENT, - URL, - { ...PAGE, key: 'transaction.page' }, - { ...USER, required: true }, - USER_AGENT, - CUSTOM_TRANSACTION, -]; diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/helper.test.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/helper.test.ts index 770b35e7d17f2..2e64c170437d8 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/helper.test.ts +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/helper.test.ts @@ -5,62 +5,52 @@ * 2.0. */ -import { getSectionsWithRows, filterSectionsByTerm } from './helper'; -import { LABELS, HTTP, SERVICE } from './sections'; -import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; +import { filterSectionsByTerm, getSectionsFromFields } from './helper'; describe('MetadataTable Helper', () => { - const sections = [ - { ...LABELS, required: true }, - HTTP, - { ...SERVICE, properties: ['environment'] }, - ]; - const apmDoc = { - http: { - headers: { - Connection: 'close', - Host: 'opbeans:3000', - request: { method: 'get' }, - }, - }, - service: { - framework: { name: 'express' }, - environment: 'production', - }, - } as unknown as Transaction; - const metadataItems = getSectionsWithRows(sections, apmDoc); + const fields = { + 'http.headers.Connection': ['close'], + 'http.headers.Host': ['opbeans:3000'], + 'http.headers.request.method': ['get'], + 'service.framework.name': ['express'], + 'service.environment': ['production'], + }; + + const metadataItems = getSectionsFromFields(fields); - it('returns flattened data and required section', () => { + it('returns flattened data', () => { expect(metadataItems).toEqual([ - { key: 'labels', label: 'Labels', required: true, rows: [] }, { key: 'http', - label: 'HTTP', - rows: [ - { key: 'http.headers.Connection', value: 'close' }, - { key: 'http.headers.Host', value: 'opbeans:3000' }, - { key: 'http.headers.request.method', value: 'get' }, + label: 'http', + properties: [ + { field: 'http.headers.Connection', value: ['close'] }, + { field: 'http.headers.Host', value: ['opbeans:3000'] }, + { field: 'http.headers.request.method', value: ['get'] }, ], }, { key: 'service', - label: 'Service', - properties: ['environment'], - rows: [{ key: 'service.environment', value: 'production' }], + label: 'service', + properties: [ + { field: 'service.environment', value: ['production'] }, + { field: 'service.framework.name', value: ['express'] }, + ], }, ]); }); + describe('filter', () => { it('items by key', () => { const filteredItems = filterSectionsByTerm(metadataItems, 'http'); expect(filteredItems).toEqual([ { key: 'http', - label: 'HTTP', - rows: [ - { key: 'http.headers.Connection', value: 'close' }, - { key: 'http.headers.Host', value: 'opbeans:3000' }, - { key: 'http.headers.request.method', value: 'get' }, + label: 'http', + properties: [ + { field: 'http.headers.Connection', value: ['close'] }, + { field: 'http.headers.Host', value: ['opbeans:3000'] }, + { field: 'http.headers.request.method', value: ['get'] }, ], }, ]); @@ -71,9 +61,8 @@ describe('MetadataTable Helper', () => { expect(filteredItems).toEqual([ { key: 'service', - label: 'Service', - properties: ['environment'], - rows: [{ key: 'service.environment', value: 'production' }], + label: 'service', + properties: [{ field: 'service.environment', value: ['production'] }], }, ]); }); diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/helper.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/helper.ts index bd115c1c7c174..c9e0f2aa66745 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/helper.ts +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/helper.ts @@ -5,35 +5,52 @@ * 2.0. */ -import { get, pick, isEmpty } from 'lodash'; -import { Section } from './sections'; -import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; -import { APMError } from '../../../../typings/es_schemas/ui/apm_error'; -import { Span } from '../../../../typings/es_schemas/ui/span'; -import { flattenObject, KeyValuePair } from '../../../utils/flattenObject'; - -export type SectionsWithRows = ReturnType; - -export const getSectionsWithRows = ( - sections: Section[], - apmDoc: Transaction | APMError | Span -) => { - return sections - .map((section) => { - const sectionData: Record = get(apmDoc, section.key); - const filteredData: Record | undefined = - section.properties - ? pick(sectionData, section.properties) - : sectionData; - - const rows: KeyValuePair[] = flattenObject(filteredData, section.key); - return { ...section, rows }; - }) - .filter(({ required, rows }) => required || !isEmpty(rows)); +import { isEmpty, groupBy, partition } from 'lodash'; +import type { SectionDescriptor } from './types'; + +const EXCLUDED_FIELDS = ['error.exception.stacktrace', 'span.stacktrace']; + +export const getSectionsFromFields = (fields: Record) => { + const rows = Object.keys(fields) + .filter( + (field) => !EXCLUDED_FIELDS.some((excluded) => field.startsWith(excluded)) + ) + .sort() + .map((field) => { + return { + section: field.split('.')[0], + field, + value: fields[field], + }; + }); + + const sections = Object.values(groupBy(rows, 'section')).map( + (rowsForSection) => { + const first = rowsForSection[0]; + + const section: SectionDescriptor = { + key: first.section, + label: first.section.toLowerCase(), + properties: rowsForSection.map((row) => ({ + field: row.field, + value: row.value, + })), + }; + + return section; + } + ); + + const [labelSections, otherSections] = partition( + sections, + (section) => section.key === 'labels' + ); + + return [...labelSections, ...otherSections]; }; export const filterSectionsByTerm = ( - sections: SectionsWithRows, + sections: SectionDescriptor[], searchTerm: string ) => { if (!searchTerm) { @@ -41,15 +58,16 @@ export const filterSectionsByTerm = ( } return sections .map((section) => { - const { rows = [] } = section; - const filteredRows = rows.filter(({ key, value }) => { - const valueAsString = String(value).toLowerCase(); + const { properties = [] } = section; + const filteredProps = properties.filter(({ field, value }) => { return ( - key.toLowerCase().includes(searchTerm) || - valueAsString.includes(searchTerm) + field.toLowerCase().includes(searchTerm) || + value.some((val: string | number) => + String(val).toLowerCase().includes(searchTerm) + ) ); }); - return { ...section, rows: filteredRows }; + return { ...section, properties: filteredProps }; }) - .filter(({ rows }) => !isEmpty(rows)); + .filter(({ properties }) => !isEmpty(properties)); }; diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx index 45be525512d0a..248fa240fd557 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx @@ -19,18 +19,21 @@ import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React, { useCallback } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; +import { EuiLoadingSpinner } from '@elastic/eui'; import { useUrlParams } from '../../../context/url_params_context/use_url_params'; import { HeightRetainer } from '../HeightRetainer'; import { fromQuery, toQuery } from '../Links/url_helpers'; -import { filterSectionsByTerm, SectionsWithRows } from './helper'; +import { filterSectionsByTerm } from './helper'; import { Section } from './Section'; import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; +import { SectionDescriptor } from './types'; interface Props { - sections: SectionsWithRows; + sections: SectionDescriptor[]; + isLoading: boolean; } -export function MetadataTable({ sections }: Props) { +export function MetadataTable({ sections, isLoading }: Props) { const history = useHistory(); const location = useLocation(); const { urlParams } = useUrlParams(); @@ -77,6 +80,13 @@ export function MetadataTable({ sections }: Props) { /> + {isLoading && ( + + + + + + )} {filteredSections.map((section) => (
    @@ -84,7 +94,7 @@ export function MetadataTable({ sections }: Props) {
    {section.label}
    -
    +
    ))} diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts deleted file mode 100644 index efc2ef8bde66b..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts +++ /dev/null @@ -1,173 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export interface Section { - key: string; - label: string; - required?: boolean; - properties?: string[]; -} - -export const LABELS: Section = { - key: 'labels', - label: i18n.translate('xpack.apm.metadataTable.section.labelsLabel', { - defaultMessage: 'Labels', - }), -}; - -export const EVENT: Section = { - key: 'event', - label: i18n.translate('xpack.apm.metadataTable.section.eventLabel', { - defaultMessage: 'event', - }), - properties: ['outcome'], -}; - -export const HTTP: Section = { - key: 'http', - label: i18n.translate('xpack.apm.metadataTable.section.httpLabel', { - defaultMessage: 'HTTP', - }), -}; - -export const HOST: Section = { - key: 'host', - label: i18n.translate('xpack.apm.metadataTable.section.hostLabel', { - defaultMessage: 'Host', - }), -}; - -export const CLIENT: Section = { - key: 'client', - label: i18n.translate('xpack.apm.metadataTable.section.clientLabel', { - defaultMessage: 'Client', - }), - properties: ['ip'], -}; - -export const CONTAINER: Section = { - key: 'container', - label: i18n.translate('xpack.apm.metadataTable.section.containerLabel', { - defaultMessage: 'Container', - }), -}; - -export const SERVICE: Section = { - key: 'service', - label: i18n.translate('xpack.apm.metadataTable.section.serviceLabel', { - defaultMessage: 'Service', - }), -}; - -export const PROCESS: Section = { - key: 'process', - label: i18n.translate('xpack.apm.metadataTable.section.processLabel', { - defaultMessage: 'Process', - }), -}; - -export const AGENT: Section = { - key: 'agent', - label: i18n.translate('xpack.apm.metadataTable.section.agentLabel', { - defaultMessage: 'Agent', - }), -}; - -export const URL: Section = { - key: 'url', - label: i18n.translate('xpack.apm.metadataTable.section.urlLabel', { - defaultMessage: 'URL', - }), -}; - -export const USER: Section = { - key: 'user', - label: i18n.translate('xpack.apm.metadataTable.section.userLabel', { - defaultMessage: 'User', - }), -}; - -export const USER_AGENT: Section = { - key: 'user_agent', - label: i18n.translate('xpack.apm.metadataTable.section.userAgentLabel', { - defaultMessage: 'User agent', - }), -}; - -export const PAGE: Section = { - key: 'page', - label: i18n.translate('xpack.apm.metadataTable.section.pageLabel', { - defaultMessage: 'Page', - }), -}; - -export const SPAN: Section = { - key: 'span', - label: i18n.translate('xpack.apm.metadataTable.section.spanLabel', { - defaultMessage: 'Span', - }), - properties: ['id'], -}; - -export const TRANSACTION: Section = { - key: 'transaction', - label: i18n.translate('xpack.apm.metadataTable.section.transactionLabel', { - defaultMessage: 'Transaction', - }), - properties: ['id'], -}; - -export const TRACE: Section = { - key: 'trace', - label: i18n.translate('xpack.apm.metadataTable.section.traceLabel', { - defaultMessage: 'Trace', - }), - properties: ['id'], -}; - -export const ERROR: Section = { - key: 'error', - label: i18n.translate('xpack.apm.metadataTable.section.errorLabel', { - defaultMessage: 'Error', - }), - properties: ['id'], -}; - -const customLabel = i18n.translate( - 'xpack.apm.metadataTable.section.customLabel', - { - defaultMessage: 'Custom', - } -); - -export const CUSTOM_ERROR: Section = { - key: 'error.custom', - label: customLabel, -}; -export const CUSTOM_TRANSACTION: Section = { - key: 'transaction.custom', - label: customLabel, -}; - -const messageLabel = i18n.translate( - 'xpack.apm.metadataTable.section.messageLabel', - { - defaultMessage: 'Message', - } -); - -export const MESSAGE_TRANSACTION: Section = { - key: 'transaction.message', - label: messageLabel, -}; - -export const MESSAGE_SPAN: Section = { - key: 'span.message', - label: messageLabel, -}; diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/types.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/types.ts new file mode 100644 index 0000000000000..3ce7698460f30 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/types.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export interface SectionDescriptor { + key: string; + label: string; + required?: boolean; + properties: Array<{ field: string; value: string[] | number[] }>; +} diff --git a/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts b/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts new file mode 100644 index 0000000000000..97e2e1356363f --- /dev/null +++ b/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { + ERROR_ID, + SPAN_ID, + TRANSACTION_ID, +} from '../../../common/elasticsearch_fieldnames'; +import { ProcessorEvent } from '../../../common/processor_event'; +import type { APMEventClient } from '../helpers/create_es_client/create_apm_event_client'; + +export async function getEventMetadata({ + apmEventClient, + processorEvent, + id, +}: { + apmEventClient: APMEventClient; + processorEvent: ProcessorEvent; + id: string; +}) { + const filter: QueryDslQueryContainer[] = []; + + switch (processorEvent) { + case ProcessorEvent.error: + filter.push({ + term: { [ERROR_ID]: id }, + }); + break; + + case ProcessorEvent.transaction: + filter.push({ + term: { + [TRANSACTION_ID]: id, + }, + }); + break; + + case ProcessorEvent.span: + filter.push({ + term: { [SPAN_ID]: id }, + }); + break; + } + + const response = await apmEventClient.search('get_event_metadata', { + apm: { + events: [processorEvent], + }, + body: { + query: { + bool: { filter }, + }, + size: 1, + _source: false, + fields: [{ field: '*', include_unmapped: true }], + }, + terminate_after: 1, + }); + + return response.hits.hits[0].fields; +} diff --git a/x-pack/plugins/apm/server/routes/event_metadata.ts b/x-pack/plugins/apm/server/routes/event_metadata.ts new file mode 100644 index 0000000000000..8970ab8ffdeea --- /dev/null +++ b/x-pack/plugins/apm/server/routes/event_metadata.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as t from 'io-ts'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; +import { createApmServerRoute } from './create_apm_server_route'; +import { getEventMetadata } from '../lib/event_metadata/get_event_metadata'; +import { processorEventRt } from '../../common/processor_event'; +import { setupRequest } from '../lib/helpers/setup_request'; + +const eventMetadataRoute = createApmServerRoute({ + endpoint: 'GET /api/apm/event_metadata/{processorEvent}/{id}', + options: { tags: ['access:apm'] }, + params: t.type({ + path: t.type({ + processorEvent: processorEventRt, + id: t.string, + }), + }), + handler: async (resources) => { + const setup = await setupRequest(resources); + + const { + path: { processorEvent, id }, + } = resources.params; + + const metadata = await getEventMetadata({ + apmEventClient: setup.apmEventClient, + processorEvent, + id, + }); + + return { + metadata, + }; + }, +}); + +export const eventMetadataRouteRepository = + createApmServerRouteRepository().add(eventMetadataRoute); diff --git a/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts b/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts index 7aa520dd5b8a2..472e46fecfa10 100644 --- a/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts +++ b/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts @@ -33,6 +33,7 @@ import { traceRouteRepository } from './traces'; import { transactionRouteRepository } from './transactions'; import { APMRouteHandlerResources } from './typings'; import { historicalDataRouteRepository } from './historical_data'; +import { eventMetadataRouteRepository } from './event_metadata'; import { suggestionsRouteRepository } from './suggestions'; const getTypedGlobalApmServerRouteRepository = () => { @@ -58,7 +59,8 @@ const getTypedGlobalApmServerRouteRepository = () => { .merge(apmFleetRouteRepository) .merge(backendsRouteRepository) .merge(fallbackToTransactionsRouteRepository) - .merge(historicalDataRouteRepository); + .merge(historicalDataRouteRepository) + .merge(eventMetadataRouteRepository); return repository; }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index dcbb8ce26ee4a..bdccd8ad87760 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6432,24 +6432,6 @@ "xpack.apm.localFilters.titles.serviceName": "サービス名", "xpack.apm.localFilters.titles.transactionUrl": "URL", "xpack.apm.localFiltersTitle": "フィルター", - "xpack.apm.metadataTable.section.agentLabel": "エージェント", - "xpack.apm.metadataTable.section.clientLabel": "クライアント", - "xpack.apm.metadataTable.section.containerLabel": "コンテナー", - "xpack.apm.metadataTable.section.customLabel": "カスタム", - "xpack.apm.metadataTable.section.errorLabel": "エラー", - "xpack.apm.metadataTable.section.hostLabel": "ホスト", - "xpack.apm.metadataTable.section.httpLabel": "HTTP", - "xpack.apm.metadataTable.section.labelsLabel": "ラベル", - "xpack.apm.metadataTable.section.messageLabel": "メッセージ", - "xpack.apm.metadataTable.section.pageLabel": "ページ", - "xpack.apm.metadataTable.section.processLabel": "プロセス", - "xpack.apm.metadataTable.section.serviceLabel": "サービス", - "xpack.apm.metadataTable.section.spanLabel": "スパン", - "xpack.apm.metadataTable.section.traceLabel": "トレース", - "xpack.apm.metadataTable.section.transactionLabel": "トランザクション", - "xpack.apm.metadataTable.section.urlLabel": "URL", - "xpack.apm.metadataTable.section.userAgentLabel": "ユーザーエージェント", - "xpack.apm.metadataTable.section.userLabel": "ユーザー", "xpack.apm.metrics.transactionChart.machineLearningLabel": "機械学習:", "xpack.apm.metrics.transactionChart.machineLearningTooltip": "ストリームには、平均レイテンシの想定境界が表示されます。赤色の垂直の注釈は、異常スコアが75以上の異常値を示します。", "xpack.apm.metrics.transactionChart.machineLearningTooltip.withKuery": "フィルタリングで検索バーを使用しているときには、機械学習結果が表示されません", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 87c96d1efe48d..4be40151f7318 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6483,24 +6483,6 @@ "xpack.apm.localFilters.titles.serviceName": "服务名称", "xpack.apm.localFilters.titles.transactionUrl": "URL", "xpack.apm.localFiltersTitle": "筛选", - "xpack.apm.metadataTable.section.agentLabel": "代理", - "xpack.apm.metadataTable.section.clientLabel": "客户端", - "xpack.apm.metadataTable.section.containerLabel": "容器", - "xpack.apm.metadataTable.section.customLabel": "定制", - "xpack.apm.metadataTable.section.errorLabel": "错误", - "xpack.apm.metadataTable.section.hostLabel": "主机", - "xpack.apm.metadataTable.section.httpLabel": "HTTP", - "xpack.apm.metadataTable.section.labelsLabel": "标签", - "xpack.apm.metadataTable.section.messageLabel": "消息", - "xpack.apm.metadataTable.section.pageLabel": "页", - "xpack.apm.metadataTable.section.processLabel": "进程", - "xpack.apm.metadataTable.section.serviceLabel": "服务", - "xpack.apm.metadataTable.section.spanLabel": "跨度", - "xpack.apm.metadataTable.section.traceLabel": "跟踪", - "xpack.apm.metadataTable.section.transactionLabel": "事务", - "xpack.apm.metadataTable.section.urlLabel": "URL", - "xpack.apm.metadataTable.section.userAgentLabel": "用户代理", - "xpack.apm.metadataTable.section.userLabel": "用户", "xpack.apm.metrics.transactionChart.machineLearningLabel": "Machine Learning", "xpack.apm.metrics.transactionChart.machineLearningTooltip": "流显示平均延迟的预期边界。红色垂直标注表示异常分数等于或大于 75 的异常。", "xpack.apm.metrics.transactionChart.machineLearningTooltip.withKuery": "使用搜索栏筛选时,Machine Learning 结果处于隐藏状态", diff --git a/x-pack/test/apm_api_integration/tests/index.ts b/x-pack/test/apm_api_integration/tests/index.ts index d402a74287f98..efe159b36e3d3 100644 --- a/x-pack/test/apm_api_integration/tests/index.ts +++ b/x-pack/test/apm_api_integration/tests/index.ts @@ -37,6 +37,10 @@ export default function apmApiIntegrationTests(providerContext: FtrProviderConte loadTestFile(require.resolve('./correlations/latency')); }); + describe('metadata/event_metadata', function () { + loadTestFile(require.resolve('./metadata/event_metadata')); + }); + describe('metrics_charts/metrics_charts', function () { loadTestFile(require.resolve('./metrics_charts/metrics_charts')); }); diff --git a/x-pack/test/apm_api_integration/tests/metadata/event_metadata.ts b/x-pack/test/apm_api_integration/tests/metadata/event_metadata.ts new file mode 100644 index 0000000000000..d979f0bad1ec6 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/metadata/event_metadata.ts @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import expect from '@kbn/expect'; +import { PROCESSOR_EVENT } from '../../../../plugins/apm/common/elasticsearch_fieldnames'; +import { ProcessorEvent } from '../../../../plugins/apm/common/processor_event'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const apmApiClient = getService('apmApiClient'); + const esClient = getService('es'); + + async function getLastDocId(processorEvent: ProcessorEvent) { + const response = await esClient.search<{ + [key: string]: { id: string }; + }>({ + index: ['apm-*'], + body: { + query: { + bool: { + filter: [{ term: { [PROCESSOR_EVENT]: processorEvent } }], + }, + }, + size: 1, + sort: { + '@timestamp': 'desc', + }, + }, + }); + + return response.body.hits.hits[0]._source![processorEvent].id; + } + + registry.when('Event metadata', { config: 'basic', archives: ['apm_8.0.0'] }, () => { + it('fetches transaction metadata', async () => { + const id = await getLastDocId(ProcessorEvent.transaction); + + const { body } = await apmApiClient.readUser({ + endpoint: 'GET /api/apm/event_metadata/{processorEvent}/{id}', + params: { + path: { + processorEvent: ProcessorEvent.transaction, + id, + }, + }, + }); + + expect(body).keys('metadata').ok(); + + expect( + Object.keys(body.metadata).filter((key) => { + return Array.isArray(body.metadata[key]); + }) + ); + + expect(body.metadata).keys( + '@timestamp', + 'agent.name', + 'transaction.name', + 'transaction.type', + 'service.name' + ); + }); + + it('fetches error metadata', async () => { + const id = await getLastDocId(ProcessorEvent.error); + + const { body } = await apmApiClient.readUser({ + endpoint: 'GET /api/apm/event_metadata/{processorEvent}/{id}', + params: { + path: { + processorEvent: ProcessorEvent.error, + id, + }, + }, + }); + + expect(body).keys('metadata').ok(); + + expect( + Object.keys(body.metadata).filter((key) => { + return Array.isArray(body.metadata[key]); + }) + ); + + expect(body.metadata).keys( + '@timestamp', + 'agent.name', + 'error.grouping_key', + 'error.grouping_name', + 'service.name' + ); + }); + + it('fetches span metadata', async () => { + const id = await getLastDocId(ProcessorEvent.span); + + const { body } = await apmApiClient.readUser({ + endpoint: 'GET /api/apm/event_metadata/{processorEvent}/{id}', + params: { + path: { + processorEvent: ProcessorEvent.span, + id, + }, + }, + }); + + expect(body).keys('metadata').ok(); + + expect( + Object.keys(body.metadata).filter((key) => { + return Array.isArray(body.metadata[key]); + }) + ); + + expect(body.metadata).keys( + '@timestamp', + 'agent.name', + 'span.name', + 'span.type', + 'service.name' + ); + }); + }); +} From 9920e63a25b5c719ac70ad648963f949b81dc599 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 5 Oct 2021 12:50:31 +0100 Subject: [PATCH 97/98] skip flaky suite (#60559) --- .../apps/discover/feature_controls/discover_spaces.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts index c245b45917497..5c6d68466dde4 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_spaces.ts @@ -33,7 +33,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); }); - describe('space with no features disabled', () => { + // FLAKY: https://github.com/elastic/kibana/issues/60559 + describe.skip('space with no features disabled', () => { before(async () => { // we need to load the following in every situation as deleting // a space deletes all of the associated saved objects From 853c5886265371a7c1f633b9d06744797455b95f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Tue, 5 Oct 2021 14:00:19 +0200 Subject: [PATCH 98/98] [APM] Add documentation for APM data and queries (#113542) --- x-pack/plugins/apm/dev_docs/apm_queries.md | 426 +++++++++++++++++++++ 1 file changed, 426 insertions(+) create mode 100644 x-pack/plugins/apm/dev_docs/apm_queries.md diff --git a/x-pack/plugins/apm/dev_docs/apm_queries.md b/x-pack/plugins/apm/dev_docs/apm_queries.md new file mode 100644 index 0000000000000..7d730d2ef2a77 --- /dev/null +++ b/x-pack/plugins/apm/dev_docs/apm_queries.md @@ -0,0 +1,426 @@ +# Transactions + +Transactions are stored in two different formats: + +#### Individual transactions document + +A single transaction with a latency of 2ms + +```json +{ + "@timestamp": "2021-09-01T10:00:00.000Z", + "processor.event": "transaction", + "transaction.duration.us": 2000, + "event.outcome": "success" +} +``` + +or + +#### Aggregated (metric) document +A pre-aggregated document where `_doc_count` is the number of original transactions, and `transaction.duration.histogram` is the latency distribution. + +```json +{ + "_doc_count": 2, + "@timestamp": "2021-09-01T10:00:00.000Z", + "processor.event": "metric", + "metricset.name": "transaction", + "transaction.duration.histogram": { + "counts": [1, 1], + "values": [2000, 3000] + }, + "event.outcome": "success" +} +``` + +The decision to use aggregated transactions or not is determined in [`getSearchAggregatedTransactions`](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/index.ts#L53-L79) and then used to [specify the index](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts#L30-L32) and the [latency field](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts#L62-L65) + +### Latency + +Latency is the duration of a transaction. This can be calculated using transaction events or metric events (aggregated transactions). + +Noteworthy fields: `transaction.duration.us`, `transaction.duration.histogram` + +#### Transaction-based latency + +```json +{ + "size": 0, + "query": { + "bool": { + "filter": [{ "terms": { "processor.event": ["transaction"] } }] + } + }, + "aggs": { + "latency": { "avg": { "field": "transaction.duration.us" } } + } +} +``` + +#### Metric-based latency + +```json +{ + "size": 0, + "query": { + "bool": { + "filter": [ + { "terms": { "processor.event": ["metric"] } }, + { "term": { "metricset.name": "transaction" } } + ] + } + }, + "aggs": { + "latency": { "avg": { "field": "transaction.duration.histogram" } } + } +} +``` + +Please note: `metricset.name: transaction` was only recently introduced. To retain backwards compatability we still use the old filter `{ "exists": { "field": "transaction.duration.histogram" }}` when filtering for aggregated transactions. + +### Throughput + +Throughput is the number of transactions per minute. This can be calculated using transaction events or metric events (aggregated transactions). + +Noteworthy fields: None (based on `doc_count`) + +```js +{ + "size": 0, + "query": { + // same filters as for latency + }, + "aggs": { + "throughput": { "rate": { "unit": "minute" } } + } +} +``` + +### Failed transaction rate + +Failed transaction rate is the number of transactions with `event.outcome=failure` per minute. +Noteworthy fields: `event.outcome` + +```js +{ + "size": 0, + "query": { + // same filters as for latency + }, + "aggs": { + "outcomes": { + "terms": { + "field": "event.outcome", + "include": ["failure", "success"] + } + } + } +} +``` + +# System metrics + +System metrics are captured periodically (every 60 seconds by default). + +### CPU + +![image](https://user-images.githubusercontent.com/209966/135990500-f85bd8d9-b5a5-4b7c-b9e1-0759eefb8a29.png) + +Used in: [Metrics section](https://github.com/elastic/kibana/blob/00bb59713ed115343eb70d4e39059476edafbade/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts#L83) + +Noteworthy fields: `system.cpu.total.norm.pct`, `system.process.cpu.total.norm.pct` + +#### Sample document + +```json +{ + "@timestamp": "2021-09-01T10:00:00.000Z", + "processor.event": "metric", + "metricset.name": "app", + "system.process.cpu.total.norm.pct": 0.003, + "system.cpu.total.norm.pct": 0.28 +} +``` + +#### Query + +```json +{ + "size": 0, + "query": { + "bool": { + "filter": [ + { "terms": { "processor.event": ["metric"] } }, + { "terms": { "metricset.name": ["app"] } } + ] + } + }, + "aggs": { + "systemCPUAverage": { "avg": { "field": "system.cpu.total.norm.pct" } }, + "processCPUAverage": { + "avg": { "field": "system.process.cpu.total.norm.pct" } + } + } +} +``` + +### Memory + +![image](https://user-images.githubusercontent.com/209966/135990556-31716990-2812-46c3-a926-8c2a64c7c89f.png) + +Noteworthy fields: `system.memory.actual.free`, `system.memory.total`, + +#### Sample document + +```json +{ + "@timestamp": "2021-09-01T10:00:00.000Z", + "processor.event": "metric", + "metricset.name": "app", + "system.memory.actual.free": 13182939136, + "system.memory.total": 15735697408 +} +``` + +#### Query + +```js +{ + "size": 0, + "query": { + "bool": { + "filter": [ + { "terms": { "processor.event": ["metric"] }}, + { "terms": { "metricset.name": ["app"] }} + + // ensure the memory fields exists + { "exists": { "field": "system.memory.actual.free" }}, + { "exists": { "field": "system.memory.total" }}, + ] + } + }, + "aggs": { + "memoryUsedAvg": { + "avg": { + "script": { + "lang": "expression", + "source": "1 - doc['system.memory.actual.free'] / doc['system.memory.total']" + } + } + } + } +} +``` + +Above example is overly simplified. In reality [we do a bit more](https://github.com/elastic/kibana/blob/fe9b5332e157fd456f81aecfd4ffa78d9e511a66/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts#L51-L71) to properly calculate memory usage inside containers + + + +# Transaction breakdown metrics (`transaction_breakdown`) + +A pre-aggregations of transaction documents where `transaction.breakdown.count` is the number of original transactions. + +Noteworthy fields: `transaction.name`, `transaction.type` + +#### Sample document + +```json +{ + "@timestamp": "2021-09-27T21:59:59.828Z", + "processor.event": "metric", + "metricset.name": "transaction_breakdown", + "transaction.breakdown.count": 12, + "transaction.name": "GET /api/products", + "transaction.type": "request" +} +} +``` + +# Span breakdown metrics (`span_breakdown`) + +A pre-aggregations of span documents where `span.self_time.count` is the number of original spans. Measures the "self-time" for a span type, and optional subtype, within a transaction group. + +Span breakdown metrics are used to power the "Time spent by span type" graph. Agents collect summarized metrics about the timings of spans, broken down by `span.type`. + +![image](https://user-images.githubusercontent.com/209966/135990865-9077ae3e-a7a4-4b5d-bdce-41dc832689ea.png) + +Used in: ["Time spent by span type" chart](https://github.com/elastic/kibana/blob/723370ab23573e50b3524a62c6b9998f2042423d/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts#L48-L87) + +Noteworthy fields: `transaction.name`, `transaction.type`, `span.type`, `span.subtype`, `span.self_time.*` + +#### Sample document + +```json +{ + "@timestamp": "2021-09-27T21:59:59.828Z", + "processor.event": "metric", + "metricset.name": "span_breakdown", + "transaction.name": "GET /api/products", + "transaction.type": "request", + "span.self_time.sum.us": 1028, + "span.self_time.count": 12, + "span.type": "db", + "span.subtype": "elasticsearch" +} +``` + +#### Query + +```json +{ + "size": 0, + "query": { + "bool": { + "filter": [ + { "terms": { "processor.event": ["metric"] } }, + { "terms": { "metricset.name": ["span_breakdown"] } } + ] + } + }, + "aggs": { + "total_self_time": { "sum": { "field": "span.self_time.sum.us" } }, + "types": { + "terms": { "field": "span.type" }, + "aggs": { + "subtypes": { + "terms": { "field": "span.subtype" }, + "aggs": { + "self_time_per_subtype": { + "sum": { "field": "span.self_time.sum.us" } + } + } + } + } + } + } +} +``` + +# Service destination metrics + +Pre-aggregations of span documents, where `span.destination.service.response_time.count` is the number of original spans. +These metrics measure the count and total duration of requests from one service to another service. + +![image](https://user-images.githubusercontent.com/209966/135990117-170070da-2fc5-4014-a597-0dda0970854c.png) + +Used in: [Dependencies (latency)](https://github.com/elastic/kibana/blob/00bb59713ed115343eb70d4e39059476edafbade/x-pack/plugins/apm/server/lib/backends/get_latency_charts_for_backend.ts#L68-L79), [Dependencies (throughput)](https://github.com/elastic/kibana/blob/00bb59713ed115343eb70d4e39059476edafbade/x-pack/plugins/apm/server/lib/backends/get_throughput_charts_for_backend.ts#L67-L74) and [Service Map](https://github.com/elastic/kibana/blob/00bb59713ed115343eb70d4e39059476edafbade/x-pack/plugins/apm/server/lib/service_map/get_service_map_backend_node_info.ts#L57-L67) + +Noteworthy fields: `span.destination.service.*` + +#### Sample document + +A pre-aggregated document with 73 span requests from opbeans-ruby to elasticsearch, and a combined latency of 1554ms + +```json +{ + "@timestamp": "2021-09-01T10:00:00.000Z", + "processor.event": "metric", + "metricset.name": "service_destination", + "service.name": "opbeans-ruby", + "span.destination.service.response_time.count": 73, + "span.destination.service.response_time.sum.us": 1554192, + "span.destination.service.resource": "elasticsearch", + "event.outcome": "success" +} +``` + +### Latency + +The latency between a service and an (external) endpoint + +```json +{ + "size": 0, + "query": { + "bool": { + "filter": [ + { "terms": { "processor.event": ["metric"] } }, + { "term": { "metricset.name": "service_destination" } }, + { "term": { "span.destination.service.resource": "elasticsearch" } } + ] + } + }, + "aggs": { + "latency_sum": { + "sum": { "field": "span.destination.service.response_time.sum.us" } + }, + "latency_count": { + "sum": { "field": "span.destination.service.response_time.count" } + } + } +} +``` + +### Throughput + +Captures the number of requests made from a service to an (external) endpoint + + +#### Query + +```json +{ + "size": 0, + "query": { + "bool": { + "filter": [ + { "terms": { "processor.event": ["metric"] } }, + { "term": { "metricset.name": "service_destination" } }, + { "term": { "span.destination.service.resource": "elasticsearch" } } + ] + } + }, + "aggs": { + "throughput": { + "rate": { + "field": "span.destination.service.response_time.count", + "unit": "minute" + } + } + } +} +``` + +## Common filters + +Most Elasticsearch queries will need to have one or more filters. There are a couple of reasons for adding filters: + +- correctness: Running an aggregation on unrelated documents will produce incorrect results +- stability: Running an aggregation on unrelated documents could cause the entire query to fail +- performance: limiting the number of documents will make the query faster + +```js +{ + "query": { + "bool": { + "filter": [ + // service name + { "term": { "service.name": "opbeans-go" }}, + + // service environment + { "term": { "service.environment": "testing" }} + + // transaction type + { "term": { "transaction.type": "request" }} + + // event type (possible values : transaction, span, metric, error) + { "terms": { "processor.event": ["metric"] }}, + + // metric set is a subtype of `processor.event: metric` + { "terms": { "metricset.name": ["transaction"] }}, + + // time range + { + "range": { + "@timestamp": { + "gte": 1633000560000, + "lte": 1633001498988, + "format": "epoch_millis" + } + } + } + ] + } + }, +```