From a9b26eebda55a39f8ea565ee8020a79b582828bf Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 5 Jul 2022 10:59:54 -0500 Subject: [PATCH 01/81] [docker] Retry fonts download (#134933) We recently had a build failure due to a temporary network failure. Most of the asset downloads in our Dockerfile already have retries, this adds similar to the reporting font download. --- .../os_packages/docker_generator/templates/base/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile b/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile index d171c48662cf6..da897e858867a 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/base/Dockerfile @@ -102,7 +102,7 @@ RUN set -e ; \ chmod +x /bin/tini RUN mkdir /usr/share/fonts/local -RUN curl -L -o /usr/share/fonts/local/NotoSansCJK-Regular.ttc https://github.com/googlefonts/noto-cjk/raw/NotoSansV2.001/NotoSansCJK-Regular.ttc +RUN curl --retry 8 -S -L -o /usr/share/fonts/local/NotoSansCJK-Regular.ttc https://github.com/googlefonts/noto-cjk/raw/NotoSansV2.001/NotoSansCJK-Regular.ttc RUN echo "5dcd1c336cc9344cb77c03a0cd8982ca8a7dc97d620fd6c9c434e02dcb1ceeb3 /usr/share/fonts/local/NotoSansCJK-Regular.ttc" | sha256sum -c - RUN fc-cache -v From 7b86fe76fc730d22afd32a6a13300db36af8333e Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 5 Jul 2022 18:39:49 +0200 Subject: [PATCH 02/81] [Synthetics] Added step duration breakdown on summary page (#135187) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../tabs_content/step_duration_panel.tsx | 65 +++++++++++++++++++ .../tabs_content/summary_tab_content.tsx | 42 ++++++++---- 2 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/tabs_content/step_duration_panel.tsx diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/tabs_content/step_duration_panel.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/tabs_content/step_duration_panel.tsx new file mode 100644 index 0000000000000..671e661f4eb06 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/tabs_content/step_duration_panel.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 { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText, EuiTitle } from '@elastic/eui'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { ReportTypes } from '@kbn/observability-plugin/public'; +import { useParams } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; + +import { ClientPluginsStart } from '../../../../../plugin'; +export const StepDurationPanel = () => { + const { observability } = useKibana().services; + + const { ExploratoryViewEmbeddable } = observability; + + const { monitorId } = useParams<{ monitorId: string }>(); + + return ( + + + + +

{DURATION_BY_STEP_LABEL}

+
+
+ + + {LAST_24H_LABEL} + + +
+ + +
+ ); +}; + +const DURATION_BY_STEP_LABEL = i18n.translate('xpack.synthetics.detailsPanel.durationByStep', { + defaultMessage: 'Duration by step', +}); + +const LAST_24H_LABEL = i18n.translate('xpack.synthetics.detailsPanel.last24Hours', { + defaultMessage: 'Last 24 hours', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/tabs_content/summary_tab_content.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/tabs_content/summary_tab_content.tsx index 0184cb5f8f150..41309a7cdc0b9 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/tabs_content/summary_tab_content.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/tabs_content/summary_tab_content.tsx @@ -6,26 +6,40 @@ */ import React from 'react'; -import { EuiTitle, EuiPanel, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiTitle, EuiPanel, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { StepDurationPanel } from './step_duration_panel'; import { MonitorDetailsPanel } from './monitor_details_panel'; export const SummaryTabContent = () => { return ( - - - - -

{MONITOR_DETAILS_LABEL}

-
- -
-
- - - -
+ <> + + + + +

{MONITOR_DETAILS_LABEL}

+
+ +
+
+ + + +
+ + {/* TODO: Add status panel*/} + + + + {/* TODO: Add last run panel*/} + + + + + + ); }; From 5e272cef123c3409a757ba0ff338be41363222fa Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Tue, 5 Jul 2022 18:48:24 +0200 Subject: [PATCH 03/81] [Security Solution][Endpoint][Response Actions] Show relative dates on date picker (#135611) * Update command column title refs elastic/security-team/issues/4279 * Show relative dates when used fixes elastic/security-team/issues/4279 * use super date picker update button fixes elastic/security-team/issues/4279 * update tests fixes elastic/security-team/issues/4279 * type imports * full width date picker inputs review comments --- .../action_list_date_range_picker.tsx | 116 +++++------ .../components/hooks.tsx | 15 +- .../response_actions_list.test.tsx | 187 ++++++++++-------- .../response_actions_list.tsx | 6 +- .../translations.tsx | 2 +- 5 files changed, 182 insertions(+), 144 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_list_date_range_picker.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_list_date_range_picker.tsx index ba09160a4d6da..cf453e2070705 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_list_date_range_picker.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_list_date_range_picker.tsx @@ -5,33 +5,31 @@ * 2.0. */ -import React, { memo, useState, useMemo } from 'react'; -import dateMath from '@kbn/datemath'; -import { EuiSuperDatePicker } from '@elastic/eui'; +import React, { useCallback, memo, useState } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiSuperDatePicker, EuiSuperUpdateButton } from '@elastic/eui'; +import type { IDataPluginServices } from '@kbn/data-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import type { EuiSuperDatePickerRecentRange } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { DurationRange, OnRefreshChangeProps } from '@elastic/eui/src/components/date_picker/types'; -import { useUiSetting$ } from '../../../../common/lib/kibana'; -import { DEFAULT_TIMEPICKER_QUICK_RANGES } from '../../../../../common/constants'; +import type { + DurationRange, + OnRefreshChangeProps, +} from '@elastic/eui/src/components/date_picker/types'; +import { UI_SETTINGS } from '@kbn/data-plugin/common'; +import type { useGetEndpointActionList } from '../../../hooks'; +import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; export interface DateRangePickerValues { autoRefreshOptions: { enabled: boolean; duration: number; }; - startDate?: string; - endDate?: string; + startDate: string; + endDate: string; recentlyUsedDateRanges: EuiSuperDatePickerRecentRange[]; } -interface Range { - from: string; - to: string; - display: string; -} const DatePickerWrapper = euiStyled.div` - width: ${(props) => props.theme.eui.fractions.single.percentage}; padding-bottom: ${(props) => `${props.theme.eui.euiCodeBlockPaddingModifiers.paddingLarge}`}; `; @@ -42,56 +40,64 @@ export const ActionListDateRangePicker = memo( onRefresh, onRefreshChange, onTimeChange, + onClick, }: { dateRangePickerState: DateRangePickerValues; isDataLoading: boolean; onRefresh: () => void; onRefreshChange: (evt: OnRefreshChangeProps) => void; onTimeChange: ({ start, end }: DurationRange) => void; + onClick: ReturnType['refetch']; }) => { - const { uiSettings } = useKibana().services; - const [quickRanges] = useUiSetting$(DEFAULT_TIMEPICKER_QUICK_RANGES); - const [dateFormat] = useState(() => uiSettings?.get('dateFormat')); - const commonlyUsedRanges = !quickRanges.length - ? [] - : quickRanges.map(({ from, to, display }) => ({ - start: from, - end: to, - label: display, - })); - - const end = useMemo( - () => - dateRangePickerState.endDate - ? dateMath.parse(dateRangePickerState.endDate)?.toISOString() - : undefined, - [dateRangePickerState] - ); - - const start = useMemo( - () => - dateRangePickerState.startDate - ? dateMath.parse(dateRangePickerState.startDate)?.toISOString() - : undefined, - [dateRangePickerState] - ); + const getTestId = useTestIdGenerator('response-actions-list'); + const kibana = useKibana(); + const { uiSettings } = kibana.services; + const [commonlyUsedRanges] = useState(() => { + return ( + uiSettings + ?.get(UI_SETTINGS.TIMEPICKER_QUICK_RANGES) + ?.map(({ from, to, display }: { from: string; to: string; display: string }) => { + return { + start: from, + end: to, + label: display, + }; + }) ?? [] + ); + }); + const onClickCallback = useCallback(() => onClick(), [onClick]); return ( - - + + + + + + + + + ); } diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx index 4cc2e79981123..5ea37b444dad1 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import dateMath from '@kbn/datemath'; import { useCallback, useState } from 'react'; import type { DurationRange, @@ -18,7 +17,7 @@ const defaultDateRangeOptions = Object.freeze({ enabled: false, duration: 10000, }, - startDate: 'now-1d', + startDate: 'now-24h/h', endDate: 'now', recentlyUsedDateRanges: [], }); @@ -31,8 +30,8 @@ export const useDateRangePicker = () => { ({ start, end }) => { setDateRangePickerState((prevState) => ({ ...prevState, - startDate: dateMath.parse(start)?.toISOString(), - endDate: dateMath.parse(end)?.toISOString(), + startDate: start, + endDate: end, })); }, [setDateRangePickerState] @@ -62,6 +61,10 @@ export const useDateRangePicker = () => { // handle manual time change on date picker const onTimeChange = useCallback( ({ start: newStart, end: newEnd }: DurationRange) => { + // update date ranges + updateActionListDateRanges({ start: newStart, end: newEnd }); + + // update recently used date ranges const newRecentlyUsedDateRanges = [ { start: newStart, end: newEnd }, ...dateRangePickerState.recentlyUsedDateRanges @@ -71,10 +74,6 @@ export const useDateRangePicker = () => { ) .slice(0, 9), ]; - - // update date ranges - updateActionListDateRanges({ start: newStart, end: newEnd }); - // update recently used date ranges updateActionListRecentlyUsedDateRanges(newRecentlyUsedDateRanges); }, [ diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.test.tsx index d3f8b780df77e..7123ead68d096 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.test.tsx @@ -9,12 +9,11 @@ import uuid from 'uuid'; import React from 'react'; import * as reactTestingLibrary from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../../common/mock/endpoint'; +import type { AppContextTestRender } from '../../../common/mock/endpoint'; +import { createAppRootMockRenderer } from '../../../common/mock/endpoint'; import { ResponseActionsList } from './response_actions_list'; -import { ActionDetails, ActionListApiResponse } from '../../../../common/endpoint/types'; -import { useKibana, useUiSetting$ } from '../../../common/lib/kibana'; -import { createUseUiSetting$Mock } from '../../../common/lib/kibana/kibana_react.mock'; -import { DEFAULT_TIMEPICKER_QUICK_RANGES, MANAGEMENT_PATH } from '../../../../common/constants'; +import type { ActionDetails, ActionListApiResponse } from '../../../../common/endpoint/types'; +import { MANAGEMENT_PATH } from '../../../../common/constants'; import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; let mockUseGetEndpointActionList: { @@ -32,60 +31,79 @@ jest.mock('../../hooks/endpoint/use_get_endpoint_action_list', () => { }; }); -const mockUseUiSetting$ = useUiSetting$ as jest.Mock; -const timepickerRanges = [ - { - from: 'now/d', - to: 'now/d', - display: 'Today', - }, - { - from: 'now/w', - to: 'now/w', - display: 'This week', - }, - { - from: 'now-15m', - to: 'now', - display: 'Last 15 minutes', - }, - { - from: 'now-30m', - to: 'now', - display: 'Last 30 minutes', - }, - { - from: 'now-1h', - to: 'now', - display: 'Last 1 hour', - }, - { - from: 'now-24h', - to: 'now', - display: 'Last 24 hours', - }, - { - from: 'now-7d', - to: 'now', - display: 'Last 7 days', - }, - { - from: 'now-30d', - to: 'now', - display: 'Last 30 days', - }, - { - from: 'now-90d', - to: 'now', - display: 'Last 90 days', - }, - { - from: 'now-1y', - to: 'now', - display: 'Last 1 year', - }, -]; -jest.mock('../../../common/lib/kibana'); +jest.mock('@kbn/kibana-react-plugin/public', () => { + const original = jest.requireActual('@kbn/kibana-react-plugin/public'); + return { + ...original, + useKibana: () => ({ + services: { + uiSettings: { + get: jest.fn().mockImplementation((key) => { + const get = (k: 'dateFormat' | 'timepicker:quickRanges') => { + const x = { + dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', + 'timepicker:quickRanges': [ + { + from: 'now/d', + to: 'now/d', + display: 'Today', + }, + { + from: 'now/w', + to: 'now/w', + display: 'This week', + }, + { + from: 'now-15m', + to: 'now', + display: 'Last 15 minutes', + }, + { + from: 'now-30m', + to: 'now', + display: 'Last 30 minutes', + }, + { + from: 'now-1h', + to: 'now', + display: 'Last 1 hour', + }, + { + from: 'now-24h', + to: 'now', + display: 'Last 24 hours', + }, + { + from: 'now-7d', + to: 'now', + display: 'Last 7 days', + }, + { + from: 'now-30d', + to: 'now', + display: 'Last 30 days', + }, + { + from: 'now-90d', + to: 'now', + display: 'Last 90 days', + }, + { + from: 'now-1y', + to: 'now', + display: 'Last 1 year', + }, + ], + }; + return x[k]; + }; + return get(key); + }), + }, + }, + }), + }; +}); describe('Response Actions List', () => { const testPrefix = 'response-actions-list'; @@ -113,14 +131,6 @@ describe('Response Actions List', () => { reactTestingLibrary.act(() => { history.push(`${MANAGEMENT_PATH}/response_actions`); }); - (useKibana as jest.Mock).mockReturnValue({ services: mockedContext.startServices }); - mockUseUiSetting$.mockImplementation((key, defaultValue) => { - const useUiSetting$Mock = createUseUiSetting$Mock(); - - return key === DEFAULT_TIMEPICKER_QUICK_RANGES - ? [timepickerRanges, jest.fn()] - : useUiSetting$Mock(key, defaultValue); - }); mockUseGetEndpointActionList = { ...baseMockedActionList, @@ -132,16 +142,13 @@ describe('Response Actions List', () => { mockUseGetEndpointActionList = { ...baseMockedActionList, }; - }); - - afterEach(() => { jest.clearAllMocks(); }); - describe('Without agentIds filter', () => { + describe('Without data', () => { it('should show date filters', () => { render(); - expect(renderResult.getByTestId('actionListSuperDatePicker')).toBeTruthy(); + expect(renderResult.getByTestId(`${testPrefix}-super-date-picker`)).toBeTruthy(); }); it('should show empty state when there is no data', async () => { @@ -152,7 +159,9 @@ describe('Response Actions List', () => { render(); expect(renderResult.getByTestId(`${testPrefix}-empty-prompt`)).toBeTruthy(); }); + }); + describe('With Data', () => { it('should show table when there is data', async () => { render(); @@ -171,7 +180,7 @@ describe('Response Actions List', () => { ) .slice(0, 6) .map((col) => col.textContent) - ).toEqual(['Time', 'Command/action', 'User', 'Host', 'Comments', 'Status']); + ).toEqual(['Time', 'Command', 'User', 'Host', 'Comments', 'Status']); }); it('should paginate table when there is data', async () => { @@ -253,8 +262,8 @@ describe('Response Actions List', () => { it('should refresh data when autoRefresh is toggled on', async () => { render(); - const quickMenu = renderResult.getByTestId('superDatePickerToggleQuickMenuButton'); - userEvent.click(quickMenu); + const quickMenuButton = renderResult.getByTestId('superDatePickerToggleQuickMenuButton'); + userEvent.click(quickMenuButton); const toggle = renderResult.getByTestId('superDatePickerToggleRefreshButton'); const intervalInput = renderResult.getByTestId('superDatePickerRefreshIntervalInput'); @@ -266,6 +275,30 @@ describe('Response Actions List', () => { expect(refetchFunction).toHaveBeenCalledTimes(3); }); }); + + it('should refresh data when super date picker refresh button is clicked', async () => { + render(); + + const superRefreshButton = renderResult.getByTestId( + `${testPrefix}-super-date-picker-refresh-button` + ); + userEvent.click(superRefreshButton); + expect(refetchFunction).toHaveBeenCalledTimes(1); + }); + + it('should set date picker with relative dates', async () => { + render(); + const quickMenuButton = renderResult.getByTestId('superDatePickerToggleQuickMenuButton'); + const startDatePopoverButton = renderResult.getByTestId(`superDatePickerShowDatesButton`); + + // shows 24 hours at first + expect(startDatePopoverButton).toHaveTextContent('Last 24 hours'); + + // pick another relative date + userEvent.click(quickMenuButton); + userEvent.click(renderResult.getByTestId('superDatePickerCommonlyUsed_Last_15 minutes')); + expect(startDatePopoverButton).toHaveTextContent('Last 15 minutes'); + }); }); describe('Action status ', () => { @@ -357,7 +390,7 @@ describe('Response Actions List', () => { ) .slice(0, 5) .map((col) => col.textContent) - ).toEqual(['Time', 'Command/action', 'User', 'Comments', 'Status']); + ).toEqual(['Time', 'Command', 'User', 'Comments', 'Status']); }); it('should show a host column when multiple agentIds', async () => { @@ -374,7 +407,7 @@ describe('Response Actions List', () => { ) .slice(0, 6) .map((col) => col.textContent) - ).toEqual(['Time', 'Command/action', 'User', 'Host', 'Comments', 'Status']); + ).toEqual(['Time', 'Command', 'User', 'Host', 'Comments', 'Status']); }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.tsx index 65e7dc13b739d..74c52f1be973b 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.tsx @@ -6,7 +6,6 @@ */ import { - CriteriaWithPagination, EuiAvatar, EuiBadge, EuiBasicTable, @@ -27,12 +26,12 @@ import { } from '@elastic/eui'; import { euiStyled, css } from '@kbn/kibana-react-plugin/common'; -import type { HorizontalAlignment } from '@elastic/eui'; +import type { HorizontalAlignment, CriteriaWithPagination } from '@elastic/eui'; import React, { memo, useCallback, useMemo, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { getEmptyValue } from '../../../common/components/empty_value'; import { FormattedDate } from '../../../common/components/formatted_date'; -import { ActionDetails } from '../../../../common/endpoint/types'; +import type { ActionDetails } from '../../../../common/endpoint/types'; import type { EndpointActionListRequestQuery } from '../../../../common/endpoint/schema/actions'; import { ManagementEmptyStateWrapper } from '../management_empty_state_wrapper'; import { useGetEndpointActionList } from '../../hooks'; @@ -507,6 +506,7 @@ export const ResponseActionsList = memo< Date: Tue, 5 Jul 2022 10:21:01 -0700 Subject: [PATCH 04/81] [Session View] Searchbar fixes (#135502) Co-authored-by: Larry Gregory --- .../common/types/process_tree/index.ts | 2 +- .../public/components/process_tree/helpers.ts | 21 +++++++- .../public/components/process_tree/hooks.ts | 2 +- .../components/process_tree/index.test.tsx | 2 +- .../process_tree_node/index.test.tsx | 17 ++++-- .../components/process_tree_node/index.tsx | 49 +++++++---------- .../process_tree_node/split_text.test.tsx | 6 --- .../process_tree_node/split_text.tsx | 52 +++++++++++-------- .../components/process_tree_node/styles.ts | 3 ++ .../process_tree_node/text_highlight.test.tsx | 26 ++++++++++ .../process_tree_node/text_highlight.tsx | 52 +++++++++++++++++++ 11 files changed, 167 insertions(+), 65 deletions(-) create mode 100644 x-pack/plugins/session_view/public/components/process_tree_node/text_highlight.test.tsx create mode 100644 x-pack/plugins/session_view/public/components/process_tree_node/text_highlight.tsx diff --git a/x-pack/plugins/session_view/common/types/process_tree/index.ts b/x-pack/plugins/session_view/common/types/process_tree/index.ts index b80be0b690135..b59001b1fdfff 100644 --- a/x-pack/plugins/session_view/common/types/process_tree/index.ts +++ b/x-pack/plugins/session_view/common/types/process_tree/index.ts @@ -167,7 +167,7 @@ export interface Process { orphans: Process[]; // currently, orphans are rendered inline with the entry session leaders children parent: Process | undefined; autoExpand: boolean; - searchMatched: string | null; // either false, or set to searchQuery + searchMatched: number[] | null; // either false, or set to searchQuery addEvent(event: ProcessEvent): void; addAlert(alert: ProcessEvent): void; addChild(child: Process): void; diff --git a/x-pack/plugins/session_view/public/components/process_tree/helpers.ts b/x-pack/plugins/session_view/public/components/process_tree/helpers.ts index 9a0834a015476..5ec8568a013b9 100644 --- a/x-pack/plugins/session_view/public/components/process_tree/helpers.ts +++ b/x-pack/plugins/session_view/public/components/process_tree/helpers.ts @@ -5,6 +5,7 @@ * 2.0. */ import uuid from 'uuid'; +import { escapeRegExp } from 'lodash'; import { sortProcesses } from '../../../common/utils/sort_processes'; import { AlertStatusEventEntityIdMap, @@ -210,7 +211,10 @@ export const searchProcessTree = ( // for now plain text search is limited to searching process.working_directory + process.args const text = `${workingDirectory ?? ''} ${args?.join(' ')}`; - process.searchMatched = text.includes(searchQuery) ? searchQuery : null; + const searchMatch = [...text.matchAll(new RegExp(escapeRegExp(searchQuery), 'gi'))]; + + process.searchMatched = + searchMatch.length > 0 ? getSearchMatchedIndices(text, searchMatch) : null; if (process.searchMatched) { results.push(process); @@ -223,6 +227,21 @@ export const searchProcessTree = ( return results.sort(sortProcesses); }; +const getSearchMatchedIndices = (text: string, matches: RegExpMatchArray[]) => { + return text.split('').reduce((accum, _, idx) => { + const findMatch = matches.find( + (match) => + match.index !== undefined && idx >= match.index && idx < match.index + match[0].length + ); + + if (findMatch) { + accum = [...accum, idx]; + } + + return accum; + }, [] as number[]); +}; + // Iterate over all processes in processMap, and mark each process (and it's ancestors) for auto expansion if: // a) the process was "user entered" (aka an interactive group leader) // b) we are jumping to a specific process diff --git a/x-pack/plugins/session_view/public/components/process_tree/hooks.ts b/x-pack/plugins/session_view/public/components/process_tree/hooks.ts index c742c7cd59569..3b33db65f8274 100644 --- a/x-pack/plugins/session_view/public/components/process_tree/hooks.ts +++ b/x-pack/plugins/session_view/public/components/process_tree/hooks.ts @@ -41,7 +41,7 @@ export class ProcessImpl implements Process { children: Process[]; parent: Process | undefined; autoExpand: boolean; - searchMatched: string | null; + searchMatched: number[] | null; orphans: Process[]; constructor(id: string) { diff --git a/x-pack/plugins/session_view/public/components/process_tree/index.test.tsx b/x-pack/plugins/session_view/public/components/process_tree/index.test.tsx index 2ba29107661c5..0f0d1daffe36b 100644 --- a/x-pack/plugins/session_view/public/components/process_tree/index.test.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree/index.test.tsx @@ -111,7 +111,7 @@ describe('ProcessTree component', () => { it('When Verbose mode is ON, it should show all childrens', () => { renderResult = mockedContext.render(); - expect(renderResult.queryByText('cat')).toBeTruthy(); + expect(renderResult.queryByRole('document', { name: '/home/vagrant cat' })).toBeTruthy(); }); }); }); diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/index.test.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/index.test.tsx index cff05c5c1003b..857c791d81a3a 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/index.test.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_node/index.test.tsx @@ -294,14 +294,23 @@ describe('ProcessTreeNode component', () => { }); describe('Search', () => { it('highlights text within the process node line item if it matches the searchQuery', () => { + const searchQuery = '/vagr'; // set a mock search matched indicator for the process (typically done by ProcessTree/helpers.ts) - processMock.searchMatched = '/vagr'; + const processMockClone = { ...processMock, searchMatched: [5, 6, 7, 8, 9] }; - renderResult = mockedContext.render(); + renderResult = mockedContext.render( + + ); + expect(renderResult.queryAllByTestId(`sessionView:splitTextIsHighlighted`)).toHaveLength( + searchQuery.length + ); expect( - renderResult.getByTestId('sessionView:processNodeSearchHighlight').textContent - ).toEqual('/vagr'); + renderResult + .queryAllByTestId(`sessionView:splitTextIsHighlighted`) + .map(({ textContent }) => textContent) + .join('') + ).toEqual(searchQuery); // ensures we are showing the rest of the info, and not replacing it with just the match. const { process } = props.process.getDetails(); diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx index f65cb0f25530a..47f56b6c51a42 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx @@ -12,8 +12,6 @@ * 2.0. */ import React, { - useRef, - useLayoutEffect, useState, useEffect, MouseEvent, @@ -35,6 +33,7 @@ import { useStyles } from './styles'; import { SplitText } from './split_text'; import { Nbsp } from './nbsp'; import { useDateFormat } from '../../hooks'; +import { TextHighlight } from './text_highlight'; export interface ProcessDeps { process: Process; @@ -74,14 +73,16 @@ export function ProcessTreeNode({ loadPreviousButton, loadNextButton, }: ProcessDeps) { - const textRef = useRef(null); - const [childrenExpanded, setChildrenExpanded] = useState(isSessionLeader || process.autoExpand); const [alertsExpanded, setAlertsExpanded] = useState(false); const { searchMatched } = process; const dateFormat = useDateFormat(); + useEffect(() => { + setChildrenExpanded(process.autoExpand); + }, [process.autoExpand]); + // forces nodes to expand if the selected process is a descendant useEffect(() => { if (!childrenExpanded && selectedProcess) { @@ -91,10 +92,6 @@ export function ProcessTreeNode({ } }, [selectedProcess, process, childrenExpanded]); - useEffect(() => { - setChildrenExpanded(process.autoExpand); - }, [process.autoExpand]); - const alerts = process.getAlerts(); const hasAlerts = useMemo(() => !!alerts.length, [alerts]); const hasInvestigatedAlert = useMemo( @@ -135,22 +132,6 @@ export function ProcessTreeNode({ } }, [hasInvestigatedAlert]); - useLayoutEffect(() => { - if (searchMatched !== null && textRef.current) { - const regex = new RegExp(searchMatched); - const text = textRef.current.textContent; - - if (text) { - const html = text.replace(regex, (match) => { - return `${match}`; - }); - - // eslint-disable-next-line no-unsanitized/property - textRef.current.innerHTML = '' + html + ''; - } - } - }, [searchMatched, styles.searchHighlight]); - const onChildrenToggle = useCallback(() => { setChildrenExpanded(!childrenExpanded); }, [childrenExpanded]); @@ -272,12 +253,20 @@ export function ProcessTreeNode({ - - {dataOrDash(workingDirectory)} - - {dataOrDash(args?.[0])} - - {args?.slice(1).join(' ') || ''} + + + + {dataOrDash(workingDirectory) + ' '} + + {`${dataOrDash(args?.[0])}`} + + {args && args.length > 1 ? ' ' + args?.slice(1).join(' ') : ''} + + )} diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/split_text.test.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/split_text.test.tsx index eaa18b18d81cf..88aaf6f2fff0f 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/split_text.test.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_node/split_text.test.tsx @@ -19,10 +19,4 @@ describe('SplitText component', () => { } expect(renderResult.container.textContent?.replace(/\s+/g, ' ')).toEqual(text); }); - it('should provide an acessible label for screen readers', async () => { - const text = 'hello world'; - - const renderResult = render({text}); - expect(renderResult.queryByRole('document', { name: text })).toBeTruthy(); - }); }); diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/split_text.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/split_text.tsx index d31590c9ab967..6ac7a12aa0f4e 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/split_text.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_node/split_text.tsx @@ -10,30 +10,40 @@ import { CSSObject } from '@emotion/react'; type Props = { children: string; + highlightIndices?: number[]; + highlightStyle?: CSSObject; role?: string; }; -const css: CSSObject = { - '&&': { - display: 'inline', - fontSize: 0, - lineHeight: 0, - }, -}; - // Split a text into multiple spans, each of which a single character. This is // useful for creating inline "like" text but still having control over the blocks // exclusive features, such height or line-height. -// It adds a `aria-label` attribute to a parent span, which is used by screen readers to -// read the text as a single block. -export const SplitText = ({ children, role = 'document', ...props }: Props) => ( - - {children.split('').map(function (char, index) { - return ( - - ); - })} - -); + +const css: CSSObject = {}; + +export const SplitText = ({ + children, + role = 'document', + highlightIndices, + highlightStyle, + ...props +}: Props) => { + return ( + <> + {children.split('').map(function (char, index) { + const isHighlighted = highlightIndices?.includes(index); + return ( + + ); + })} + + ); +}; diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/styles.ts b/x-pack/plugins/session_view/public/components/process_tree_node/styles.ts index 54dbdb1bc4565..3936fc35aac81 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/styles.ts +++ b/x-pack/plugins/session_view/public/components/process_tree_node/styles.ts @@ -109,6 +109,9 @@ export const useStyles = ({ backgroundColor: bgColor, width: `calc(100% + ${depth} * ${TREE_INDENT} + ${PROCESS_TREE_LEFT_PADDING})`, }, + '.euiToolTipAnchor': { + verticalAlign: 'middle', + }, }; const textSection: CSSObject = { diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/text_highlight.test.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/text_highlight.test.tsx new file mode 100644 index 0000000000000..733327ab23e57 --- /dev/null +++ b/x-pack/plugins/session_view/public/components/process_tree_node/text_highlight.test.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 { render } from '@testing-library/react'; +import { TextHighlight } from './text_highlight'; + +describe('TextHighlight component', () => { + it('should provide an acessible label for screen readers', async () => { + const text = 'hello world'; + + const renderResult = render( + + <> + {text} + + + ); + + expect(renderResult.queryByRole('document', { name: text })).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/text_highlight.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/text_highlight.tsx new file mode 100644 index 0000000000000..6d21726e0d430 --- /dev/null +++ b/x-pack/plugins/session_view/public/components/process_tree_node/text_highlight.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { CSSObject } from '@emotion/react'; + +type Props = { + children: JSX.Element | JSX.Element[]; + text: string; + match: null | number[]; + highlightStyle: any; +}; + +const css: CSSObject = { + '&&': { + display: 'inline', + fontSize: 0, + lineHeight: 0, + verticalAlign: 'middle', + }, +}; +// Component that takes an array of matching indices in a text and pass down a highlight +// css style prop across its children +// Currently it works only for a single child level, designed to be in combination with SplitText +// It adds a `aria-label` attribute to a parent span, which is used by screen readers to +// read the text as a single block. +export const TextHighlight = ({ children, match, text, highlightStyle }: Props): JSX.Element => { + let startIdx = 0; + + return ( + + {!match + ? children + : React.Children.map(children, (child) => { + const childText = child.props.children; + const childTextLength = childText.length; + + const highlightIndices = match.map((v) => v - startIdx); + startIdx += childTextLength; + + return React.cloneElement(child, { + highlightIndices, + highlightStyle, + }); + })} + + ); +}; From 91739ce834761ed917cc2528d44c8efc057468c0 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Tue, 5 Jul 2022 11:27:45 -0600 Subject: [PATCH 05/81] Mock getFormatterForField for storybook (#135670) --- .../public/__stories__/fixtures/flights.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/plugins/presentation_util/public/__stories__/fixtures/flights.ts b/src/plugins/presentation_util/public/__stories__/fixtures/flights.ts index c574d18b8de31..17cedff90ad23 100644 --- a/src/plugins/presentation_util/public/__stories__/fixtures/flights.ts +++ b/src/plugins/presentation_util/public/__stories__/fixtures/flights.ts @@ -8,6 +8,11 @@ import { map, uniq } from 'lodash'; import { DataView, DataViewField, IIndexPatternFieldList } from '@kbn/data-views-plugin/public'; +import { + FieldFormatsGetConfigFn, + NumberFormat, + StringFormat, +} from '@kbn/field-formats-plugin/common'; import { flights } from './flights_data'; export type Flight = typeof flights[number]; @@ -53,6 +58,8 @@ const numberFields = [ 'FlightTimeMin', ]; +const getConfig = (() => {}) as FieldFormatsGetConfigFn; + export const flightFieldByName: { [key: string]: DataViewField } = {}; flightFieldNames.forEach( (flightFieldName) => @@ -72,6 +79,10 @@ export const storybookFlightsDataView: DataView = { title: 'demo data flights', fields: flightFields as unknown as IIndexPatternFieldList, getFieldByName: (name: string) => flightFieldByName[name], + getFormatterForField: (field: DataViewField) => { + if (numberFields.includes(field.name)) return new NumberFormat({}, getConfig); + return new StringFormat({}, getConfig); + }, } as unknown as DataView; export const getFlightOptions = (field: string) => uniq(map(flights, field)).sort(); From 98dfdf1285297b6595645840e7af5d0d7cf850ee Mon Sep 17 00:00:00 2001 From: Miriam <31922082+MiriamAparicio@users.noreply.github.com> Date: Tue, 5 Jul 2022 19:00:28 +0100 Subject: [PATCH 06/81] Rename maxServiceSelections to maxServiceSelection (#135730) --- x-pack/plugins/apm/server/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/server/index.ts b/x-pack/plugins/apm/server/index.ts index 6c853ea02a34b..5058b86249f2d 100644 --- a/x-pack/plugins/apm/server/index.ts +++ b/x-pack/plugins/apm/server/index.ts @@ -99,7 +99,7 @@ export const config: PluginConfigDescriptor = { { level: 'warning' } ), renameFromRoot( - 'xpack.apm.maxServiceSelections', + 'xpack.apm.maxServiceSelection', `uiSettings.overrides[${maxSuggestions}]`, { level: 'warning' } ), From 1f5ab7d196cce956d8c7a459273ac51e4477fe03 Mon Sep 17 00:00:00 2001 From: Julian Gernun Date: Tue, 5 Jul 2022 20:31:33 +0200 Subject: [PATCH 07/81] Custom inline/row actions for alerts table (#134015) * first commit * add actionColumn related hook and prop * move showExpandToDetails to the right place * remove debugging comments * fix type leadingControlColumns * remove not needed changes * move column width calculation to its own module * some refactoring + first tests * test + refactor * add theme vars in width calc + better naming * remove placeholder icons * remove not needed dependencies * refactor use props object instead of jsx * remove debug code * actions depending on row * refactor so jsx can be used instead of props * remove not needed type * add suggested changes --- .../alerts_table/alerts_table.test.tsx | 99 +++++++++++++++++++ .../sections/alerts_table/alerts_table.tsx | 94 ++++++++++-------- .../triggers_actions_ui/public/types.ts | 5 + 3 files changed, 159 insertions(+), 39 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.test.tsx index 1fda39cd84ee9..3a7d693ce6375 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.test.tsx @@ -12,6 +12,7 @@ import { EcsFieldsResponse } from '@kbn/rule-registry-plugin/common/search_strat import { AlertsTable } from './alerts_table'; import { AlertsField } from '../../../types'; +import { EuiButtonIcon, EuiFlexItem } from '@elastic/eui'; jest.mock('@kbn/data-plugin/public'); @@ -129,5 +130,103 @@ describe('AlertsTable', () => { expect(wrapper.queryByTestId('testCell')).not.toBe(null); }); }); + + describe('actions column', () => { + it('should load actions set in config', () => { + const customTableProps = { + ...tableProps, + alertsTableConfiguration: { + ...alertsTableConfiguration, + useActionsColumn: () => { + return { + renderCustomActionsRow: () => { + return ( + <> + + {}} + size="s" + data-test-subj="testActionColumn" + /> + + + {}} + size="s" + data-test-subj="testActionColumn2" + /> + + + ); + }, + }; + }, + }, + }; + + const { queryByTestId } = render(); + expect(queryByTestId('testActionColumn')).not.toBe(null); + expect(queryByTestId('testActionColumn2')).not.toBe(null); + expect(queryByTestId('expandColumnCellOpenFlyoutButton-0')).not.toBe(null); + }); + + it('should not add expansion action when not set', () => { + const customTableProps = { + ...tableProps, + showExpandToDetails: false, + alertsTableConfiguration: { + ...alertsTableConfiguration, + useActionsColumn: () => { + return { + renderCustomActionsRow: () => { + return ( + <> + + {}} + size="s" + data-test-subj="testActionColumn" + /> + + + {}} + size="s" + data-test-subj="testActionColumn2" + /> + + + ); + }, + }; + }, + }, + }; + + const { queryByTestId } = render(); + expect(queryByTestId('testActionColumn')).not.toBe(null); + expect(queryByTestId('testActionColumn2')).not.toBe(null); + expect(queryByTestId('expandColumnCellOpenFlyoutButton-0')).toBe(null); + }); + + it('should render no action column if there is neither the action nor the expand action config is set', () => { + const customTableProps = { + ...tableProps, + showExpandToDetails: false, + }; + + const { queryByTestId } = render(); + expect(queryByTestId('expandColumnHeaderLabel')).toBe(null); + expect(queryByTestId('expandColumnCellOpenFlyoutButton')).toBe(null); + }); + }); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx index a46105454bea0..37108a2da260d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx @@ -22,9 +22,11 @@ import { ALERTS_TABLE_CONTROL_COLUMNS_ACTIONS_LABEL, ALERTS_TABLE_CONTROL_COLUMNS_VIEW_DETAILS_LABEL, } from './translations'; + import './alerts_table.scss'; export const ACTIVE_ROW_CLASS = 'alertsTableActiveRow'; +const DEFAULT_ACTIONS_COLUMNS_WIDTH = 75; const AlertsFlyout = lazy(() => import('./alerts_flyout')); const GridStyles: EuiDataGridStyle = { border: 'none', @@ -57,6 +59,8 @@ const AlertsTable: React.FunctionComponent = (props: AlertsTab pageIndex: activePage, pageSize: props.pageSize, }); + const { useActionsColumn = () => ({ renderCustomActionsRow: undefined, width: undefined }) } = + props.alertsTableConfiguration; const [visibleColumns, setVisibleColumns] = useState(props.visibleColumns); @@ -71,49 +75,61 @@ const AlertsTable: React.FunctionComponent = (props: AlertsTab [onColumnsChange, props.columns] ); + const { renderCustomActionsRow, width: actionsColumnWidth = DEFAULT_ACTIONS_COLUMNS_WIDTH } = + useActionsColumn(); + const leadingControlColumns = useMemo(() => { + if (!props.showExpandToDetails && !renderCustomActionsRow) return props.leadingControlColumns; + return [ - ...(props.showExpandToDetails - ? [ - { - id: 'expandColumn', - width: 75, - headerCellRender: () => { - return ( - - {ALERTS_TABLE_CONTROL_COLUMNS_ACTIONS_LABEL} - - ); - }, - rowCellRender: (cveProps: EuiDataGridCellValueElementProps) => { - const { visibleRowIndex } = cveProps as EuiDataGridCellValueElementProps & { - visibleRowIndex: number; - }; - return ( - - - - { - setFlyoutAlertIndex(visibleRowIndex); - }} - data-test-subj={`expandColumnCellOpenFlyoutButton-${visibleRowIndex}`} - aria-label={ALERTS_TABLE_CONTROL_COLUMNS_VIEW_DETAILS_LABEL} - /> - - - - ); - }, - }, - ] - : []), + { + id: 'expandColumn', + width: actionsColumnWidth, + headerCellRender: () => { + return ( + + {ALERTS_TABLE_CONTROL_COLUMNS_ACTIONS_LABEL} + + ); + }, + rowCellRender: (cveProps: EuiDataGridCellValueElementProps) => { + const { visibleRowIndex } = cveProps as EuiDataGridCellValueElementProps & { + visibleRowIndex: number; + }; + + return ( + + {props.showExpandToDetails && ( + + + { + setFlyoutAlertIndex(visibleRowIndex); + }} + data-test-subj={`expandColumnCellOpenFlyoutButton-${visibleRowIndex}`} + aria-label={ALERTS_TABLE_CONTROL_COLUMNS_VIEW_DETAILS_LABEL} + /> + + + )} + {renderCustomActionsRow && renderCustomActionsRow(alerts[visibleRowIndex])} + + ); + }, + }, ...props.leadingControlColumns, ]; - }, [props.leadingControlColumns, props.showExpandToDetails, setFlyoutAlertIndex]); + }, [ + actionsColumnWidth, + alerts, + props.leadingControlColumns, + props.showExpandToDetails, + renderCustomActionsRow, + setFlyoutAlertIndex, + ]); useEffect(() => { // Row classes do not deal with visible row indices so we need to handle page offset diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index 32ef0d6239d76..80572ebb1e7f4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -413,6 +413,7 @@ export type AlertTableFlyoutComponent = | React.FunctionComponent | React.LazyExoticComponent> | null; + export interface AlertsTableConfigurationRegistry { id: string; columns: EuiDataGridColumn[]; @@ -423,6 +424,10 @@ export interface AlertsTableConfigurationRegistry { }; sort?: SortCombinations[]; getRenderCellValue?: GetRenderCellValue; + useActionsColumn?: () => { + renderCustomActionsRow: (alert?: EcsFieldsResponse) => JSX.Element; + width?: number; + }; } export interface AlertsTableFlyoutBaseProps { From 2aec10c6a58380f5d8818b7c6598e5d9b12764c2 Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Tue, 5 Jul 2022 20:54:33 +0200 Subject: [PATCH 08/81] [Canvas] Fix check for "by-ref" embeddable during migration (#135738) --- .../functions/external/embeddable.ts | 6 +++--- .../canvas/exports/8.1.embeddable_test.ndjson | 6 ++++++ .../apps/canvas/migrations_smoke_test.ts | 21 ++++++++++++++++--- 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 x-pack/test/functional/apps/canvas/exports/8.1.embeddable_test.ndjson diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/embeddable.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/embeddable.ts index 204021564d1f0..aee62f2c3de2a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/external/embeddable.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/external/embeddable.ts @@ -56,12 +56,12 @@ export function embeddableFunctionFactory({ migrateFn: MigrateFunction ): MigrateFunction => (state: ExpressionAstFunction): ExpressionAstFunction => { - const embeddableInput = decode(state.arguments.config[0] as string); + const embeddableInput = decode(state.arguments.config[0] as string) as EmbeddableInput; const embeddableType = state.arguments.type[0]; - if (embeddableInput.explicitInput.attributes || embeddableInput.explicitInput.savedVis) { - const migratedInput = migrateFn({ ...embeddableInput, type: embeddableType }); + if (embeddableInput.savedObjectId === undefined) { + const migratedInput = migrateFn({ ...embeddableInput, type: embeddableType as string }); state.arguments.config[0] = encode(migratedInput); state.arguments.type[0] = migratedInput.type as string; } diff --git a/x-pack/test/functional/apps/canvas/exports/8.1.embeddable_test.ndjson b/x-pack/test/functional/apps/canvas/exports/8.1.embeddable_test.ndjson new file mode 100644 index 0000000000000..3ec13414a35a1 --- /dev/null +++ b/x-pack/test/functional/apps/canvas/exports/8.1.embeddable_test.ndjson @@ -0,0 +1,6 @@ +{"attributes":{"fieldAttrs":"{\"products.manufacturer\":{\"count\":1},\"products.price\":{\"count\":1},\"products.product_name\":{\"count\":1},\"total_quantity\":{\"count\":1}}","fieldFormatMap":"{\"taxful_total_price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.[00]\"}},\"products.price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.00\"}},\"taxless_total_price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.00\"}},\"products.taxless_price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.00\"}},\"products.taxful_price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.00\"}},\"products.min_price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.00\"}},\"products.base_unit_price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.00\"}},\"products.base_price\":{\"id\":\"number\",\"params\":{\"pattern\":\"$0,0.00\"}}}","fields":"[]","runtimeFieldMap":"{}","timeFieldName":"order_date","title":"kibana_sample_data_ecommerce","typeMeta":"{}"},"coreMigrationVersion":"8.1.3","id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2022-06-22T13:05:00.290Z","version":"WzE5OCwxXQ=="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Agg Viz","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Agg Viz\",\"type\":\"area\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"}],\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{},\"style\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":true,\"truncate\":100},\"title\":{\"text\":\"\"},\"style\":{}}],\"seriesParams\":[{\"show\":true,\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"circlesRadius\":1,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"detailedTooltip\":true,\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"addLegend\":true,\"legendPosition\":\"right\",\"fittingFunction\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"truncateLegend\":true,\"maxLegendLines\":1,\"radiusRatio\":9,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}}}"},"coreMigrationVersion":"8.1.3","id":"21815490-f242-11ec-865d-c9490d79025a","migrationVersion":{"visualization":"8.0.0"},"references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2022-06-22T15:43:58.563Z","version":"WzM4OSwxXQ=="} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"5228311a-6224-495f-80a7-2e9218844cff":{"columnOrder":["3a9ec66c-f6fd-4a3d-91ab-27b7dc421398","b0b90b4f-e836-461f-863a-80144bf2e011"],"columns":{"3a9ec66c-f6fd-4a3d-91ab-27b7dc421398":{"dataType":"string","isBucketed":true,"label":"Top values of currency","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"b0b90b4f-e836-461f-863a-80144bf2e011","type":"column"},"orderDirection":"desc","otherBucket":true,"parentFormat":{"id":"terms"},"size":5},"scale":"ordinal","sourceField":"currency"},"b0b90b4f-e836-461f-863a-80144bf2e011":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"___records___"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"layers":[{"accessors":["b0b90b4f-e836-461f-863a-80144bf2e011"],"layerId":"5228311a-6224-495f-80a7-2e9218844cff","layerType":"data","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"3a9ec66c-f6fd-4a3d-91ab-27b7dc421398"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide","yLeftExtent":{"mode":"full"},"yRightExtent":{"mode":"full"}}},"title":"demo lens","visualizationType":"lnsXY"},"coreMigrationVersion":"8.1.3","id":"dffc15e0-f22e-11ec-865d-c9490d79025a","migrationVersion":{"lens":"8.1.0"},"references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"indexpattern-datasource-layer-5228311a-6224-495f-80a7-2e9218844cff","type":"index-pattern"}],"type":"lens","updated_at":"2022-06-22T13:26:08.304Z","version":"WzI5MywxXQ=="} +{"attributes":{"description":"","layerListJSON":"[{\"id\":\"0hmz5\",\"alpha\":1,\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true,\"lightModeDefault\":\"road_map_desaturated\"},\"visible\":true,\"style\":{},\"type\":\"EMS_VECTOR_TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"7ameq\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"world_countries\",\"tooltipProperties\":[\"name\",\"iso2\"]},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"__kbnjoin__count__741db9c6-8ebb-4ea9-9885-b6b4ac019d14\",\"origin\":\"join\"},\"color\":\"Green to Red\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\",\"joins\":[{\"leftField\":\"iso2\",\"right\":{\"type\":\"ES_TERM_SOURCE\",\"id\":\"741db9c6-8ebb-4ea9-9885-b6b4ac019d14\",\"indexPatternTitle\":\"kibana_sample_data_ecommerce\",\"term\":\"geoip.country_iso_code\",\"indexPatternRefName\":\"layer_1_join_0_index_pattern\",\"metrics\":[{\"type\":\"count\",\"label\":\"sales count\"}],\"applyGlobalQuery\":true}}]},{\"id\":\"jmtgf\",\"label\":\"United States\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"usa_states\",\"tooltipProperties\":[\"name\"]},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"__kbnjoin__count__30a0ec24-49b6-476a-b4ed-6c1636333695\",\"origin\":\"join\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"type\":\"ES_TERM_SOURCE\",\"id\":\"30a0ec24-49b6-476a-b4ed-6c1636333695\",\"indexPatternTitle\":\"kibana_sample_data_ecommerce\",\"term\":\"geoip.region_name\",\"indexPatternRefName\":\"layer_2_join_0_index_pattern\",\"metrics\":[{\"type\":\"count\",\"label\":\"sales count\"}],\"applyGlobalQuery\":true}}]},{\"id\":\"ui5f8\",\"label\":\"France\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"france_departments\",\"tooltipProperties\":[\"label_en\"]},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"__kbnjoin__count__e325c9da-73fa-4b3b-8b59-364b99370826\",\"origin\":\"join\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\",\"joins\":[{\"leftField\":\"label_en\",\"right\":{\"type\":\"ES_TERM_SOURCE\",\"id\":\"e325c9da-73fa-4b3b-8b59-364b99370826\",\"indexPatternTitle\":\"kibana_sample_data_ecommerce\",\"term\":\"geoip.region_name\",\"indexPatternRefName\":\"layer_3_join_0_index_pattern\",\"metrics\":[{\"type\":\"count\",\"label\":\"sales count\"}],\"applyGlobalQuery\":true}}]},{\"id\":\"y3fjb\",\"label\":\"United Kingdom\",\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"sourceDescriptor\":{\"type\":\"EMS_FILE\",\"id\":\"uk_subdivisions\",\"tooltipProperties\":[\"label_en\"]},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"__kbnjoin__count__612d805d-8533-43a9-ac0e-cbf51fe63dcd\",\"origin\":\"join\"},\"color\":\"Blues\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\",\"joins\":[{\"leftField\":\"label_en\",\"right\":{\"type\":\"ES_TERM_SOURCE\",\"id\":\"612d805d-8533-43a9-ac0e-cbf51fe63dcd\",\"indexPatternTitle\":\"kibana_sample_data_ecommerce\",\"term\":\"geoip.region_name\",\"indexPatternRefName\":\"layer_4_join_0_index_pattern\",\"metrics\":[{\"type\":\"count\",\"label\":\"sales count\"}],\"applyGlobalQuery\":true}}]},{\"id\":\"c54wk\",\"label\":\"Sales\",\"minZoom\":9,\"maxZoom\":24,\"alpha\":1,\"sourceDescriptor\":{\"id\":\"04c983b0-8cfa-4e6a-a64b-52c10b7008fe\",\"type\":\"ES_SEARCH\",\"geoField\":\"geoip.location\",\"limit\":2048,\"filterByMapBounds\":true,\"tooltipProperties\":[\"category\",\"customer_gender\",\"manufacturer\",\"order_id\",\"total_quantity\",\"total_unique_products\",\"taxful_total_price\",\"order_date\",\"geoip.region_name\",\"geoip.country_iso_code\"],\"indexPatternRefName\":\"layer_5_source_index_pattern\",\"applyGlobalQuery\":true,\"scalingType\":\"LIMIT\"},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"taxful_total_price\",\"origin\":\"source\"},\"color\":\"Greens\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\"},{\"id\":\"qvhh3\",\"label\":\"Total Sales Revenue\",\"minZoom\":0,\"maxZoom\":9,\"alpha\":1,\"sourceDescriptor\":{\"type\":\"ES_GEO_GRID\",\"resolution\":\"COARSE\",\"id\":\"aa7f87b8-9dc5-42be-b19e-1a2fa09b6cad\",\"geoField\":\"geoip.location\",\"requestType\":\"point\",\"metrics\":[{\"type\":\"count\",\"label\":\"sales count\"},{\"type\":\"sum\",\"field\":\"taxful_total_price\",\"label\":\"total sales price\"}],\"indexPatternRefName\":\"layer_6_source_index_pattern\",\"applyGlobalQuery\":true},\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"doc_count\",\"origin\":\"source\"},\"color\":\"Greens\",\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"sum_of_taxful_total_price\",\"origin\":\"source\"},\"minSize\":1,\"maxSize\":20,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"labelText\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"sum_of_taxful_total_price\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"labelSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"name\":\"sum_of_taxful_total_price\",\"origin\":\"source\"},\"minSize\":12,\"maxSize\":24,\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3}}},\"labelBorderSize\":{\"options\":{\"size\":\"MEDIUM\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}}}},\"type\":\"GEOJSON_VECTOR\"}]","mapStateJSON":"{\"zoom\":2.11,\"center\":{\"lon\":-15.07605,\"lat\":45.88578},\"timeFilters\":{\"from\":\"now-7d\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"settings\":{\"autoFitToDataBounds\":false}}","title":"[eCommerce] Orders by Country","uiStateJSON":"{\"isDarkMode\":false}"},"coreMigrationVersion":"8.1.3","id":"2c9c1f60-1909-11e9-919b-ffe5949a18d2","migrationVersion":{"map":"8.1.0"},"references":[{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"layer_1_join_0_index_pattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"layer_2_join_0_index_pattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"layer_3_join_0_index_pattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"layer_4_join_0_index_pattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"layer_5_source_index_pattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"layer_6_source_index_pattern","type":"index-pattern"}],"type":"map","updated_at":"2022-06-22T13:05:00.290Z","version":"WzIxNywxXQ=="} +{"attributes":{"@created":"2022-06-23T12:48:05.589Z","@timestamp":"2022-06-23T12:49:52.382Z","assets":{},"colors":["#37988d","#c19628","#b83c6f","#3f9939","#1785b0","#ca5f35","#45bdb0","#f2bc33","#e74b8b","#4fbf48","#1ea6dc","#fd7643","#72cec3","#f5cc5d","#ec77a8","#7acf74","#4cbce4","#fd986f","#a1ded7","#f8dd91","#f2a4c5","#a6dfa2","#86d2ed","#fdba9f","#000000","#444444","#777777","#BBBBBB","#FFFFFF","rgba(255,255,255,0)"],"css":".canvasPage {\n\n}","height":720,"isWriteable":true,"name":"Test Workpad","page":1,"pages":[{"elements":[{"expression":"embeddable \n config=\"eyJ2aWV3TW9kZSI6ImVkaXQiLCJ0aW1lUmFuZ2UiOnsiZnJvbSI6Im5vdy0xNW0iLCJ0byI6Im5vdyJ9LCJkaXNhYmxlVHJpZ2dlcnMiOnRydWUsInJlbmRlck1vZGUiOiJub0ludGVyYWN0aXZpdHkiLCJzYXZlZE9iamVjdElkIjoiMjE4MTU0OTAtZjI0Mi0xMWVjLTg2NWQtYzk0OTBkNzkwMjVhIiwiZmlsdGVycyI6W10sImlkIjoiZWxlbWVudC1jZWI4OTRkNC04MGI0LTRhZmQtOWUwOS0wZGEyOTY4NDExNDcifQ==\" type=\"visualization\"\n| render","filter":null,"id":"element-ceb894d4-80b4-4afd-9e09-0da296841147","position":{"angle":0,"height":300,"left":20,"parent":null,"top":20,"width":500}},{"expression":"embeddable \n config=\"eyJ2aWV3TW9kZSI6ImVkaXQiLCJ0aW1lUmFuZ2UiOnsiZnJvbSI6Im5vdy0xNW0iLCJ0byI6Im5vdyJ9LCJkaXNhYmxlVHJpZ2dlcnMiOnRydWUsInJlbmRlck1vZGUiOiJub0ludGVyYWN0aXZpdHkiLCJzYXZlZE9iamVjdElkIjoiZGZmYzE1ZTAtZjIyZS0xMWVjLTg2NWQtYzk0OTBkNzkwMjVhIiwiZmlsdGVycyI6W10sImlkIjoiZWxlbWVudC1iNzJjYmJlNC1lZWVhLTRiYTMtODhiOC1mZTc3N2M2MDc2ODYifQ==\" type=\"lens\"\n| render","filter":null,"id":"element-b72cbbe4-eeea-4ba3-88b8-fe777c607686","position":{"angle":0,"height":300,"left":27,"parent":null,"top":336,"width":500}},{"expression":"embeddable \n config=\"eyJ2aWV3TW9kZSI6ImVkaXQiLCJ0aW1lUmFuZ2UiOnsiZnJvbSI6Im5vdy0xNW0iLCJ0byI6Im5vdyJ9LCJkaXNhYmxlVHJpZ2dlcnMiOnRydWUsInJlbmRlck1vZGUiOiJub0ludGVyYWN0aXZpdHkiLCJzYXZlZE9iamVjdElkIjoiMmM5YzFmNjAtMTkwOS0xMWU5LTkxOWItZmZlNTk0OWExOGQyIiwiZmlsdGVycyI6W10sImlkIjoiZWxlbWVudC03ZTU3NTJhNC01NjQzLTRmYWUtYTg5ZS1hZWI5MjViZjlkMmIiLCJtYXBDZW50ZXIiOnsibGF0Ijo0NS44ODU3OCwibG9uIjotMTUuMDc2MDUsInpvb20iOjIuMTF9LCJtYXBCdWZmZXIiOnsibWluTG9uIjotOTAsIm1pbkxhdCI6MCwibWF4TG9uIjo0NSwibWF4TGF0Ijo2Ni41MTMyNn0sImlzTGF5ZXJUT0NPcGVuIjp0cnVlLCJvcGVuVE9DRGV0YWlscyI6W10sImhpZGRlbkxheWVycyI6W119\" type=\"map\"\n| render","filter":null,"id":"element-7e5752a4-5643-4fae-a89e-aeb925bf9d2b","position":{"angle":0,"height":291,"left":566,"parent":null,"top":150,"width":364}}],"groups":[],"id":"page-6bc85300-159a-4246-ad13-e967bb80b25f","style":{"background":"#FFF"},"transition":{}},{"elements":[{"expression":"embeddable \n config=\"eyJ2aWV3TW9kZSI6ImVkaXQiLCJ0aW1lUmFuZ2UiOnsiZnJvbSI6Im5vdy0xNW0iLCJ0byI6Im5vdyJ9LCJkaXNhYmxlVHJpZ2dlcnMiOnRydWUsInJlbmRlck1vZGUiOiJub0ludGVyYWN0aXZpdHkiLCJhdHRyaWJ1dGVzIjp7InRpdGxlIjoiIiwidmlzdWFsaXphdGlvblR5cGUiOiJsbnNYWSIsInR5cGUiOiJsZW5zIiwicmVmZXJlbmNlcyI6W3sidHlwZSI6ImluZGV4LXBhdHRlcm4iLCJpZCI6ImZmOTU5ZDQwLWI4ODAtMTFlOC1hNmQ5LWU1NDZmZTJiYmE1ZiIsIm5hbWUiOiJpbmRleHBhdHRlcm4tZGF0YXNvdXJjZS1jdXJyZW50LWluZGV4cGF0dGVybiJ9LHsidHlwZSI6ImluZGV4LXBhdHRlcm4iLCJpZCI6ImZmOTU5ZDQwLWI4ODAtMTFlOC1hNmQ5LWU1NDZmZTJiYmE1ZiIsIm5hbWUiOiJpbmRleHBhdHRlcm4tZGF0YXNvdXJjZS1sYXllci0wYTdhMDU3ZS04YzA5LTQyMTQtYjJiNy1mOTRlNmU1MjMwYjgifV0sInN0YXRlIjp7InZpc3VhbGl6YXRpb24iOnsibGVnZW5kIjp7ImlzVmlzaWJsZSI6dHJ1ZSwicG9zaXRpb24iOiJyaWdodCJ9LCJ2YWx1ZUxhYmVscyI6ImhpZGUiLCJmaXR0aW5nRnVuY3Rpb24iOiJOb25lIiwieUxlZnRFeHRlbnQiOnsibW9kZSI6ImZ1bGwifSwieVJpZ2h0RXh0ZW50Ijp7Im1vZGUiOiJmdWxsIn0sImF4aXNUaXRsZXNWaXNpYmlsaXR5U2V0dGluZ3MiOnsieCI6dHJ1ZSwieUxlZnQiOnRydWUsInlSaWdodCI6dHJ1ZX0sInRpY2tMYWJlbHNWaXNpYmlsaXR5U2V0dGluZ3MiOnsieCI6dHJ1ZSwieUxlZnQiOnRydWUsInlSaWdodCI6dHJ1ZX0sImxhYmVsc09yaWVudGF0aW9uIjp7IngiOjAsInlMZWZ0IjowLCJ5UmlnaHQiOjB9LCJncmlkbGluZXNWaXNpYmlsaXR5U2V0dGluZ3MiOnsieCI6dHJ1ZSwieUxlZnQiOnRydWUsInlSaWdodCI6dHJ1ZX0sInByZWZlcnJlZFNlcmllc1R5cGUiOiJiYXJfc3RhY2tlZCIsImxheWVycyI6W3sibGF5ZXJJZCI6IjBhN2EwNTdlLThjMDktNDIxNC1iMmI3LWY5NGU2ZTUyMzBiOCIsImFjY2Vzc29ycyI6WyJmZjdmODczMy0zODEwLTQzYjctOWMxZS05ZjBmZTZlY2ZjNGUiXSwicG9zaXRpb24iOiJ0b3AiLCJzZXJpZXNUeXBlIjoiYmFyX3N0YWNrZWQiLCJzaG93R3JpZGxpbmVzIjpmYWxzZSwibGF5ZXJUeXBlIjoiZGF0YSIsInhBY2Nlc3NvciI6Ijg4MTM0MDcwLTJlNGItNGVjZi1hMTUwLTgzMGFmNWMzOTAzZCJ9XX0sInF1ZXJ5Ijp7InF1ZXJ5IjoiIiwibGFuZ3VhZ2UiOiJrdWVyeSJ9LCJmaWx0ZXJzIjpbXSwiZGF0YXNvdXJjZVN0YXRlcyI6eyJpbmRleHBhdHRlcm4iOnsibGF5ZXJzIjp7IjBhN2EwNTdlLThjMDktNDIxNC1iMmI3LWY5NGU2ZTUyMzBiOCI6eyJjb2x1bW5zIjp7Ijg4MTM0MDcwLTJlNGItNGVjZi1hMTUwLTgzMGFmNWMzOTAzZCI6eyJsYWJlbCI6IlRvcCB2YWx1ZXMgb2YgY3VycmVuY3kiLCJkYXRhVHlwZSI6InN0cmluZyIsIm9wZXJhdGlvblR5cGUiOiJ0ZXJtcyIsInNjYWxlIjoib3JkaW5hbCIsInNvdXJjZUZpZWxkIjoiY3VycmVuY3kiLCJpc0J1Y2tldGVkIjp0cnVlLCJwYXJhbXMiOnsic2l6ZSI6NSwib3JkZXJCeSI6eyJ0eXBlIjoiY29sdW1uIiwiY29sdW1uSWQiOiJmZjdmODczMy0zODEwLTQzYjctOWMxZS05ZjBmZTZlY2ZjNGUifSwib3JkZXJEaXJlY3Rpb24iOiJkZXNjIiwib3RoZXJCdWNrZXQiOnRydWUsIm1pc3NpbmdCdWNrZXQiOmZhbHNlLCJwYXJlbnRGb3JtYXQiOnsiaWQiOiJ0ZXJtcyJ9fX0sImZmN2Y4NzMzLTM4MTAtNDNiNy05YzFlLTlmMGZlNmVjZmM0ZSI6eyJsYWJlbCI6IkNvdW50IG9mIHJlY29yZHMiLCJkYXRhVHlwZSI6Im51bWJlciIsIm9wZXJhdGlvblR5cGUiOiJjb3VudCIsImlzQnVja2V0ZWQiOmZhbHNlLCJzY2FsZSI6InJhdGlvIiwic291cmNlRmllbGQiOiJfX19yZWNvcmRzX19fIn19LCJjb2x1bW5PcmRlciI6WyI4ODEzNDA3MC0yZTRiLTRlY2YtYTE1MC04MzBhZjVjMzkwM2QiLCJmZjdmODczMy0zODEwLTQzYjctOWMxZS05ZjBmZTZlY2ZjNGUiXSwiaW5jb21wbGV0ZUNvbHVtbnMiOnt9fX19fX19LCJmaWx0ZXJzIjpbXSwiaWQiOiJlbGVtZW50LTVmYzhhZmI3LTFhN2QtNDdlYS04ZjY2LWZhNDBlMjY5MzI4MCIsImVuaGFuY2VtZW50cyI6e319\" type=\"lens\"\n| render","filter":null,"id":"element-5fc8afb7-1a7d-47ea-8f66-fa40e2693280","position":{"angle":0,"height":300,"left":20,"parent":null,"top":20,"width":500}},{"expression":"embeddable \n config=\"eyJ2aWV3TW9kZSI6ImVkaXQiLCJ0aW1lUmFuZ2UiOnsiZnJvbSI6Im5vdy0xNW0iLCJ0byI6Im5vdyJ9LCJkaXNhYmxlVHJpZ2dlcnMiOnRydWUsInJlbmRlck1vZGUiOiJub0ludGVyYWN0aXZpdHkiLCJhdHRyaWJ1dGVzIjp7InRpdGxlIjoiIiwiZGVzY3JpcHRpb24iOiIiLCJsYXllckxpc3RKU09OIjoiW3tcInNvdXJjZURlc2NyaXB0b3JcIjp7XCJ0eXBlXCI6XCJFTVNfVE1TXCIsXCJpc0F1dG9TZWxlY3RcIjp0cnVlLFwibGlnaHRNb2RlRGVmYXVsdFwiOlwicm9hZF9tYXBfZGVzYXR1cmF0ZWRcIn0sXCJpZFwiOlwiNDMwYTVmZjAtYmM4Yi00MjdlLWE3ODYtODk1ZDIyMDVmNGU3XCIsXCJsYWJlbFwiOm51bGwsXCJtaW5ab29tXCI6MCxcIm1heFpvb21cIjoyNCxcImFscGhhXCI6MSxcInZpc2libGVcIjp0cnVlLFwic3R5bGVcIjp7XCJ0eXBlXCI6XCJUSUxFXCJ9LFwiaW5jbHVkZUluRml0VG9Cb3VuZHNcIjp0cnVlLFwidHlwZVwiOlwiRU1TX1ZFQ1RPUl9USUxFXCJ9LHtcInNvdXJjZURlc2NyaXB0b3JcIjp7XCJnZW9GaWVsZFwiOlwiZ2VvaXAubG9jYXRpb25cIixcInNjYWxpbmdUeXBlXCI6XCJNVlRcIixcImlkXCI6XCI4YWRhOTk2MS1lZWQ2LTQ3MzYtYmRkMC05OWI2ZGRmNWJiOTBcIixcInR5cGVcIjpcIkVTX1NFQVJDSFwiLFwiYXBwbHlHbG9iYWxRdWVyeVwiOnRydWUsXCJhcHBseUdsb2JhbFRpbWVcIjp0cnVlLFwiYXBwbHlGb3JjZVJlZnJlc2hcIjp0cnVlLFwiZmlsdGVyQnlNYXBCb3VuZHNcIjp0cnVlLFwidG9vbHRpcFByb3BlcnRpZXNcIjpbXSxcInNvcnRGaWVsZFwiOlwiXCIsXCJzb3J0T3JkZXJcIjpcImRlc2NcIixcInRvcEhpdHNTcGxpdEZpZWxkXCI6XCJcIixcInRvcEhpdHNTaXplXCI6MSxcImluZGV4UGF0dGVyblJlZk5hbWVcIjpcImxheWVyXzFfc291cmNlX2luZGV4X3BhdHRlcm5cIn0sXCJpZFwiOlwiYTNlYzYzZjAtMzViNy00Y2JkLTk0MGYtNzZiZGM2YjRjNThmXCIsXCJsYWJlbFwiOlwic29tZXRoaW5nXCIsXCJtaW5ab29tXCI6MCxcIm1heFpvb21cIjoyNCxcImFscGhhXCI6MC43NSxcInZpc2libGVcIjp0cnVlLFwic3R5bGVcIjp7XCJ0eXBlXCI6XCJWRUNUT1JcIixcInByb3BlcnRpZXNcIjp7XCJpY29uXCI6e1widHlwZVwiOlwiU1RBVElDXCIsXCJvcHRpb25zXCI6e1widmFsdWVcIjpcIm1hcmtlclwifX0sXCJmaWxsQ29sb3JcIjp7XCJ0eXBlXCI6XCJTVEFUSUNcIixcIm9wdGlvbnNcIjp7XCJjb2xvclwiOlwiIzU0QjM5OVwifX0sXCJsaW5lQ29sb3JcIjp7XCJ0eXBlXCI6XCJTVEFUSUNcIixcIm9wdGlvbnNcIjp7XCJjb2xvclwiOlwiIzQxOTM3Y1wifX0sXCJsaW5lV2lkdGhcIjp7XCJ0eXBlXCI6XCJTVEFUSUNcIixcIm9wdGlvbnNcIjp7XCJzaXplXCI6MX19LFwiaWNvblNpemVcIjp7XCJ0eXBlXCI6XCJTVEFUSUNcIixcIm9wdGlvbnNcIjp7XCJzaXplXCI6Nn19LFwiaWNvbk9yaWVudGF0aW9uXCI6e1widHlwZVwiOlwiU1RBVElDXCIsXCJvcHRpb25zXCI6e1wib3JpZW50YXRpb25cIjowfX0sXCJsYWJlbFRleHRcIjp7XCJ0eXBlXCI6XCJTVEFUSUNcIixcIm9wdGlvbnNcIjp7XCJ2YWx1ZVwiOlwiXCJ9fSxcImxhYmVsQ29sb3JcIjp7XCJ0eXBlXCI6XCJTVEFUSUNcIixcIm9wdGlvbnNcIjp7XCJjb2xvclwiOlwiIzAwMDAwMFwifX0sXCJsYWJlbFNpemVcIjp7XCJ0eXBlXCI6XCJTVEFUSUNcIixcIm9wdGlvbnNcIjp7XCJzaXplXCI6MTR9fSxcImxhYmVsQm9yZGVyQ29sb3JcIjp7XCJ0eXBlXCI6XCJTVEFUSUNcIixcIm9wdGlvbnNcIjp7XCJjb2xvclwiOlwiI0ZGRkZGRlwifX0sXCJzeW1ib2xpemVBc1wiOntcIm9wdGlvbnNcIjp7XCJ2YWx1ZVwiOlwiY2lyY2xlXCJ9fSxcImxhYmVsQm9yZGVyU2l6ZVwiOntcIm9wdGlvbnNcIjp7XCJzaXplXCI6XCJTTUFMTFwifX19LFwiaXNUaW1lQXdhcmVcIjp0cnVlfSxcImluY2x1ZGVJbkZpdFRvQm91bmRzXCI6dHJ1ZSxcInR5cGVcIjpcIk1WVF9WRUNUT1JcIixcImpvaW5zXCI6W119XSIsIm1hcFN0YXRlSlNPTiI6IntcInpvb21cIjoxLjQ2LFwiY2VudGVyXCI6e1wibG9uXCI6MCxcImxhdFwiOjE5Ljk0Mjc3fSxcInRpbWVGaWx0ZXJzXCI6e1wiZnJvbVwiOlwibm93LTE1bVwiLFwidG9cIjpcIm5vd1wifSxcInJlZnJlc2hDb25maWdcIjp7XCJpc1BhdXNlZFwiOnRydWUsXCJpbnRlcnZhbFwiOjB9LFwicXVlcnlcIjp7XCJxdWVyeVwiOlwiXCIsXCJsYW5ndWFnZVwiOlwia3VlcnlcIn0sXCJmaWx0ZXJzXCI6W10sXCJzZXR0aW5nc1wiOntcImF1dG9GaXRUb0RhdGFCb3VuZHNcIjpmYWxzZSxcImJhY2tncm91bmRDb2xvclwiOlwiI2ZmZmZmZlwiLFwiZGlzYWJsZUludGVyYWN0aXZlXCI6ZmFsc2UsXCJkaXNhYmxlVG9vbHRpcENvbnRyb2xcIjpmYWxzZSxcImhpZGVUb29sYmFyT3ZlcmxheVwiOmZhbHNlLFwiaGlkZUxheWVyQ29udHJvbFwiOmZhbHNlLFwiaGlkZVZpZXdDb250cm9sXCI6ZmFsc2UsXCJpbml0aWFsTG9jYXRpb25cIjpcIkxBU1RfU0FWRURfTE9DQVRJT05cIixcImZpeGVkTG9jYXRpb25cIjp7XCJsYXRcIjowLFwibG9uXCI6MCxcInpvb21cIjoyfSxcImJyb3dzZXJMb2NhdGlvblwiOntcInpvb21cIjoyfSxcIm1heFpvb21cIjoyNCxcIm1pblpvb21cIjowLFwic2hvd1NjYWxlQ29udHJvbFwiOmZhbHNlLFwic2hvd1NwYXRpYWxGaWx0ZXJzXCI6dHJ1ZSxcInNob3dUaW1lc2xpZGVyVG9nZ2xlQnV0dG9uXCI6dHJ1ZSxcInNwYXRpYWxGaWx0ZXJzQWxwYVwiOjAuMyxcInNwYXRpYWxGaWx0ZXJzRmlsbENvbG9yXCI6XCIjREE4QjQ1XCIsXCJzcGF0aWFsRmlsdGVyc0xpbmVDb2xvclwiOlwiI0RBOEI0NVwifX0iLCJ1aVN0YXRlSlNPTiI6IntcImlzTGF5ZXJUT0NPcGVuXCI6dHJ1ZSxcIm9wZW5UT0NEZXRhaWxzXCI6W119In0sImZpbHRlcnMiOltdLCJpZCI6ImVsZW1lbnQtMDE4MzM3YzctOWE3OS00MTkwLWExMWUtMmY4ZDc1Y2Y0NWYzIiwibWFwQ2VudGVyIjp7ImxhdCI6MTkuOTQyNzcsImxvbiI6MCwiem9vbSI6MS40Nn0sIm1hcEJ1ZmZlciI6eyJtaW5Mb24iOi05MCwibWluTGF0IjotNjYuNTEzMjYsIm1heExvbiI6OTAsIm1heExhdCI6NjYuNTEzMjZ9LCJpc0xheWVyVE9DT3BlbiI6dHJ1ZSwib3BlblRPQ0RldGFpbHMiOltdLCJoaWRkZW5MYXllcnMiOltdLCJlbmhhbmNlbWVudHMiOnt9fQ==\" type=\"map\"\n| render","filter":null,"id":"element-018337c7-9a79-4190-a11e-2f8d75cf45f3","position":{"angle":0,"height":300,"left":430,"parent":null,"top":360,"width":500}}],"groups":[],"id":"page-b8904ba9-0d34-4d67-9dc4-2e24d6dd08a8","style":{"background":"#FFF"},"transition":{}}],"variables":[],"width":1080},"coreMigrationVersion":"8.1.3","id":"workpad-a57ed7c6-d7db-4b4e-9b34-a46a33f6a3aa","migrationVersion":{"canvas-workpad":"8.1.0"},"references":[{"id":"21815490-f242-11ec-865d-c9490d79025a","name":"element-ceb894d4-80b4-4afd-9e09-0da296841147:l0_embeddable.savedObjectId","type":"visualization"},{"id":"dffc15e0-f22e-11ec-865d-c9490d79025a","name":"element-b72cbbe4-eeea-4ba3-88b8-fe777c607686:l0_embeddable.savedObjectId","type":"lens"},{"id":"2c9c1f60-1909-11e9-919b-ffe5949a18d2","name":"element-7e5752a4-5643-4fae-a89e-aeb925bf9d2b:l0_embeddable.savedObjectId","type":"map"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"element-5fc8afb7-1a7d-47ea-8f66-fa40e2693280:l0_indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"element-5fc8afb7-1a7d-47ea-8f66-fa40e2693280:l0_indexpattern-datasource-layer-0a7a057e-8c09-4214-b2b7-f94e6e5230b8","type":"index-pattern"},{"id":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","name":"element-018337c7-9a79-4190-a11e-2f8d75cf45f3:l0_layer_1_source_index_pattern","type":"index-pattern"}],"type":"canvas-workpad","updated_at":"2022-06-23T12:49:52.425Z","version":"WzU4OSwxXQ=="} +{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":5,"missingRefCount":0,"missingReferences":[]} diff --git a/x-pack/test/functional/apps/canvas/migrations_smoke_test.ts b/x-pack/test/functional/apps/canvas/migrations_smoke_test.ts index 12a75e5a2ba8b..7577073a1004d 100644 --- a/x-pack/test/functional/apps/canvas/migrations_smoke_test.ts +++ b/x-pack/test/functional/apps/canvas/migrations_smoke_test.ts @@ -15,10 +15,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('imports an 8.2 workpad', async function () { /* In 8.1 Canvas introduced by value embeddables, which requires expressions to know about embeddable migrations - Starting in 8.3, we were seeing an error during migration where it would appear that an 8.2 workpad was - from a future version. This was because there were missing embeddable migrations on the expression because + Starting in 8.3, we were seeing an error during migration where it would appear that an 8.2 workpad was + from a future version. This was because there were missing embeddable migrations on the expression because the Canvas plugin was adding the embeddable expression with all of it's migrations before other embeddables had - registered their own migrations. + registered their own migrations. This smoke test is intended to import an 8.2 workpad to ensure that we don't hit a similar scenario in the future */ @@ -31,5 +31,20 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.savedObjects.checkImportSucceeded(); await PageObjects.savedObjects.clickImportDone(); }); + + it('migrates a workpad from 8.1', async function () { + /* + This is a smoke test to make sure migrations don't fail. + This workpad from 8.1 has both by-val and by-ref embeddables + */ + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaSavedObjects(); + await PageObjects.savedObjects.waitTableIsLoaded(); + await PageObjects.savedObjects.importFile( + path.join(__dirname, 'exports', '8.1.embeddable_test.ndjson') + ); + await PageObjects.savedObjects.checkImportSucceeded(); + await PageObjects.savedObjects.clickImportDone(); + }); }); } From 8f8ea8dd493e09b80fa65df52ac37ba2add6e32b Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 5 Jul 2022 14:20:25 -0500 Subject: [PATCH 09/81] Bump license-checker to 25.0.1 (#135252) * Bump license-checker to 25.0.1 * [CI] Auto-commit changed files from 'yarn kbn run build -i @kbn/pm' * fix jszip Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 2 +- packages/kbn-pm/dist/index.js | 4708 ++++++++++++++--------------- src/dev/license_checker/config.ts | 1 + yarn.lock | 192 +- 4 files changed, 2423 insertions(+), 2480 deletions(-) diff --git a/package.json b/package.json index ef7ff5c382c15..a7411852a1382 100644 --- a/package.json +++ b/package.json @@ -1026,7 +1026,7 @@ "json-schema-typed": "^7.0.3", "json5": "^1.0.1", "jsondiffpatch": "0.4.1", - "license-checker": "^16.0.0", + "license-checker": "^25.0.1", "listr": "^0.14.1", "lmdb-store": "^1.6.11", "marge": "^1.0.1", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 3c68dc90dda18..3b48937eb1098 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -56511,2663 +56511,2663 @@ module.exports.default = sortPackageJson /***/ }), -/***/ "../../node_modules/spdx-expression-parse/index.js": +/***/ "../../node_modules/strip-ansi/index.js": /***/ (function(module, exports, __webpack_require__) { -var parser = __webpack_require__("../../node_modules/spdx-expression-parse/parser.js").parser +"use strict"; -module.exports = function (argument) { - return parser.parse(argument) -} +const ansiRegex = __webpack_require__("../../node_modules/ansi-regex/index.js"); + +module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string; /***/ }), -/***/ "../../node_modules/spdx-expression-parse/parser.js": +/***/ "../../node_modules/strip-bom/index.js": /***/ (function(module, exports, __webpack_require__) { -/* WEBPACK VAR INJECTION */(function(module) {/* parser generated by jison 0.4.17 */ -/* - Returns a Parser object of the following structure: +"use strict"; - Parser: { - yy: {} - } - Parser.prototype: { - yy: {}, - trace: function(), - symbols_: {associative list: name ==> number}, - terminals_: {associative list: number ==> name}, - productions_: [...], - performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), - table: [...], - defaultActions: {...}, - parseError: function(str, hash), - parse: function(input), +module.exports = string => { + if (typeof string !== 'string') { + throw new TypeError(`Expected a string, got ${typeof string}`); + } - lexer: { - EOF: 1, - parseError: function(str, hash), - setInput: function(input), - input: function(), - unput: function(str), - more: function(), - less: function(n), - pastInput: function(), - upcomingInput: function(), - showPosition: function(), - test_match: function(regex_match_array, rule_index), - next: function(), - lex: function(), - begin: function(condition), - popState: function(), - _currentRules: function(), - topState: function(), - pushState: function(condition), + // Catches EFBBBF (UTF-8 BOM) because the buffer-to-string + // conversion translates it to FEFF (UTF-16 BOM) + if (string.charCodeAt(0) === 0xFEFF) { + return string.slice(1); + } - options: { - ranges: boolean (optional: true ==> token location info will include a .range[] member) - flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) - backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) - }, + return string; +}; - performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), - rules: [...], - conditions: {associative list: name ==> set}, - } - } +/***/ }), - token location info (@$, _$, etc.): { - first_line: n, - last_line: n, - first_column: n, - last_column: n, - range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) +/***/ "../../node_modules/strip-final-newline/index.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = input => { + const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt(); + const CR = typeof input === 'string' ? '\r' : '\r'.charCodeAt(); + + if (input[input.length - 1] === LF) { + input = input.slice(0, input.length - 1); + } + + if (input[input.length - 1] === CR) { + input = input.slice(0, input.length - 1); + } + + return input; +}; + + +/***/ }), + +/***/ "../../node_modules/strong-log-transformer/index.js": +/***/ (function(module, exports, __webpack_require__) { + +// Copyright IBM Corp. 2014,2018. All Rights Reserved. +// Node module: strong-log-transformer +// 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__("../../node_modules/strong-log-transformer/lib/logger.js"); +module.exports.cli = __webpack_require__("../../node_modules/strong-log-transformer/lib/cli.js"); + + +/***/ }), + +/***/ "../../node_modules/strong-log-transformer/lib/cli.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// Copyright IBM Corp. 2014,2018. All Rights Reserved. +// Node module: strong-log-transformer +// This file is licensed under the Apache License 2.0. +// License text available at https://opensource.org/licenses/Apache-2.0 + + + +var minimist = __webpack_require__("../../node_modules/minimist/index.js"); +var path = __webpack_require__("path"); + +var Logger = __webpack_require__("../../node_modules/strong-log-transformer/lib/logger.js"); +var pkg = __webpack_require__("../../node_modules/strong-log-transformer/package.json"); + +module.exports = cli; + +function cli(args) { + var opts = minimist(args.slice(2)); + var $0 = path.basename(args[1]); + var p = console.log.bind(console); + if (opts.v || opts.version) { + version($0, p); + } else if (opts.h || opts.help) { + usage($0, p); + } else if (args.length < 3) { + process.stdin.pipe(Logger()).pipe(process.stdout); + } else { + process.stdin.pipe(Logger(opts)).pipe(process.stdout); } +} +function version($0, p) { + p('%s v%s', pkg.name, pkg.version); +} - the parseError function receives a 'hash' object with these members for lexer and parser errors: { - text: (matched text) - token: (the produced terminal token, if any) - line: (yylineno) +function usage($0, p) { + var PADDING = ' '; + var opt, def; + p('Usage: %s [options]', $0); + p(''); + p('%s', pkg.description); + p(''); + p('OPTIONS:'); + for (opt in Logger.DEFAULTS) { + def = Logger.DEFAULTS[opt]; + if (typeof def === 'boolean') + boolOpt(opt, Logger.DEFAULTS[opt]); + else + stdOpt(opt, Logger.DEFAULTS[opt]); } - while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { - loc: (yylloc) - expected: (string describing the set of expected tokens) - recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) + p(''); + + function boolOpt(name, def) { + name = name + PADDING.slice(0, 20-name.length); + p(' --%s default: %s', name, def); } -*/ -var spdxparse = (function(){ -var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,6],$V2=[1,7],$V3=[1,4],$V4=[1,9],$V5=[1,10],$V6=[5,14,15,17],$V7=[5,12,14,15,17]; -var parser = {trace: function trace() { }, -yy: {}, -symbols_: {"error":2,"start":3,"expression":4,"EOS":5,"simpleExpression":6,"LICENSE":7,"PLUS":8,"LICENSEREF":9,"DOCUMENTREF":10,"COLON":11,"WITH":12,"EXCEPTION":13,"AND":14,"OR":15,"OPEN":16,"CLOSE":17,"$accept":0,"$end":1}, -terminals_: {2:"error",5:"EOS",7:"LICENSE",8:"PLUS",9:"LICENSEREF",10:"DOCUMENTREF",11:"COLON",12:"WITH",13:"EXCEPTION",14:"AND",15:"OR",16:"OPEN",17:"CLOSE"}, -productions_: [0,[3,2],[6,1],[6,2],[6,1],[6,3],[4,1],[4,3],[4,3],[4,3],[4,3]], -performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { -/* this == yyval */ -var $0 = $$.length - 1; -switch (yystate) { -case 1: -return this.$ = $$[$0-1] -break; -case 2: case 4: case 5: -this.$ = {license: yytext} -break; -case 3: -this.$ = {license: $$[$0-1], plus: true} -break; -case 6: -this.$ = $$[$0] -break; -case 7: -this.$ = {exception: $$[$0]} -this.$.license = $$[$0-2].license -if ($$[$0-2].hasOwnProperty('plus')) { - this.$.plus = $$[$0-2].plus -} -break; -case 8: -this.$ = {conjunction: 'and', left: $$[$0-2], right: $$[$0]} -break; -case 9: -this.$ = {conjunction: 'or', left: $$[$0-2], right: $$[$0]} -break; -case 10: -this.$ = $$[$0-1] -break; + function stdOpt(name, def) { + var value = name.toUpperCase() + + PADDING.slice(0, 19 - name.length*2); + p(' --%s %s default: %j', name, value, def); + } } -}, -table: [{3:1,4:2,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{1:[3]},{5:[1,8],14:$V4,15:$V5},o($V6,[2,6],{12:[1,11]}),{4:12,6:3,7:$V0,9:$V1,10:$V2,16:$V3},o($V7,[2,2],{8:[1,13]}),o($V7,[2,4]),{11:[1,14]},{1:[2,1]},{4:15,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{4:16,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{13:[1,17]},{14:$V4,15:$V5,17:[1,18]},o($V7,[2,3]),{9:[1,19]},o($V6,[2,8]),o([5,15,17],[2,9],{14:$V4}),o($V6,[2,7]),o($V6,[2,10]),o($V7,[2,5])], -defaultActions: {8:[2,1]}, -parseError: function parseError(str, hash) { - if (hash.recoverable) { - this.trace(str); - } else { - function _parseError (msg, hash) { - this.message = msg; - this.hash = hash; - } - _parseError.prototype = Error; - throw new _parseError(str, hash); - } -}, -parse: function parse(input) { - var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; - var args = lstack.slice.call(arguments, 1); - var lexer = Object.create(this.lexer); - var sharedState = { yy: {} }; - for (var k in this.yy) { - if (Object.prototype.hasOwnProperty.call(this.yy, k)) { - sharedState.yy[k] = this.yy[k]; - } - } - lexer.setInput(input, sharedState.yy); - sharedState.yy.lexer = lexer; - sharedState.yy.parser = this; - if (typeof lexer.yylloc == 'undefined') { - lexer.yylloc = {}; - } - var yyloc = lexer.yylloc; - lstack.push(yyloc); - var ranges = lexer.options && lexer.options.ranges; - if (typeof sharedState.yy.parseError === 'function') { - this.parseError = sharedState.yy.parseError; - } else { - this.parseError = Object.getPrototypeOf(this).parseError; - } - function popStack(n) { - stack.length = stack.length - 2 * n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - _token_stack: - var lex = function () { - var token; - token = lexer.lex() || EOF; - if (typeof token !== 'number') { - token = self.symbols_[token] || token; - } - return token; - }; - var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; - while (true) { - state = stack[stack.length - 1]; - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol === null || typeof symbol == 'undefined') { - symbol = lex(); - } - action = table[state] && table[state][symbol]; - } - if (typeof action === 'undefined' || !action.length || !action[0]) { - var errStr = ''; - expected = []; - for (p in table[state]) { - if (this.terminals_[p] && p > TERROR) { - expected.push('\'' + this.terminals_[p] + '\''); - } - } - if (lexer.showPosition) { - errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; - } else { - errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); - } - this.parseError(errStr, { - text: lexer.match, - token: this.terminals_[symbol] || symbol, - line: lexer.yylineno, - loc: yyloc, - expected: expected - }); - } - if (action[0] instanceof Array && action.length > 1) { - throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); - } - switch (action[0]) { - case 1: - stack.push(symbol); - vstack.push(lexer.yytext); - lstack.push(lexer.yylloc); - stack.push(action[1]); - symbol = null; - if (!preErrorSymbol) { - yyleng = lexer.yyleng; - yytext = lexer.yytext; - yylineno = lexer.yylineno; - yyloc = lexer.yylloc; - if (recovering > 0) { - recovering--; - } - } else { - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - case 2: - len = this.productions_[action[1]][1]; - yyval.$ = vstack[vstack.length - len]; - yyval._$ = { - first_line: lstack[lstack.length - (len || 1)].first_line, - last_line: lstack[lstack.length - 1].last_line, - first_column: lstack[lstack.length - (len || 1)].first_column, - last_column: lstack[lstack.length - 1].last_column - }; - if (ranges) { - yyval._$.range = [ - lstack[lstack.length - (len || 1)].range[0], - lstack[lstack.length - 1].range[1] - ]; - } - r = this.performAction.apply(yyval, [ - yytext, - yyleng, - yylineno, - sharedState.yy, - action[1], - vstack, - lstack - ].concat(args)); - if (typeof r !== 'undefined') { - return r; - } - if (len) { - stack = stack.slice(0, -1 * len * 2); - vstack = vstack.slice(0, -1 * len); - lstack = lstack.slice(0, -1 * len); - } - stack.push(this.productions_[action[1]][0]); - vstack.push(yyval.$); - lstack.push(yyval._$); - newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; - stack.push(newState); - break; - case 3: - return true; - } - } - return true; -}}; -/* generated by jison-lex 0.3.4 */ -var lexer = (function(){ -var lexer = ({ -EOF:1, +/***/ }), -parseError:function parseError(str, hash) { - if (this.yy.parser) { - this.yy.parser.parseError(str, hash); - } else { - throw new Error(str); - } - }, +/***/ "../../node_modules/strong-log-transformer/lib/logger.js": +/***/ (function(module, exports, __webpack_require__) { -// resets the lexer, sets new input -setInput:function (input, yy) { - this.yy = yy || this.yy || {}; - this._input = input; - this._more = this._backtrack = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = { - first_line: 1, - first_column: 0, - last_line: 1, - last_column: 0 - }; - if (this.options.ranges) { - this.yylloc.range = [0,0]; - } - this.offset = 0; - return this; - }, +"use strict"; +// Copyright IBM Corp. 2014,2018. All Rights Reserved. +// Node module: strong-log-transformer +// This file is licensed under the Apache License 2.0. +// License text available at https://opensource.org/licenses/Apache-2.0 -// consumes and returns one char from the input -input:function () { - var ch = this._input[0]; - this.yytext += ch; - this.yyleng++; - this.offset++; - this.match += ch; - this.matched += ch; - var lines = ch.match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno++; - this.yylloc.last_line++; - } else { - this.yylloc.last_column++; - } - if (this.options.ranges) { - this.yylloc.range[1]++; - } - this._input = this._input.slice(1); - return ch; - }, -// unshifts one char (or a string) into the input -unput:function (ch) { - var len = ch.length; - var lines = ch.split(/(?:\r\n?|\n)/g); +var stream = __webpack_require__("stream"); +var util = __webpack_require__("util"); +var fs = __webpack_require__("fs"); - this._input = ch + this._input; - this.yytext = this.yytext.substr(0, this.yytext.length - len); - //this.yyleng -= len; - this.offset -= len; - var oldLines = this.match.split(/(?:\r\n?|\n)/g); - this.match = this.match.substr(0, this.match.length - 1); - this.matched = this.matched.substr(0, this.matched.length - 1); +var through = __webpack_require__("../../node_modules/through/index.js"); +var duplexer = __webpack_require__("../../node_modules/duplexer/index.js"); +var StringDecoder = __webpack_require__("string_decoder").StringDecoder; - if (lines.length - 1) { - this.yylineno -= lines.length - 1; - } - var r = this.yylloc.range; +module.exports = Logger; - this.yylloc = { - first_line: this.yylloc.first_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.first_column, - last_column: lines ? - (lines.length === oldLines.length ? this.yylloc.first_column : 0) - + oldLines[oldLines.length - lines.length].length - lines[0].length : - this.yylloc.first_column - len - }; +Logger.DEFAULTS = { + format: 'text', + tag: '', + mergeMultiline: false, + timeStamp: false, +}; - if (this.options.ranges) { - this.yylloc.range = [r[0], r[0] + this.yyleng - len]; - } - this.yyleng = this.yytext.length; - return this; - }, +var formatters = { + text: textFormatter, + json: jsonFormatter, +} -// When called from action, caches matched text and appends it on next action -more:function () { - this._more = true; - return this; - }, +function Logger(options) { + var defaults = JSON.parse(JSON.stringify(Logger.DEFAULTS)); + options = util._extend(defaults, options || {}); + var catcher = deLiner(); + var emitter = catcher; + var transforms = [ + objectifier(), + ]; -// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. -reject:function () { - if (this.options.backtrack_lexer) { - this._backtrack = true; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { - text: "", - token: null, - line: this.yylineno - }); + if (options.tag) { + transforms.push(staticTagger(options.tag)); + } - } - return this; - }, + if (options.mergeMultiline) { + transforms.push(lineMerger()); + } -// retain first n characters of the match -less:function (n) { - this.unput(this.match.slice(n)); - }, - -// displays already matched input, i.e. for error messages -pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, + // TODO + // if (options.pidStamp) { + // transforms.push(pidStamper(options.pid)); + // } -// displays upcoming input, i.e. for error messages -upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); - }, + // TODO + // if (options.workerStamp) { + // transforms.push(workerStamper(options.worker)); + // } -// displays the character position where the lexing error occurred, i.e. for error messages -showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c + "^"; - }, + transforms.push(formatters[options.format](options)); -// test the lexed token: return FALSE when not a match, otherwise return token -test_match:function (match, indexed_rule) { - var token, - lines, - backup; + // restore line endings that were removed by line splitting + transforms.push(reLiner()); - if (this.options.backtrack_lexer) { - // save context - backup = { - yylineno: this.yylineno, - yylloc: { - first_line: this.yylloc.first_line, - last_line: this.last_line, - first_column: this.yylloc.first_column, - last_column: this.yylloc.last_column - }, - yytext: this.yytext, - match: this.match, - matches: this.matches, - matched: this.matched, - yyleng: this.yyleng, - offset: this.offset, - _more: this._more, - _input: this._input, - yy: this.yy, - conditionStack: this.conditionStack.slice(0), - done: this.done - }; - if (this.options.ranges) { - backup.yylloc.range = this.yylloc.range.slice(0); - } - } + for (var t in transforms) { + emitter = emitter.pipe(transforms[t]); + } - lines = match[0].match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno += lines.length; - } - this.yylloc = { - first_line: this.yylloc.last_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.last_column, - last_column: lines ? - lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : - this.yylloc.last_column + match[0].length - }; - this.yytext += match[0]; - this.match += match[0]; - this.matches = match; - this.yyleng = this.yytext.length; - if (this.options.ranges) { - this.yylloc.range = [this.offset, this.offset += this.yyleng]; - } - this._more = false; - this._backtrack = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); - if (this.done && this._input) { - this.done = false; - } - if (token) { - return token; - } else if (this._backtrack) { - // recover context - for (var k in backup) { - this[k] = backup[k]; - } - return false; // rule action called reject() implying the next rule should be tested instead. - } - return false; - }, + return duplexer(catcher, emitter); +} -// return next match in input -next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) { - this.done = true; - } +function deLiner() { + var decoder = new StringDecoder('utf8'); + var last = ''; - var token, - match, - tempMatch, - index; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i = 0; i < rules.length; i++) { - tempMatch = this._input.match(this.rules[rules[i]]); - if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { - match = tempMatch; - index = i; - if (this.options.backtrack_lexer) { - token = this.test_match(tempMatch, rules[i]); - if (token !== false) { - return token; - } else if (this._backtrack) { - match = false; - continue; // rule action called reject() implying a rule MISmatch. - } else { - // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) - return false; - } - } else if (!this.options.flex) { - break; - } - } - } - if (match) { - token = this.test_match(match, rules[index]); - if (token !== false) { - return token; - } - // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) - return false; - } - if (this._input === "") { - return this.EOF; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { - text: "", - token: null, - line: this.yylineno - }); + return new stream.Transform({ + transform(chunk, _enc, callback) { + last += decoder.write(chunk); + var list = last.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g); + last = list.pop(); + for (var i = 0; i < list.length; i++) { + // swallow empty lines + if (list[i]) { + this.push(list[i]); } + } + callback(); }, - -// return next match that has a token -lex:function lex() { - var r = this.next(); - if (r) { - return r; - } else { - return this.lex(); - } + flush(callback) { + // incomplete UTF8 sequences become UTF8 replacement characters + last += decoder.end(); + if (last) { + this.push(last); + } + callback(); }, + }); +} -// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) -begin:function begin(condition) { - this.conditionStack.push(condition); - }, +function reLiner() { + return through(appendNewline); -// pop the previously active lexer condition state off the condition stack -popState:function popState() { - var n = this.conditionStack.length - 1; - if (n > 0) { - return this.conditionStack.pop(); - } else { - return this.conditionStack[0]; - } - }, + function appendNewline(line) { + this.emit('data', line + '\n'); + } +} -// produce the lexer rule set which is active for the currently active lexer condition state -_currentRules:function _currentRules() { - if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { - return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; - } else { - return this.conditions["INITIAL"].rules; - } - }, +function objectifier() { + return through(objectify, null, {autoDestroy: false}); -// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available -topState:function topState(n) { - n = this.conditionStack.length - 1 - Math.abs(n || 0); - if (n >= 0) { - return this.conditionStack[n]; - } else { - return "INITIAL"; - } - }, + function objectify(line) { + this.emit('data', { + msg: line, + time: Date.now(), + }); + } +} -// alias for begin(condition) -pushState:function pushState(condition) { - this.begin(condition); - }, +function staticTagger(tag) { + return through(tagger); -// return the number of states currently on the stack -stateStackSize:function stateStackSize() { - return this.conditionStack.length; - }, -options: {}, -performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { -var YYSTATE=YY_START; -switch($avoiding_name_collisions) { -case 0:return 5 -break; -case 1:/* skip whitespace */ -break; -case 2:return 8 -break; -case 3:return 16 -break; -case 4:return 17 -break; -case 5:return 11 -break; -case 6:return 10 -break; -case 7:return 9 -break; -case 8:return 14 -break; -case 9:return 15 -break; -case 10:return 12 -break; -case 11:return 7 -break; -case 12:return 7 -break; -case 13:return 7 -break; -case 14:return 7 -break; -case 15:return 7 -break; -case 16:return 7 -break; -case 17:return 7 -break; -case 18:return 7 -break; -case 19:return 7 -break; -case 20:return 7 -break; -case 21:return 7 -break; -case 22:return 7 -break; -case 23:return 7 -break; -case 24:return 13 -break; -case 25:return 13 -break; -case 26:return 13 -break; -case 27:return 13 -break; -case 28:return 13 -break; -case 29:return 13 -break; -case 30:return 13 -break; -case 31:return 13 -break; -case 32:return 7 -break; -case 33:return 13 -break; -case 34:return 7 -break; -case 35:return 13 -break; -case 36:return 7 -break; -case 37:return 13 -break; -case 38:return 13 -break; -case 39:return 7 -break; -case 40:return 13 -break; -case 41:return 13 -break; -case 42:return 13 -break; -case 43:return 13 -break; -case 44:return 13 -break; -case 45:return 7 -break; -case 46:return 13 -break; -case 47:return 7 -break; -case 48:return 7 -break; -case 49:return 7 -break; -case 50:return 7 -break; -case 51:return 7 -break; -case 52:return 7 -break; -case 53:return 7 -break; -case 54:return 7 -break; -case 55:return 7 -break; -case 56:return 7 -break; -case 57:return 7 -break; -case 58:return 7 -break; -case 59:return 7 -break; -case 60:return 7 -break; -case 61:return 7 -break; -case 62:return 7 -break; -case 63:return 13 -break; -case 64:return 7 -break; -case 65:return 7 -break; -case 66:return 13 -break; -case 67:return 7 -break; -case 68:return 7 -break; -case 69:return 7 -break; -case 70:return 7 -break; -case 71:return 7 -break; -case 72:return 7 -break; -case 73:return 13 -break; -case 74:return 7 -break; -case 75:return 13 -break; -case 76:return 7 -break; -case 77:return 7 -break; -case 78:return 7 -break; -case 79:return 7 -break; -case 80:return 7 -break; -case 81:return 7 -break; -case 82:return 7 -break; -case 83:return 7 -break; -case 84:return 7 -break; -case 85:return 7 -break; -case 86:return 7 -break; -case 87:return 7 -break; -case 88:return 7 -break; -case 89:return 7 -break; -case 90:return 7 -break; -case 91:return 7 -break; -case 92:return 7 -break; -case 93:return 7 -break; -case 94:return 7 -break; -case 95:return 7 -break; -case 96:return 7 -break; -case 97:return 7 -break; -case 98:return 7 -break; -case 99:return 7 -break; -case 100:return 7 -break; -case 101:return 7 -break; -case 102:return 7 -break; -case 103:return 7 -break; -case 104:return 7 -break; -case 105:return 7 -break; -case 106:return 7 -break; -case 107:return 7 -break; -case 108:return 7 -break; -case 109:return 7 -break; -case 110:return 7 -break; -case 111:return 7 -break; -case 112:return 7 -break; -case 113:return 7 -break; -case 114:return 7 -break; -case 115:return 7 -break; -case 116:return 7 -break; -case 117:return 7 -break; -case 118:return 7 -break; -case 119:return 7 -break; -case 120:return 7 -break; -case 121:return 7 -break; -case 122:return 7 -break; -case 123:return 7 -break; -case 124:return 7 -break; -case 125:return 7 -break; -case 126:return 7 -break; -case 127:return 7 -break; -case 128:return 7 -break; -case 129:return 7 -break; -case 130:return 7 -break; -case 131:return 7 -break; -case 132:return 7 -break; -case 133:return 7 -break; -case 134:return 7 -break; -case 135:return 7 -break; -case 136:return 7 -break; -case 137:return 7 -break; -case 138:return 7 -break; -case 139:return 7 -break; -case 140:return 7 -break; -case 141:return 7 -break; -case 142:return 7 -break; -case 143:return 7 -break; -case 144:return 7 -break; -case 145:return 7 -break; -case 146:return 7 -break; -case 147:return 7 -break; -case 148:return 7 -break; -case 149:return 7 -break; -case 150:return 7 -break; -case 151:return 7 -break; -case 152:return 7 -break; -case 153:return 7 -break; -case 154:return 7 -break; -case 155:return 7 -break; -case 156:return 7 -break; -case 157:return 7 -break; -case 158:return 7 -break; -case 159:return 7 -break; -case 160:return 7 -break; -case 161:return 7 -break; -case 162:return 7 -break; -case 163:return 7 -break; -case 164:return 7 -break; -case 165:return 7 -break; -case 166:return 7 -break; -case 167:return 7 -break; -case 168:return 7 -break; -case 169:return 7 -break; -case 170:return 7 -break; -case 171:return 7 -break; -case 172:return 7 -break; -case 173:return 7 -break; -case 174:return 7 -break; -case 175:return 7 -break; -case 176:return 7 -break; -case 177:return 7 -break; -case 178:return 7 -break; -case 179:return 7 -break; -case 180:return 7 -break; -case 181:return 7 -break; -case 182:return 7 -break; -case 183:return 7 -break; -case 184:return 7 -break; -case 185:return 7 -break; -case 186:return 7 -break; -case 187:return 7 -break; -case 188:return 7 -break; -case 189:return 7 -break; -case 190:return 7 -break; -case 191:return 7 -break; -case 192:return 7 -break; -case 193:return 7 -break; -case 194:return 7 -break; -case 195:return 7 -break; -case 196:return 7 -break; -case 197:return 7 -break; -case 198:return 7 -break; -case 199:return 7 -break; -case 200:return 7 -break; -case 201:return 7 -break; -case 202:return 7 -break; -case 203:return 7 -break; -case 204:return 7 -break; -case 205:return 7 -break; -case 206:return 7 -break; -case 207:return 7 -break; -case 208:return 7 -break; -case 209:return 7 -break; -case 210:return 7 -break; -case 211:return 7 -break; -case 212:return 7 -break; -case 213:return 7 -break; -case 214:return 7 -break; -case 215:return 7 -break; -case 216:return 7 -break; -case 217:return 7 -break; -case 218:return 7 -break; -case 219:return 7 -break; -case 220:return 7 -break; -case 221:return 7 -break; -case 222:return 7 -break; -case 223:return 7 -break; -case 224:return 7 -break; -case 225:return 7 -break; -case 226:return 7 -break; -case 227:return 7 -break; -case 228:return 7 -break; -case 229:return 7 -break; -case 230:return 7 -break; -case 231:return 7 -break; -case 232:return 7 -break; -case 233:return 7 -break; -case 234:return 7 -break; -case 235:return 7 -break; -case 236:return 7 -break; -case 237:return 7 -break; -case 238:return 7 -break; -case 239:return 7 -break; -case 240:return 7 -break; -case 241:return 7 -break; -case 242:return 7 -break; -case 243:return 7 -break; -case 244:return 7 -break; -case 245:return 7 -break; -case 246:return 7 -break; -case 247:return 7 -break; -case 248:return 7 -break; -case 249:return 7 -break; -case 250:return 7 -break; -case 251:return 7 -break; -case 252:return 7 -break; -case 253:return 7 -break; -case 254:return 7 -break; -case 255:return 7 -break; -case 256:return 7 -break; -case 257:return 7 -break; -case 258:return 7 -break; -case 259:return 7 -break; -case 260:return 7 -break; -case 261:return 7 -break; -case 262:return 7 -break; -case 263:return 7 -break; -case 264:return 7 -break; -case 265:return 7 -break; -case 266:return 7 -break; -case 267:return 7 -break; -case 268:return 7 -break; -case 269:return 7 -break; -case 270:return 7 -break; -case 271:return 7 -break; -case 272:return 7 -break; -case 273:return 7 -break; -case 274:return 7 -break; -case 275:return 7 -break; -case 276:return 7 -break; -case 277:return 7 -break; -case 278:return 7 -break; -case 279:return 7 -break; -case 280:return 7 -break; -case 281:return 7 -break; -case 282:return 7 -break; -case 283:return 7 -break; -case 284:return 7 -break; -case 285:return 7 -break; -case 286:return 7 -break; -case 287:return 7 -break; -case 288:return 7 -break; -case 289:return 7 -break; -case 290:return 7 -break; -case 291:return 7 -break; -case 292:return 7 -break; -case 293:return 7 -break; -case 294:return 7 -break; -case 295:return 7 -break; -case 296:return 7 -break; -case 297:return 7 -break; -case 298:return 7 -break; -case 299:return 7 -break; -case 300:return 7 -break; -case 301:return 7 -break; -case 302:return 7 -break; -case 303:return 7 -break; -case 304:return 7 -break; -case 305:return 7 -break; -case 306:return 7 -break; -case 307:return 7 -break; -case 308:return 7 -break; -case 309:return 7 -break; -case 310:return 7 -break; -case 311:return 7 -break; -case 312:return 7 -break; -case 313:return 7 -break; -case 314:return 7 -break; -case 315:return 7 -break; -case 316:return 7 -break; -case 317:return 7 -break; -case 318:return 7 -break; -case 319:return 7 -break; -case 320:return 7 -break; -case 321:return 7 -break; -case 322:return 7 -break; -case 323:return 7 -break; -case 324:return 7 -break; -case 325:return 7 -break; -case 326:return 7 -break; -case 327:return 7 -break; -case 328:return 7 -break; -case 329:return 7 -break; -case 330:return 7 -break; -case 331:return 7 -break; -case 332:return 7 -break; -case 333:return 7 -break; -case 334:return 7 -break; -case 335:return 7 -break; -case 336:return 7 -break; -case 337:return 7 -break; -case 338:return 7 -break; -case 339:return 7 -break; -case 340:return 7 -break; -case 341:return 7 -break; -case 342:return 7 -break; -case 343:return 7 -break; -case 344:return 7 -break; -case 345:return 7 -break; -case 346:return 7 -break; -case 347:return 7 -break; -case 348:return 7 -break; -case 349:return 7 -break; -case 350:return 7 -break; -case 351:return 7 -break; -case 352:return 7 -break; -case 353:return 7 -break; -case 354:return 7 -break; -case 355:return 7 -break; -case 356:return 7 -break; -case 357:return 7 -break; -case 358:return 7 -break; -case 359:return 7 -break; -case 360:return 7 -break; -case 361:return 7 -break; -case 362:return 7 -break; -case 363:return 7 -break; -case 364:return 7 -break; + function tagger(logEvent) { + logEvent.tag = tag; + this.emit('data', logEvent); + } } -}, -rules: [/^(?:$)/,/^(?:\s+)/,/^(?:\+)/,/^(?:\()/,/^(?:\))/,/^(?::)/,/^(?:DocumentRef-([0-9A-Za-z-+.]+))/,/^(?:LicenseRef-([0-9A-Za-z-+.]+))/,/^(?:AND)/,/^(?:OR)/,/^(?:WITH)/,/^(?:BSD-3-Clause-No-Nuclear-License-2014)/,/^(?:BSD-3-Clause-No-Nuclear-Warranty)/,/^(?:GPL-2\.0-with-classpath-exception)/,/^(?:GPL-3\.0-with-autoconf-exception)/,/^(?:GPL-2\.0-with-autoconf-exception)/,/^(?:BSD-3-Clause-No-Nuclear-License)/,/^(?:MPL-2\.0-no-copyleft-exception)/,/^(?:GPL-2\.0-with-bison-exception)/,/^(?:GPL-2\.0-with-font-exception)/,/^(?:GPL-2\.0-with-GCC-exception)/,/^(?:CNRI-Python-GPL-Compatible)/,/^(?:GPL-3\.0-with-GCC-exception)/,/^(?:BSD-3-Clause-Attribution)/,/^(?:Classpath-exception-2\.0)/,/^(?:WxWindows-exception-3\.1)/,/^(?:freertos-exception-2\.0)/,/^(?:Autoconf-exception-3\.0)/,/^(?:i2p-gpl-java-exception)/,/^(?:gnu-javamail-exception)/,/^(?:Nokia-Qt-exception-1\.1)/,/^(?:Autoconf-exception-2\.0)/,/^(?:BSD-2-Clause-FreeBSD)/,/^(?:u-boot-exception-2\.0)/,/^(?:zlib-acknowledgement)/,/^(?:Bison-exception-2\.2)/,/^(?:BSD-2-Clause-NetBSD)/,/^(?:CLISP-exception-2\.0)/,/^(?:eCos-exception-2\.0)/,/^(?:BSD-3-Clause-Clear)/,/^(?:Font-exception-2\.0)/,/^(?:FLTK-exception-2\.0)/,/^(?:GCC-exception-2\.0)/,/^(?:Qwt-exception-1\.0)/,/^(?:Libtool-exception)/,/^(?:BSD-3-Clause-LBNL)/,/^(?:GCC-exception-3\.1)/,/^(?:Artistic-1\.0-Perl)/,/^(?:Artistic-1\.0-cl8)/,/^(?:CC-BY-NC-SA-2\.5)/,/^(?:MIT-advertising)/,/^(?:BSD-Source-Code)/,/^(?:CC-BY-NC-SA-4\.0)/,/^(?:LiLiQ-Rplus-1\.1)/,/^(?:CC-BY-NC-SA-3\.0)/,/^(?:BSD-4-Clause-UC)/,/^(?:CC-BY-NC-SA-2\.0)/,/^(?:CC-BY-NC-SA-1\.0)/,/^(?:CC-BY-NC-ND-4\.0)/,/^(?:CC-BY-NC-ND-3\.0)/,/^(?:CC-BY-NC-ND-2\.5)/,/^(?:CC-BY-NC-ND-2\.0)/,/^(?:CC-BY-NC-ND-1\.0)/,/^(?:LZMA-exception)/,/^(?:BitTorrent-1\.1)/,/^(?:CrystalStacker)/,/^(?:FLTK-exception)/,/^(?:SugarCRM-1\.1\.3)/,/^(?:BSD-Protection)/,/^(?:BitTorrent-1\.0)/,/^(?:HaskellReport)/,/^(?:Interbase-1\.0)/,/^(?:StandardML-NJ)/,/^(?:mif-exception)/,/^(?:Frameworx-1\.0)/,/^(?:389-exception)/,/^(?:CC-BY-NC-2\.0)/,/^(?:CC-BY-NC-2\.5)/,/^(?:CC-BY-NC-3\.0)/,/^(?:CC-BY-NC-4\.0)/,/^(?:W3C-19980720)/,/^(?:CC-BY-SA-1\.0)/,/^(?:CC-BY-SA-2\.0)/,/^(?:CC-BY-SA-2\.5)/,/^(?:CC-BY-ND-2\.0)/,/^(?:CC-BY-SA-4\.0)/,/^(?:CC-BY-SA-3\.0)/,/^(?:Artistic-1\.0)/,/^(?:Artistic-2\.0)/,/^(?:CC-BY-ND-2\.5)/,/^(?:CC-BY-ND-3\.0)/,/^(?:CC-BY-ND-4\.0)/,/^(?:CC-BY-ND-1\.0)/,/^(?:BSD-4-Clause)/,/^(?:BSD-3-Clause)/,/^(?:BSD-2-Clause)/,/^(?:CC-BY-NC-1\.0)/,/^(?:bzip2-1\.0\.6)/,/^(?:Unicode-TOU)/,/^(?:CNRI-Jython)/,/^(?:ImageMagick)/,/^(?:Adobe-Glyph)/,/^(?:CUA-OPL-1\.0)/,/^(?:OLDAP-2\.2\.2)/,/^(?:LiLiQ-R-1\.1)/,/^(?:bzip2-1\.0\.5)/,/^(?:LiLiQ-P-1\.1)/,/^(?:OLDAP-2\.0\.1)/,/^(?:OLDAP-2\.2\.1)/,/^(?:CNRI-Python)/,/^(?:XFree86-1\.1)/,/^(?:OSET-PL-2\.1)/,/^(?:Apache-2\.0)/,/^(?:Watcom-1\.0)/,/^(?:PostgreSQL)/,/^(?:Python-2\.0)/,/^(?:RHeCos-1\.1)/,/^(?:EUDatagrid)/,/^(?:Spencer-99)/,/^(?:Intel-ACPI)/,/^(?:CECILL-1\.0)/,/^(?:CECILL-1\.1)/,/^(?:JasPer-2\.0)/,/^(?:CECILL-2\.0)/,/^(?:CECILL-2\.1)/,/^(?:gSOAP-1\.3b)/,/^(?:Spencer-94)/,/^(?:Apache-1\.1)/,/^(?:Spencer-86)/,/^(?:Apache-1\.0)/,/^(?:ClArtistic)/,/^(?:TORQUE-1\.1)/,/^(?:CATOSL-1\.1)/,/^(?:Adobe-2006)/,/^(?:Zimbra-1\.4)/,/^(?:Zimbra-1\.3)/,/^(?:Condor-1\.1)/,/^(?:CC-BY-3\.0)/,/^(?:CC-BY-2\.5)/,/^(?:OLDAP-2\.4)/,/^(?:SGI-B-1\.1)/,/^(?:SISSL-1\.2)/,/^(?:SGI-B-1\.0)/,/^(?:OLDAP-2\.3)/,/^(?:CC-BY-4\.0)/,/^(?:Crossword)/,/^(?:SimPL-2\.0)/,/^(?:OLDAP-2\.2)/,/^(?:OLDAP-2\.1)/,/^(?:ErlPL-1\.1)/,/^(?:LPPL-1\.3a)/,/^(?:LPPL-1\.3c)/,/^(?:OLDAP-2\.0)/,/^(?:Leptonica)/,/^(?:CPOL-1\.02)/,/^(?:OLDAP-1\.4)/,/^(?:OLDAP-1\.3)/,/^(?:CC-BY-2\.0)/,/^(?:Unlicense)/,/^(?:OLDAP-2\.8)/,/^(?:OLDAP-1\.2)/,/^(?:MakeIndex)/,/^(?:OLDAP-2\.7)/,/^(?:OLDAP-1\.1)/,/^(?:Sleepycat)/,/^(?:D-FSL-1\.0)/,/^(?:CC-BY-1\.0)/,/^(?:OLDAP-2\.6)/,/^(?:WXwindows)/,/^(?:NPOSL-3\.0)/,/^(?:FreeImage)/,/^(?:SGI-B-2\.0)/,/^(?:OLDAP-2\.5)/,/^(?:Beerware)/,/^(?:Newsletr)/,/^(?:NBPL-1\.0)/,/^(?:NASA-1\.3)/,/^(?:NLOD-1\.0)/,/^(?:AGPL-1\.0)/,/^(?:OCLC-2\.0)/,/^(?:ODbL-1\.0)/,/^(?:PDDL-1\.0)/,/^(?:Motosoto)/,/^(?:Afmparse)/,/^(?:ANTLR-PD)/,/^(?:LPL-1\.02)/,/^(?:Abstyles)/,/^(?:eCos-2\.0)/,/^(?:APSL-1\.0)/,/^(?:LPPL-1\.2)/,/^(?:LPPL-1\.1)/,/^(?:LPPL-1\.0)/,/^(?:APSL-1\.1)/,/^(?:APSL-2\.0)/,/^(?:Info-ZIP)/,/^(?:Zend-2\.0)/,/^(?:IBM-pibs)/,/^(?:LGPL-2\.0)/,/^(?:LGPL-3\.0)/,/^(?:LGPL-2\.1)/,/^(?:GFDL-1\.3)/,/^(?:PHP-3\.01)/,/^(?:GFDL-1\.2)/,/^(?:GFDL-1\.1)/,/^(?:AGPL-3\.0)/,/^(?:Giftware)/,/^(?:EUPL-1\.1)/,/^(?:RPSL-1\.0)/,/^(?:EUPL-1\.0)/,/^(?:MIT-enna)/,/^(?:CECILL-B)/,/^(?:diffmark)/,/^(?:CECILL-C)/,/^(?:CDDL-1\.0)/,/^(?:Sendmail)/,/^(?:CDDL-1\.1)/,/^(?:CPAL-1\.0)/,/^(?:APSL-1\.2)/,/^(?:NPL-1\.1)/,/^(?:AFL-1\.2)/,/^(?:Caldera)/,/^(?:AFL-2\.0)/,/^(?:FSFULLR)/,/^(?:AFL-2\.1)/,/^(?:VSL-1\.0)/,/^(?:VOSTROM)/,/^(?:UPL-1\.0)/,/^(?:Dotseqn)/,/^(?:CPL-1\.0)/,/^(?:dvipdfm)/,/^(?:EPL-1\.0)/,/^(?:OCCT-PL)/,/^(?:ECL-1\.0)/,/^(?:Latex2e)/,/^(?:ECL-2\.0)/,/^(?:GPL-1\.0)/,/^(?:GPL-2\.0)/,/^(?:GPL-3\.0)/,/^(?:AFL-3\.0)/,/^(?:LAL-1\.2)/,/^(?:LAL-1\.3)/,/^(?:EFL-1\.0)/,/^(?:EFL-2\.0)/,/^(?:gnuplot)/,/^(?:Aladdin)/,/^(?:LPL-1\.0)/,/^(?:libtiff)/,/^(?:Entessa)/,/^(?:AMDPLPA)/,/^(?:IPL-1\.0)/,/^(?:OPL-1\.0)/,/^(?:OSL-1\.0)/,/^(?:OSL-1\.1)/,/^(?:OSL-2\.0)/,/^(?:OSL-2\.1)/,/^(?:OSL-3\.0)/,/^(?:OpenSSL)/,/^(?:ZPL-2\.1)/,/^(?:PHP-3\.0)/,/^(?:ZPL-2\.0)/,/^(?:ZPL-1\.1)/,/^(?:CC0-1\.0)/,/^(?:SPL-1\.0)/,/^(?:psutils)/,/^(?:MPL-1\.0)/,/^(?:QPL-1\.0)/,/^(?:MPL-1\.1)/,/^(?:MPL-2\.0)/,/^(?:APL-1\.0)/,/^(?:RPL-1\.1)/,/^(?:RPL-1\.5)/,/^(?:MIT-CMU)/,/^(?:Multics)/,/^(?:Eurosym)/,/^(?:BSL-1\.0)/,/^(?:MIT-feh)/,/^(?:Saxpath)/,/^(?:Borceux)/,/^(?:OFL-1\.1)/,/^(?:OFL-1\.0)/,/^(?:AFL-1\.1)/,/^(?:YPL-1\.1)/,/^(?:YPL-1\.0)/,/^(?:NPL-1\.0)/,/^(?:iMatix)/,/^(?:mpich2)/,/^(?:APAFML)/,/^(?:Bahyph)/,/^(?:RSA-MD)/,/^(?:psfrag)/,/^(?:Plexus)/,/^(?:eGenix)/,/^(?:Glulxe)/,/^(?:SAX-PD)/,/^(?:Imlib2)/,/^(?:Wsuipa)/,/^(?:LGPLLR)/,/^(?:Libpng)/,/^(?:xinetd)/,/^(?:MITNFA)/,/^(?:NetCDF)/,/^(?:Naumen)/,/^(?:SMPPL)/,/^(?:Nunit)/,/^(?:FSFUL)/,/^(?:GL2PS)/,/^(?:SMLNJ)/,/^(?:Rdisc)/,/^(?:Noweb)/,/^(?:Nokia)/,/^(?:SISSL)/,/^(?:Qhull)/,/^(?:Intel)/,/^(?:Glide)/,/^(?:Xerox)/,/^(?:AMPAS)/,/^(?:WTFPL)/,/^(?:MS-PL)/,/^(?:XSkat)/,/^(?:MS-RL)/,/^(?:MirOS)/,/^(?:RSCPL)/,/^(?:TMate)/,/^(?:OGTSL)/,/^(?:FSFAP)/,/^(?:NCSA)/,/^(?:Zlib)/,/^(?:SCEA)/,/^(?:SNIA)/,/^(?:NGPL)/,/^(?:NOSL)/,/^(?:ADSL)/,/^(?:MTLL)/,/^(?:NLPL)/,/^(?:Ruby)/,/^(?:JSON)/,/^(?:Barr)/,/^(?:0BSD)/,/^(?:Xnet)/,/^(?:Cube)/,/^(?:curl)/,/^(?:DSDP)/,/^(?:Fair)/,/^(?:HPND)/,/^(?:TOSL)/,/^(?:IJG)/,/^(?:SWL)/,/^(?:Vim)/,/^(?:FTL)/,/^(?:ICU)/,/^(?:OML)/,/^(?:NRL)/,/^(?:DOC)/,/^(?:TCL)/,/^(?:W3C)/,/^(?:NTP)/,/^(?:IPA)/,/^(?:ISC)/,/^(?:X11)/,/^(?:AAL)/,/^(?:AML)/,/^(?:xpp)/,/^(?:Zed)/,/^(?:MIT)/,/^(?:Mup)/], -conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364],"inclusive":true}} -}); -return lexer; -})(); -parser.lexer = lexer; -function Parser () { - this.yy = {}; + +function textFormatter(options) { + return through(textify); + + function textify(logEvent) { + var line = util.format('%s%s', textifyTags(logEvent.tag), + logEvent.msg.toString()); + if (options.timeStamp) { + line = util.format('%s %s', new Date(logEvent.time).toISOString(), line); + } + this.emit('data', line.replace(/\n/g, '\\n')); + } + + function textifyTags(tags) { + var str = ''; + if (typeof tags === 'string') { + str = tags + ' '; + } else if (typeof tags === 'object') { + for (var t in tags) { + str += t + ':' + tags[t] + ' '; + } + } + return str; + } } -Parser.prototype = parser;parser.Parser = Parser; -return new Parser; -})(); +function jsonFormatter(options) { + return through(jsonify); -if (true) { -exports.parser = spdxparse; -exports.Parser = spdxparse.Parser; -exports.parse = function () { return spdxparse.parse.apply(spdxparse, arguments); }; -exports.main = function commonjsMain(args) { - if (!args[1]) { - console.log('Usage: '+args[0]+' FILE'); - process.exit(1); + function jsonify(logEvent) { + if (options.timeStamp) { + logEvent.time = new Date(logEvent.time).toISOString(); + } else { + delete logEvent.time; } - var source = __webpack_require__("fs").readFileSync(__webpack_require__("path").normalize(args[1]), "utf8"); - return exports.parser.parse(source); -}; -if ( true && __webpack_require__.c[__webpack_require__.s] === module) { - exports.main(process.argv.slice(1)); + logEvent.msg = logEvent.msg.toString(); + this.emit('data', JSON.stringify(logEvent)); + } } + +function lineMerger(host) { + var previousLine = null; + var flushTimer = null; + var stream = through(lineMergerWrite, lineMergerEnd); + var flush = _flush.bind(stream); + + return stream; + + function lineMergerWrite(line) { + if (/^\s+/.test(line.msg)) { + if (previousLine) { + previousLine.msg += '\n' + line.msg; + } else { + previousLine = line; + } + } else { + flush(); + previousLine = line; + } + // rolling timeout + clearTimeout(flushTimer); + flushTimer = setTimeout(flush.bind(this), 10); + } + + function _flush() { + if (previousLine) { + this.emit('data', previousLine); + previousLine = null; + } + } + + function lineMergerEnd() { + flush.call(this); + this.emit('end'); + } } -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__("../../node_modules/webpack/buildin/module.js")(module))) /***/ }), -/***/ "../../node_modules/spdx-license-ids/spdx-license-ids.json": -/***/ (function(module) { +/***/ "../../node_modules/strong-log-transformer/package.json": +/***/ (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\"}}"); + +/***/ }), + +/***/ "../../node_modules/supports-color/index.js": +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const os = __webpack_require__("os"); +const tty = __webpack_require__("tty"); +const hasFlag = __webpack_require__("../../node_modules/has-flag/index.js"); + +const {env} = process; + +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false') || + hasFlag('color=never')) { + forceColor = 0; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = 1; +} + +if ('FORCE_COLOR' in env) { + if (env.FORCE_COLOR === 'true') { + forceColor = 1; + } else if (env.FORCE_COLOR === 'false') { + forceColor = 0; + } else { + forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3); + } +} -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\"]"); +function translateLevel(level) { + if (level === 0) { + return false; + } -/***/ }), + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; +} -/***/ "../../node_modules/strip-ansi/index.js": -/***/ (function(module, exports, __webpack_require__) { +function supportsColor(haveStream, streamIsTTY) { + if (forceColor === 0) { + return 0; + } -"use strict"; + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } -const ansiRegex = __webpack_require__("../../node_modules/ansi-regex/index.js"); + if (hasFlag('color=256')) { + return 2; + } -module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string; + if (haveStream && !streamIsTTY && forceColor === undefined) { + return 0; + } + const min = forceColor || 0; -/***/ }), + if (env.TERM === 'dumb') { + return min; + } -/***/ "../../node_modules/strip-bom/index.js": -/***/ (function(module, exports, __webpack_require__) { + if (process.platform === 'win32') { + // Windows 10 build 10586 is the first Windows release that supports 256 colors. + // Windows 10 build 14931 is the first release that supports 16m/TrueColor. + const osRelease = os.release().split('.'); + if ( + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } -"use strict"; + return 1; + } + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } -module.exports = string => { - if (typeof string !== 'string') { - throw new TypeError(`Expected a string, got ${typeof string}`); + return min; } - // Catches EFBBBF (UTF-8 BOM) because the buffer-to-string - // conversion translates it to FEFF (UTF-16 BOM) - if (string.charCodeAt(0) === 0xFEFF) { - return string.slice(1); + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; } - return string; -}; - - -/***/ }), + if ('GITHUB_ACTIONS' in env) { + return 1; + } -/***/ "../../node_modules/strip-final-newline/index.js": -/***/ (function(module, exports, __webpack_require__) { + if (env.COLORTERM === 'truecolor') { + return 3; + } -"use strict"; + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } -module.exports = input => { - const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt(); - const CR = typeof input === 'string' ? '\r' : '\r'.charCodeAt(); + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } - if (input[input.length - 1] === LF) { - input = input.slice(0, input.length - 1); + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; } - if (input[input.length - 1] === CR) { - input = input.slice(0, input.length - 1); + if ('COLORTERM' in env) { + return 1; } - return input; + return min; +} + +function getSupportLevel(stream) { + const level = supportsColor(stream, stream && stream.isTTY); + return translateLevel(level); +} + +module.exports = { + supportsColor: getSupportLevel, + stdout: translateLevel(supportsColor(true, tty.isatty(1))), + stderr: translateLevel(supportsColor(true, tty.isatty(2))) }; /***/ }), -/***/ "../../node_modules/strong-log-transformer/index.js": +/***/ "../../node_modules/through/index.js": /***/ (function(module, exports, __webpack_require__) { -// Copyright IBM Corp. 2014,2018. All Rights Reserved. -// Node module: strong-log-transformer -// This file is licensed under the Apache License 2.0. -// License text available at https://opensource.org/licenses/Apache-2.0 +var Stream = __webpack_require__("stream") -module.exports = __webpack_require__("../../node_modules/strong-log-transformer/lib/logger.js"); -module.exports.cli = __webpack_require__("../../node_modules/strong-log-transformer/lib/cli.js"); +// through +// +// a stream that does nothing but re-emit the input. +// useful for aggregating a series of changing but not ending streams into one stream) +exports = module.exports = through +through.through = through -/***/ }), +//create a readable writable stream. -/***/ "../../node_modules/strong-log-transformer/lib/cli.js": -/***/ (function(module, exports, __webpack_require__) { +function through (write, end, opts) { + write = write || function (data) { this.queue(data) } + end = end || function () { this.queue(null) } -"use strict"; -// Copyright IBM Corp. 2014,2018. All Rights Reserved. -// Node module: strong-log-transformer -// This file is licensed under the Apache License 2.0. -// License text available at https://opensource.org/licenses/Apache-2.0 + var ended = false, destroyed = false, buffer = [], _ended = false + var stream = new Stream() + stream.readable = stream.writable = true + stream.paused = false +// stream.autoPause = !(opts && opts.autoPause === false) + stream.autoDestroy = !(opts && opts.autoDestroy === false) + stream.write = function (data) { + write.call(this, data) + return !stream.paused + } -var minimist = __webpack_require__("../../node_modules/minimist/index.js"); -var path = __webpack_require__("path"); + function drain() { + while(buffer.length && !stream.paused) { + var data = buffer.shift() + if(null === data) + return stream.emit('end') + else + stream.emit('data', data) + } + } -var Logger = __webpack_require__("../../node_modules/strong-log-transformer/lib/logger.js"); -var pkg = __webpack_require__("../../node_modules/strong-log-transformer/package.json"); + stream.queue = stream.push = function (data) { +// console.error(ended) + if(_ended) return stream + if(data === null) _ended = true + buffer.push(data) + drain() + return stream + } -module.exports = cli; + //this will be registered as the first 'end' listener + //must call destroy next tick, to make sure we're after any + //stream piped from here. + //this is only a problem if end is not emitted synchronously. + //a nicer way to do this is to make sure this is the last listener for 'end' -function cli(args) { - var opts = minimist(args.slice(2)); - var $0 = path.basename(args[1]); - var p = console.log.bind(console); - if (opts.v || opts.version) { - version($0, p); - } else if (opts.h || opts.help) { - usage($0, p); - } else if (args.length < 3) { - process.stdin.pipe(Logger()).pipe(process.stdout); - } else { - process.stdin.pipe(Logger(opts)).pipe(process.stdout); + stream.on('end', function () { + stream.readable = false + if(!stream.writable && stream.autoDestroy) + process.nextTick(function () { + stream.destroy() + }) + }) + + function _end () { + stream.writable = false + end.call(stream) + if(!stream.readable && stream.autoDestroy) + stream.destroy() } -} -function version($0, p) { - p('%s v%s', pkg.name, pkg.version); -} + stream.end = function (data) { + if(ended) return + ended = true + if(arguments.length) stream.write(data) + _end() // will emit or queue + return stream + } -function usage($0, p) { - var PADDING = ' '; - var opt, def; - p('Usage: %s [options]', $0); - p(''); - p('%s', pkg.description); - p(''); - p('OPTIONS:'); - for (opt in Logger.DEFAULTS) { - def = Logger.DEFAULTS[opt]; - if (typeof def === 'boolean') - boolOpt(opt, Logger.DEFAULTS[opt]); - else - stdOpt(opt, Logger.DEFAULTS[opt]); + stream.destroy = function () { + if(destroyed) return + destroyed = true + ended = true + buffer.length = 0 + stream.writable = stream.readable = false + stream.emit('close') + return stream } - p(''); - function boolOpt(name, def) { - name = name + PADDING.slice(0, 20-name.length); - p(' --%s default: %s', name, def); + stream.pause = function () { + if(stream.paused) return + stream.paused = true + return stream } - function stdOpt(name, def) { - var value = name.toUpperCase() + - PADDING.slice(0, 19 - name.length*2); - p(' --%s %s default: %j', name, value, def); + stream.resume = function () { + if(stream.paused) { + stream.paused = false + stream.emit('resume') + } + drain() + //may have become paused again, + //as drain emits 'data'. + if(!stream.paused) + stream.emit('drain') + return stream } + return stream } + /***/ }), -/***/ "../../node_modules/strong-log-transformer/lib/logger.js": +/***/ "../../node_modules/to-regex-range/index.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; -// Copyright IBM Corp. 2014,2018. All Rights Reserved. -// Node module: strong-log-transformer -// This file is licensed under the Apache License 2.0. -// License text available at https://opensource.org/licenses/Apache-2.0 - - - -var stream = __webpack_require__("stream"); -var util = __webpack_require__("util"); -var fs = __webpack_require__("fs"); - -var through = __webpack_require__("../../node_modules/through/index.js"); -var duplexer = __webpack_require__("../../node_modules/duplexer/index.js"); -var StringDecoder = __webpack_require__("string_decoder").StringDecoder; +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ -module.exports = Logger; -Logger.DEFAULTS = { - format: 'text', - tag: '', - mergeMultiline: false, - timeStamp: false, -}; -var formatters = { - text: textFormatter, - json: jsonFormatter, -} +const isNumber = __webpack_require__("../../node_modules/to-regex-range/node_modules/is-number/index.js"); -function Logger(options) { - var defaults = JSON.parse(JSON.stringify(Logger.DEFAULTS)); - options = util._extend(defaults, options || {}); - var catcher = deLiner(); - var emitter = catcher; - var transforms = [ - objectifier(), - ]; +const toRegexRange = (min, max, options) => { + if (isNumber(min) === false) { + throw new TypeError('toRegexRange: expected the first argument to be a number'); + } - if (options.tag) { - transforms.push(staticTagger(options.tag)); + if (max === void 0 || min === max) { + return String(min); } - if (options.mergeMultiline) { - transforms.push(lineMerger()); + if (isNumber(max) === false) { + throw new TypeError('toRegexRange: expected the second argument to be a number.'); } - // TODO - // if (options.pidStamp) { - // transforms.push(pidStamper(options.pid)); - // } + let opts = { relaxZeros: true, ...options }; + if (typeof opts.strictZeros === 'boolean') { + opts.relaxZeros = opts.strictZeros === false; + } - // TODO - // if (options.workerStamp) { - // transforms.push(workerStamper(options.worker)); - // } + let relax = String(opts.relaxZeros); + let shorthand = String(opts.shorthand); + let capture = String(opts.capture); + let wrap = String(opts.wrap); + let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; - transforms.push(formatters[options.format](options)); + if (toRegexRange.cache.hasOwnProperty(cacheKey)) { + return toRegexRange.cache[cacheKey].result; + } - // restore line endings that were removed by line splitting - transforms.push(reLiner()); + let a = Math.min(min, max); + let b = Math.max(min, max); - for (var t in transforms) { - emitter = emitter.pipe(transforms[t]); + if (Math.abs(a - b) === 1) { + let result = min + '|' + max; + if (opts.capture) { + return `(${result})`; + } + if (opts.wrap === false) { + return result; + } + return `(?:${result})`; } - return duplexer(catcher, emitter); -} - -function deLiner() { - var decoder = new StringDecoder('utf8'); - var last = ''; + let isPadded = hasPadding(min) || hasPadding(max); + let state = { min, max, a, b }; + let positives = []; + let negatives = []; - return new stream.Transform({ - transform(chunk, _enc, callback) { - last += decoder.write(chunk); - var list = last.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g); - last = list.pop(); - for (var i = 0; i < list.length; i++) { - // swallow empty lines - if (list[i]) { - this.push(list[i]); - } - } - callback(); - }, - flush(callback) { - // incomplete UTF8 sequences become UTF8 replacement characters - last += decoder.end(); - if (last) { - this.push(last); - } - callback(); - }, - }); -} + if (isPadded) { + state.isPadded = isPadded; + state.maxLen = String(state.max).length; + } -function reLiner() { - return through(appendNewline); + if (a < 0) { + let newMin = b < 0 ? Math.abs(b) : 1; + negatives = splitToPatterns(newMin, Math.abs(a), state, opts); + a = state.a = 0; + } - function appendNewline(line) { - this.emit('data', line + '\n'); + if (b >= 0) { + positives = splitToPatterns(a, b, state, opts); } -} -function objectifier() { - return through(objectify, null, {autoDestroy: false}); + state.negatives = negatives; + state.positives = positives; + state.result = collatePatterns(negatives, positives, opts); - function objectify(line) { - this.emit('data', { - msg: line, - time: Date.now(), - }); + if (opts.capture === true) { + state.result = `(${state.result})`; + } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { + state.result = `(?:${state.result})`; } -} -function staticTagger(tag) { - return through(tagger); + toRegexRange.cache[cacheKey] = state; + return state.result; +}; - function tagger(logEvent) { - logEvent.tag = tag; - this.emit('data', logEvent); - } +function collatePatterns(neg, pos, options) { + let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + let intersected = filterPatterns(neg, pos, '-?', true, options) || []; + let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); } -function textFormatter(options) { - return through(textify); +function splitToRanges(min, max) { + let nines = 1; + let zeros = 1; - function textify(logEvent) { - var line = util.format('%s%s', textifyTags(logEvent.tag), - logEvent.msg.toString()); - if (options.timeStamp) { - line = util.format('%s %s', new Date(logEvent.time).toISOString(), line); - } - this.emit('data', line.replace(/\n/g, '\\n')); + let stop = countNines(min, nines); + let stops = new Set([max]); + + while (min <= stop && stop <= max) { + stops.add(stop); + nines += 1; + stop = countNines(min, nines); } - function textifyTags(tags) { - var str = ''; - if (typeof tags === 'string') { - str = tags + ' '; - } else if (typeof tags === 'object') { - for (var t in tags) { - str += t + ':' + tags[t] + ' '; - } - } - return str; + stop = countZeros(max + 1, zeros) - 1; + + while (min < stop && stop <= max) { + stops.add(stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; } + + stops = [...stops]; + stops.sort(compare); + return stops; } -function jsonFormatter(options) { - return through(jsonify); +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ - function jsonify(logEvent) { - if (options.timeStamp) { - logEvent.time = new Date(logEvent.time).toISOString(); - } else { - delete logEvent.time; - } - logEvent.msg = logEvent.msg.toString(); - this.emit('data', JSON.stringify(logEvent)); +function rangeToPattern(start, stop, options) { + if (start === stop) { + return { pattern: start, count: [], digits: 0 }; } -} -function lineMerger(host) { - var previousLine = null; - var flushTimer = null; - var stream = through(lineMergerWrite, lineMergerEnd); - var flush = _flush.bind(stream); + let zipped = zip(start, stop); + let digits = zipped.length; + let pattern = ''; + let count = 0; + + for (let i = 0; i < digits; i++) { + let [startDigit, stopDigit] = zipped[i]; + + if (startDigit === stopDigit) { + pattern += startDigit; - return stream; + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit, options); - function lineMergerWrite(line) { - if (/^\s+/.test(line.msg)) { - if (previousLine) { - previousLine.msg += '\n' + line.msg; - } else { - previousLine = line; - } } else { - flush(); - previousLine = line; + count++; } - // rolling timeout - clearTimeout(flushTimer); - flushTimer = setTimeout(flush.bind(this), 10); } - function _flush() { - if (previousLine) { - this.emit('data', previousLine); - previousLine = null; - } + if (count) { + pattern += options.shorthand === true ? '\\d' : '[0-9]'; } - function lineMergerEnd() { - flush.call(this); - this.emit('end'); - } + return { pattern, count: [count], digits }; } +function splitToPatterns(min, max, tok, options) { + let ranges = splitToRanges(min, max); + let tokens = []; + let start = min; + let prev; -/***/ }), + for (let i = 0; i < ranges.length; i++) { + let max = ranges[i]; + let obj = rangeToPattern(String(start), String(max), options); + let zeros = ''; -/***/ "../../node_modules/strong-log-transformer/package.json": -/***/ (function(module) { + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.count.length > 1) { + prev.count.pop(); + } -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\"}}"); + prev.count.push(obj.count[0]); + prev.string = prev.pattern + toQuantifier(prev.count); + start = max + 1; + continue; + } -/***/ }), + if (tok.isPadded) { + zeros = padZeros(max, tok, options); + } -/***/ "../../node_modules/supports-color/index.js": -/***/ (function(module, exports, __webpack_require__) { + obj.string = zeros + obj.pattern + toQuantifier(obj.count); + tokens.push(obj); + start = max + 1; + prev = obj; + } -"use strict"; + return tokens; +} -const os = __webpack_require__("os"); -const tty = __webpack_require__("tty"); -const hasFlag = __webpack_require__("../../node_modules/has-flag/index.js"); +function filterPatterns(arr, comparison, prefix, intersection, options) { + let result = []; -const {env} = process; + for (let ele of arr) { + let { string } = ele; -let forceColor; -if (hasFlag('no-color') || - hasFlag('no-colors') || - hasFlag('color=false') || - hasFlag('color=never')) { - forceColor = 0; -} else if (hasFlag('color') || - hasFlag('colors') || - hasFlag('color=true') || - hasFlag('color=always')) { - forceColor = 1; -} + // only push if _both_ are negative... + if (!intersection && !contains(comparison, 'string', string)) { + result.push(prefix + string); + } -if ('FORCE_COLOR' in env) { - if (env.FORCE_COLOR === 'true') { - forceColor = 1; - } else if (env.FORCE_COLOR === 'false') { - forceColor = 0; - } else { - forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3); - } + // or _both_ are positive + if (intersection && contains(comparison, 'string', string)) { + result.push(prefix + string); + } + } + return result; } -function translateLevel(level) { - if (level === 0) { - return false; - } +/** + * Zip strings + */ - return { - level, - hasBasic: true, - has256: level >= 2, - has16m: level >= 3 - }; +function zip(a, b) { + let arr = []; + for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); + return arr; } -function supportsColor(haveStream, streamIsTTY) { - if (forceColor === 0) { - return 0; - } - - if (hasFlag('color=16m') || - hasFlag('color=full') || - hasFlag('color=truecolor')) { - return 3; - } +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; +} - if (hasFlag('color=256')) { - return 2; - } +function contains(arr, key, val) { + return arr.some(ele => ele[key] === val); +} - if (haveStream && !streamIsTTY && forceColor === undefined) { - return 0; - } +function countNines(min, len) { + return Number(String(min).slice(0, -len) + '9'.repeat(len)); +} - const min = forceColor || 0; +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} - if (env.TERM === 'dumb') { - return min; - } +function toQuantifier(digits) { + let [start = 0, stop = ''] = digits; + if (stop || start > 1) { + return `{${start + (stop ? ',' + stop : '')}}`; + } + return ''; +} - if (process.platform === 'win32') { - // Windows 10 build 10586 is the first Windows release that supports 256 colors. - // Windows 10 build 14931 is the first release that supports 16m/TrueColor. - const osRelease = os.release().split('.'); - if ( - Number(osRelease[0]) >= 10 && - Number(osRelease[2]) >= 10586 - ) { - return Number(osRelease[2]) >= 14931 ? 3 : 2; - } +function toCharacterClass(a, b, options) { + return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; +} - return 1; - } +function hasPadding(str) { + return /^-?(0+)\d/.test(str); +} - if ('CI' in env) { - if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { - return 1; - } +function padZeros(value, tok, options) { + if (!tok.isPadded) { + return value; + } - return min; - } + let diff = Math.abs(tok.maxLen - String(value).length); + let relax = options.relaxZeros !== false; - if ('TEAMCITY_VERSION' in env) { - return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; - } + switch (diff) { + case 0: + return ''; + case 1: + return relax ? '0?' : '0'; + case 2: + return relax ? '0{0,2}' : '00'; + default: { + return relax ? `0{0,${diff}}` : `0{${diff}}`; + } + } +} - if ('GITHUB_ACTIONS' in env) { - return 1; - } +/** + * Cache + */ - if (env.COLORTERM === 'truecolor') { - return 3; - } +toRegexRange.cache = {}; +toRegexRange.clearCache = () => (toRegexRange.cache = {}); - if ('TERM_PROGRAM' in env) { - const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); +/** + * Expose `toRegexRange` + */ - switch (env.TERM_PROGRAM) { - case 'iTerm.app': - return version >= 3 ? 3 : 2; - case 'Apple_Terminal': - return 2; - // No default - } - } +module.exports = toRegexRange; - if (/-256(color)?$/i.test(env.TERM)) { - return 2; - } - if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { - return 1; - } +/***/ }), - if ('COLORTERM' in env) { - return 1; - } +/***/ "../../node_modules/to-regex-range/node_modules/is-number/index.js": +/***/ (function(module, exports, __webpack_require__) { - return min; -} +"use strict"; +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ -function getSupportLevel(stream) { - const level = supportsColor(stream, stream && stream.isTTY); - return translateLevel(level); -} -module.exports = { - supportsColor: getSupportLevel, - stdout: translateLevel(supportsColor(true, tty.isatty(1))), - stderr: translateLevel(supportsColor(true, tty.isatty(2))) + +module.exports = function(num) { + if (typeof num === 'number') { + return num - num === 0; + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); + } + return false; }; /***/ }), -/***/ "../../node_modules/through/index.js": +/***/ "../../node_modules/validate-npm-package-license/index.js": /***/ (function(module, exports, __webpack_require__) { -var Stream = __webpack_require__("stream") - -// through -// -// a stream that does nothing but re-emit the input. -// useful for aggregating a series of changing but not ending streams into one stream) - -exports = module.exports = through -through.through = through - -//create a readable writable stream. +var parse = __webpack_require__("../../node_modules/validate-npm-package-license/node_modules/spdx-expression-parse/index.js"); +var correct = __webpack_require__("../../node_modules/validate-npm-package-license/node_modules/spdx-correct/index.js"); -function through (write, end, opts) { - write = write || function (data) { this.queue(data) } - end = end || function () { this.queue(null) } +var genericWarning = ( + 'license should be ' + + 'a valid SPDX license expression (without "LicenseRef"), ' + + '"UNLICENSED", or ' + + '"SEE LICENSE IN "' +); - var ended = false, destroyed = false, buffer = [], _ended = false - var stream = new Stream() - stream.readable = stream.writable = true - stream.paused = false +var fileReferenceRE = /^SEE LICEN[CS]E IN (.+)$/; -// stream.autoPause = !(opts && opts.autoPause === false) - stream.autoDestroy = !(opts && opts.autoDestroy === false) +function startsWith(prefix, string) { + return string.slice(0, prefix.length) === prefix; +} - stream.write = function (data) { - write.call(this, data) - return !stream.paused +function usesLicenseRef(ast) { + if (ast.hasOwnProperty('license')) { + var license = ast.license; + return ( + startsWith('LicenseRef', license) || + startsWith('DocumentRef', license) + ); + } else { + return ( + usesLicenseRef(ast.left) || + usesLicenseRef(ast.right) + ); } +} - function drain() { - while(buffer.length && !stream.paused) { - var data = buffer.shift() - if(null === data) - return stream.emit('end') - else - stream.emit('data', data) +module.exports = function(argument) { + var ast; + + try { + ast = parse(argument); + } catch (e) { + var match + if ( + argument === 'UNLICENSED' || + argument === 'UNLICENCED' + ) { + return { + validForOldPackages: true, + validForNewPackages: true, + unlicensed: true + }; + } else if (match = fileReferenceRE.exec(argument)) { + return { + validForOldPackages: true, + validForNewPackages: true, + inFile: match[1] + }; + } else { + var result = { + validForOldPackages: false, + validForNewPackages: false, + warnings: [genericWarning] + }; + var corrected = correct(argument); + if (corrected) { + result.warnings.push( + 'license is similar to the valid expression "' + corrected + '"' + ); + } + return result; } } - stream.queue = stream.push = function (data) { -// console.error(ended) - if(_ended) return stream - if(data === null) _ended = true - buffer.push(data) - drain() - return stream + if (usesLicenseRef(ast)) { + return { + validForNewPackages: false, + validForOldPackages: false, + spdx: true, + warnings: [genericWarning] + }; + } else { + return { + validForNewPackages: true, + validForOldPackages: true, + spdx: true + }; } +}; - //this will be registered as the first 'end' listener - //must call destroy next tick, to make sure we're after any - //stream piped from here. - //this is only a problem if end is not emitted synchronously. - //a nicer way to do this is to make sure this is the last listener for 'end' - stream.on('end', function () { - stream.readable = false - if(!stream.writable && stream.autoDestroy) - process.nextTick(function () { - stream.destroy() - }) - }) +/***/ }), - function _end () { - stream.writable = false - end.call(stream) - if(!stream.readable && stream.autoDestroy) - stream.destroy() - } +/***/ "../../node_modules/validate-npm-package-license/node_modules/spdx-correct/index.js": +/***/ (function(module, exports, __webpack_require__) { - stream.end = function (data) { - if(ended) return - ended = true - if(arguments.length) stream.write(data) - _end() // will emit or queue - return stream +var licenseIDs = __webpack_require__("../../node_modules/validate-npm-package-license/node_modules/spdx-license-ids/spdx-license-ids.json"); + +function valid(string) { + return licenseIDs.indexOf(string) > -1; +} + +// Common transpositions of license identifier acronyms +var transpositions = [ + ['APGL', 'AGPL'], + ['Gpl', 'GPL'], + ['GLP', 'GPL'], + ['APL', 'Apache'], + ['ISD', 'ISC'], + ['GLP', 'GPL'], + ['IST', 'ISC'], + ['Claude', 'Clause'], + [' or later', '+'], + [' International', ''], + ['GNU', 'GPL'], + ['GUN', 'GPL'], + ['+', ''], + ['GNU GPL', 'GPL'], + ['GNU/GPL', 'GPL'], + ['GNU GLP', 'GPL'], + ['GNU General Public License', 'GPL'], + ['Gnu public license', 'GPL'], + ['GNU Public License', 'GPL'], + ['GNU GENERAL PUBLIC LICENSE', 'GPL'], + ['MTI', 'MIT'], + ['Mozilla Public License', 'MPL'], + ['WTH', 'WTF'], + ['-License', ''] +]; + +var TRANSPOSED = 0; +var CORRECT = 1; + +// Simple corrections to nearly valid identifiers. +var transforms = [ + // e.g. 'mit' + function(argument) { + return argument.toUpperCase(); + }, + // e.g. 'MIT ' + function(argument) { + return argument.trim(); + }, + // e.g. 'M.I.T.' + function(argument) { + return argument.replace(/\./g, ''); + }, + // e.g. 'Apache- 2.0' + function(argument) { + return argument.replace(/\s+/g, ''); + }, + // e.g. 'CC BY 4.0'' + function(argument) { + return argument.replace(/\s+/g, '-'); + }, + // e.g. 'LGPLv2.1' + function(argument) { + return argument.replace('v', '-'); + }, + // e.g. 'Apache 2.0' + function(argument) { + return argument.replace(/,?\s*(\d)/, '-$1'); + }, + // e.g. 'GPL 2' + function(argument) { + return argument.replace(/,?\s*(\d)/, '-$1.0'); + }, + // e.g. 'Apache Version 2.0' + function(argument) { + return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2'); + }, + // e.g. 'Apache Version 2' + function(argument) { + return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2.0'); + }, + // e.g. 'ZLIB' + function(argument) { + return argument[0].toUpperCase() + argument.slice(1); + }, + // e.g. 'MPL/2.0' + function(argument) { + return argument.replace('/', '-'); + }, + // e.g. 'Apache 2' + function(argument) { + return argument + .replace(/\s*V\s*(\d)/, '-$1') + .replace(/(\d)$/, '$1.0'); + }, + // e.g. 'GPL-2.0-' + function(argument) { + return argument.slice(0, argument.length - 1); + }, + // e.g. 'GPL2' + function(argument) { + return argument.replace(/(\d)$/, '-$1.0'); + }, + // e.g. 'BSD 3' + function(argument) { + return argument.replace(/(-| )?(\d)$/, '-$2-Clause'); + }, + // e.g. 'BSD clause 3' + function(argument) { + return argument.replace(/(-| )clause(-| )(\d)/, '-$3-Clause'); + }, + // e.g. 'BY-NC-4.0' + function(argument) { + return 'CC-' + argument; + }, + // e.g. 'BY-NC' + function(argument) { + return 'CC-' + argument + '-4.0'; + }, + // e.g. 'Attribution-NonCommercial' + function(argument) { + return argument + .replace('Attribution', 'BY') + .replace('NonCommercial', 'NC') + .replace('NoDerivatives', 'ND') + .replace(/ (\d)/, '-$1') + .replace(/ ?International/, ''); + }, + // e.g. 'Attribution-NonCommercial' + function(argument) { + return 'CC-' + + argument + .replace('Attribution', 'BY') + .replace('NonCommercial', 'NC') + .replace('NoDerivatives', 'ND') + .replace(/ (\d)/, '-$1') + .replace(/ ?International/, '') + + '-4.0'; } +]; - stream.destroy = function () { - if(destroyed) return - destroyed = true - ended = true - buffer.length = 0 - stream.writable = stream.readable = false - stream.emit('close') - return stream - } +// If all else fails, guess that strings containing certain substrings +// meant to identify certain licenses. +var lastResorts = [ + ['UNLI', 'Unlicense'], + ['WTF', 'WTFPL'], + ['2 CLAUSE', 'BSD-2-Clause'], + ['2-CLAUSE', 'BSD-2-Clause'], + ['3 CLAUSE', 'BSD-3-Clause'], + ['3-CLAUSE', 'BSD-3-Clause'], + ['AFFERO', 'AGPL-3.0'], + ['AGPL', 'AGPL-3.0'], + ['APACHE', 'Apache-2.0'], + ['ARTISTIC', 'Artistic-2.0'], + ['Affero', 'AGPL-3.0'], + ['BEER', 'Beerware'], + ['BOOST', 'BSL-1.0'], + ['BSD', 'BSD-2-Clause'], + ['ECLIPSE', 'EPL-1.0'], + ['FUCK', 'WTFPL'], + ['GNU', 'GPL-3.0'], + ['LGPL', 'LGPL-3.0'], + ['GPL', 'GPL-3.0'], + ['MIT', 'MIT'], + ['MPL', 'MPL-2.0'], + ['X11', 'X11'], + ['ZLIB', 'Zlib'] +]; - stream.pause = function () { - if(stream.paused) return - stream.paused = true - return stream - } +var SUBSTRING = 0; +var IDENTIFIER = 1; - stream.resume = function () { - if(stream.paused) { - stream.paused = false - stream.emit('resume') +var validTransformation = function(identifier) { + for (var i = 0; i < transforms.length; i++) { + var transformed = transforms[i](identifier); + if (transformed !== identifier && valid(transformed)) { + return transformed; } - drain() - //may have become paused again, - //as drain emits 'data'. - if(!stream.paused) - stream.emit('drain') - return stream - } - return stream -} - - - -/***/ }), - -/***/ "../../node_modules/to-regex-range/index.js": -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * to-regex-range - * - * Copyright (c) 2015-present, Jon Schlinkert. - * Released under the MIT License. - */ - - - -const isNumber = __webpack_require__("../../node_modules/to-regex-range/node_modules/is-number/index.js"); - -const toRegexRange = (min, max, options) => { - if (isNumber(min) === false) { - throw new TypeError('toRegexRange: expected the first argument to be a number'); } + return null; +}; - if (max === void 0 || min === max) { - return String(min); +var validLastResort = function(identifier) { + var upperCased = identifier.toUpperCase(); + for (var i = 0; i < lastResorts.length; i++) { + var lastResort = lastResorts[i]; + if (upperCased.indexOf(lastResort[SUBSTRING]) > -1) { + return lastResort[IDENTIFIER]; + } } + return null; +}; - if (isNumber(max) === false) { - throw new TypeError('toRegexRange: expected the second argument to be a number.'); +var anyCorrection = function(identifier, check) { + for (var i = 0; i < transpositions.length; i++) { + var transposition = transpositions[i]; + var transposed = transposition[TRANSPOSED]; + if (identifier.indexOf(transposed) > -1) { + var corrected = identifier.replace( + transposed, + transposition[CORRECT] + ); + var checked = check(corrected); + if (checked !== null) { + return checked; + } + } } + return null; +}; - let opts = { relaxZeros: true, ...options }; - if (typeof opts.strictZeros === 'boolean') { - opts.relaxZeros = opts.strictZeros === false; +module.exports = function(identifier) { + identifier = identifier.replace(/\+$/, ''); + if (valid(identifier)) { + return identifier; } - - let relax = String(opts.relaxZeros); - let shorthand = String(opts.shorthand); - let capture = String(opts.capture); - let wrap = String(opts.wrap); - let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; - - if (toRegexRange.cache.hasOwnProperty(cacheKey)) { - return toRegexRange.cache[cacheKey].result; + var transformed = validTransformation(identifier); + if (transformed !== null) { + return transformed; } - - let a = Math.min(min, max); - let b = Math.max(min, max); - - if (Math.abs(a - b) === 1) { - let result = min + '|' + max; - if (opts.capture) { - return `(${result})`; - } - if (opts.wrap === false) { - return result; + transformed = anyCorrection(identifier, function(argument) { + if (valid(argument)) { + return argument; } - return `(?:${result})`; - } - - let isPadded = hasPadding(min) || hasPadding(max); - let state = { min, max, a, b }; - let positives = []; - let negatives = []; - - if (isPadded) { - state.isPadded = isPadded; - state.maxLen = String(state.max).length; - } - - if (a < 0) { - let newMin = b < 0 ? Math.abs(b) : 1; - negatives = splitToPatterns(newMin, Math.abs(a), state, opts); - a = state.a = 0; + return validTransformation(argument); + }); + if (transformed !== null) { + return transformed; } - - if (b >= 0) { - positives = splitToPatterns(a, b, state, opts); + transformed = validLastResort(identifier); + if (transformed !== null) { + return transformed; } - - state.negatives = negatives; - state.positives = positives; - state.result = collatePatterns(negatives, positives, opts); - - if (opts.capture === true) { - state.result = `(${state.result})`; - } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { - state.result = `(?:${state.result})`; + transformed = anyCorrection(identifier, validLastResort); + if (transformed !== null) { + return transformed; } - - toRegexRange.cache[cacheKey] = state; - return state.result; + return null; }; -function collatePatterns(neg, pos, options) { - let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; - let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; - let intersected = filterPatterns(neg, pos, '-?', true, options) || []; - let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); - return subpatterns.join('|'); -} - -function splitToRanges(min, max) { - let nines = 1; - let zeros = 1; - - let stop = countNines(min, nines); - let stops = new Set([max]); - - while (min <= stop && stop <= max) { - stops.add(stop); - nines += 1; - stop = countNines(min, nines); - } - - stop = countZeros(max + 1, zeros) - 1; - - while (min < stop && stop <= max) { - stops.add(stop); - zeros += 1; - stop = countZeros(max + 1, zeros) - 1; - } - - stops = [...stops]; - stops.sort(compare); - return stops; -} -/** - * Convert a range to a regex pattern - * @param {Number} `start` - * @param {Number} `stop` - * @return {String} - */ +/***/ }), -function rangeToPattern(start, stop, options) { - if (start === stop) { - return { pattern: start, count: [], digits: 0 }; - } +/***/ "../../node_modules/validate-npm-package-license/node_modules/spdx-expression-parse/index.js": +/***/ (function(module, exports, __webpack_require__) { - let zipped = zip(start, stop); - let digits = zipped.length; - let pattern = ''; - let count = 0; +var parser = __webpack_require__("../../node_modules/validate-npm-package-license/node_modules/spdx-expression-parse/parser.js").parser - for (let i = 0; i < digits; i++) { - let [startDigit, stopDigit] = zipped[i]; +module.exports = function (argument) { + return parser.parse(argument) +} - if (startDigit === stopDigit) { - pattern += startDigit; - } else if (startDigit !== '0' || stopDigit !== '9') { - pattern += toCharacterClass(startDigit, stopDigit, options); +/***/ }), - } else { - count++; - } - } +/***/ "../../node_modules/validate-npm-package-license/node_modules/spdx-expression-parse/parser.js": +/***/ (function(module, exports, __webpack_require__) { - if (count) { - pattern += options.shorthand === true ? '\\d' : '[0-9]'; - } +/* WEBPACK VAR INJECTION */(function(module) {/* parser generated by jison 0.4.17 */ +/* + Returns a Parser object of the following structure: - return { pattern, count: [count], digits }; -} + Parser: { + yy: {} + } -function splitToPatterns(min, max, tok, options) { - let ranges = splitToRanges(min, max); - let tokens = []; - let start = min; - let prev; + Parser.prototype: { + yy: {}, + trace: function(), + symbols_: {associative list: name ==> number}, + terminals_: {associative list: number ==> name}, + productions_: [...], + performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), + table: [...], + defaultActions: {...}, + parseError: function(str, hash), + parse: function(input), - for (let i = 0; i < ranges.length; i++) { - let max = ranges[i]; - let obj = rangeToPattern(String(start), String(max), options); - let zeros = ''; + lexer: { + EOF: 1, + parseError: function(str, hash), + setInput: function(input), + input: function(), + unput: function(str), + more: function(), + less: function(n), + pastInput: function(), + upcomingInput: function(), + showPosition: function(), + test_match: function(regex_match_array, rule_index), + next: function(), + lex: function(), + begin: function(condition), + popState: function(), + _currentRules: function(), + topState: function(), + pushState: function(condition), - if (!tok.isPadded && prev && prev.pattern === obj.pattern) { - if (prev.count.length > 1) { - prev.count.pop(); - } + options: { + ranges: boolean (optional: true ==> token location info will include a .range[] member) + flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) + backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) + }, - prev.count.push(obj.count[0]); - prev.string = prev.pattern + toQuantifier(prev.count); - start = max + 1; - continue; + performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), + rules: [...], + conditions: {associative list: name ==> set}, } + } - if (tok.isPadded) { - zeros = padZeros(max, tok, options); - } - obj.string = zeros + obj.pattern + toQuantifier(obj.count); - tokens.push(obj); - start = max + 1; - prev = obj; + token location info (@$, _$, etc.): { + first_line: n, + last_line: n, + first_column: n, + last_column: n, + range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) } - return tokens; -} -function filterPatterns(arr, comparison, prefix, intersection, options) { - let result = []; + the parseError function receives a 'hash' object with these members for lexer and parser errors: { + text: (matched text) + token: (the produced terminal token, if any) + line: (yylineno) + } + while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { + loc: (yylloc) + expected: (string describing the set of expected tokens) + recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) + } +*/ +var spdxparse = (function(){ +var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,6],$V2=[1,7],$V3=[1,4],$V4=[1,9],$V5=[1,10],$V6=[5,14,15,17],$V7=[5,12,14,15,17]; +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"start":3,"expression":4,"EOS":5,"simpleExpression":6,"LICENSE":7,"PLUS":8,"LICENSEREF":9,"DOCUMENTREF":10,"COLON":11,"WITH":12,"EXCEPTION":13,"AND":14,"OR":15,"OPEN":16,"CLOSE":17,"$accept":0,"$end":1}, +terminals_: {2:"error",5:"EOS",7:"LICENSE",8:"PLUS",9:"LICENSEREF",10:"DOCUMENTREF",11:"COLON",12:"WITH",13:"EXCEPTION",14:"AND",15:"OR",16:"OPEN",17:"CLOSE"}, +productions_: [0,[3,2],[6,1],[6,2],[6,1],[6,3],[4,1],[4,3],[4,3],[4,3],[4,3]], +performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { +/* this == yyval */ - for (let ele of arr) { - let { string } = ele; +var $0 = $$.length - 1; +switch (yystate) { +case 1: +return this.$ = $$[$0-1] +break; +case 2: case 4: case 5: +this.$ = {license: yytext} +break; +case 3: +this.$ = {license: $$[$0-1], plus: true} +break; +case 6: +this.$ = $$[$0] +break; +case 7: +this.$ = {exception: $$[$0]} +this.$.license = $$[$0-2].license +if ($$[$0-2].hasOwnProperty('plus')) { + this.$.plus = $$[$0-2].plus +} +break; +case 8: +this.$ = {conjunction: 'and', left: $$[$0-2], right: $$[$0]} +break; +case 9: +this.$ = {conjunction: 'or', left: $$[$0-2], right: $$[$0]} +break; +case 10: +this.$ = $$[$0-1] +break; +} +}, +table: [{3:1,4:2,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{1:[3]},{5:[1,8],14:$V4,15:$V5},o($V6,[2,6],{12:[1,11]}),{4:12,6:3,7:$V0,9:$V1,10:$V2,16:$V3},o($V7,[2,2],{8:[1,13]}),o($V7,[2,4]),{11:[1,14]},{1:[2,1]},{4:15,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{4:16,6:3,7:$V0,9:$V1,10:$V2,16:$V3},{13:[1,17]},{14:$V4,15:$V5,17:[1,18]},o($V7,[2,3]),{9:[1,19]},o($V6,[2,8]),o([5,15,17],[2,9],{14:$V4}),o($V6,[2,7]),o($V6,[2,10]),o($V7,[2,5])], +defaultActions: {8:[2,1]}, +parseError: function parseError(str, hash) { + if (hash.recoverable) { + this.trace(str); + } else { + function _parseError (msg, hash) { + this.message = msg; + this.hash = hash; + } + _parseError.prototype = Error; - // only push if _both_ are negative... - if (!intersection && !contains(comparison, 'string', string)) { - result.push(prefix + string); + throw new _parseError(str, hash); } - - // or _both_ are positive - if (intersection && contains(comparison, 'string', string)) { - result.push(prefix + string); +}, +parse: function parse(input) { + var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; + var args = lstack.slice.call(arguments, 1); + var lexer = Object.create(this.lexer); + var sharedState = { yy: {} }; + for (var k in this.yy) { + if (Object.prototype.hasOwnProperty.call(this.yy, k)) { + sharedState.yy[k] = this.yy[k]; + } + } + lexer.setInput(input, sharedState.yy); + sharedState.yy.lexer = lexer; + sharedState.yy.parser = this; + if (typeof lexer.yylloc == 'undefined') { + lexer.yylloc = {}; + } + var yyloc = lexer.yylloc; + lstack.push(yyloc); + var ranges = lexer.options && lexer.options.ranges; + if (typeof sharedState.yy.parseError === 'function') { + this.parseError = sharedState.yy.parseError; + } else { + this.parseError = Object.getPrototypeOf(this).parseError; + } + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + _token_stack: + var lex = function () { + var token; + token = lexer.lex() || EOF; + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + }; + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == 'undefined') { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === 'undefined' || !action.length || !action[0]) { + var errStr = ''; + expected = []; + for (p in table[state]) { + if (this.terminals_[p] && p > TERROR) { + expected.push('\'' + this.terminals_[p] + '\''); + } + } + if (lexer.showPosition) { + errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; + } else { + errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); + } + this.parseError(errStr, { + text: lexer.match, + token: this.terminals_[symbol] || symbol, + line: lexer.yylineno, + loc: yyloc, + expected: expected + }); + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(lexer.yytext); + lstack.push(lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = lexer.yyleng; + yytext = lexer.yytext; + yylineno = lexer.yylineno; + yyloc = lexer.yylloc; + if (recovering > 0) { + recovering--; + } + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = { + first_line: lstack[lstack.length - (len || 1)].first_line, + last_line: lstack[lstack.length - 1].last_line, + first_column: lstack[lstack.length - (len || 1)].first_column, + last_column: lstack[lstack.length - 1].last_column + }; + if (ranges) { + yyval._$.range = [ + lstack[lstack.length - (len || 1)].range[0], + lstack[lstack.length - 1].range[1] + ]; + } + r = this.performAction.apply(yyval, [ + yytext, + yyleng, + yylineno, + sharedState.yy, + action[1], + vstack, + lstack + ].concat(args)); + if (typeof r !== 'undefined') { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } } - } - return result; -} - -/** - * Zip strings - */ - -function zip(a, b) { - let arr = []; - for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); - return arr; -} - -function compare(a, b) { - return a > b ? 1 : b > a ? -1 : 0; -} - -function contains(arr, key, val) { - return arr.some(ele => ele[key] === val); -} - -function countNines(min, len) { - return Number(String(min).slice(0, -len) + '9'.repeat(len)); -} - -function countZeros(integer, zeros) { - return integer - (integer % Math.pow(10, zeros)); -} - -function toQuantifier(digits) { - let [start = 0, stop = ''] = digits; - if (stop || start > 1) { - return `{${start + (stop ? ',' + stop : '')}}`; - } - return ''; -} - -function toCharacterClass(a, b, options) { - return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; -} - -function hasPadding(str) { - return /^-?(0+)\d/.test(str); -} - -function padZeros(value, tok, options) { - if (!tok.isPadded) { - return value; - } - - let diff = Math.abs(tok.maxLen - String(value).length); - let relax = options.relaxZeros !== false; + return true; +}}; +/* generated by jison-lex 0.3.4 */ +var lexer = (function(){ +var lexer = ({ - switch (diff) { - case 0: - return ''; - case 1: - return relax ? '0?' : '0'; - case 2: - return relax ? '0{0,2}' : '00'; - default: { - return relax ? `0{0,${diff}}` : `0{${diff}}`; - } - } -} +EOF:1, -/** - * Cache - */ +parseError:function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, -toRegexRange.cache = {}; -toRegexRange.clearCache = () => (toRegexRange.cache = {}); +// resets the lexer, sets new input +setInput:function (input, yy) { + this.yy = yy || this.yy || {}; + this._input = input; + this._more = this._backtrack = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = { + first_line: 1, + first_column: 0, + last_line: 1, + last_column: 0 + }; + if (this.options.ranges) { + this.yylloc.range = [0,0]; + } + this.offset = 0; + return this; + }, -/** - * Expose `toRegexRange` - */ +// consumes and returns one char from the input +input:function () { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) { + this.yylloc.range[1]++; + } -module.exports = toRegexRange; + this._input = this._input.slice(1); + return ch; + }, +// unshifts one char (or a string) into the input +unput:function (ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); -/***/ }), + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length - len); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length - 1); + this.matched = this.matched.substr(0, this.matched.length - 1); -/***/ "../../node_modules/to-regex-range/node_modules/is-number/index.js": -/***/ (function(module, exports, __webpack_require__) { + if (lines.length - 1) { + this.yylineno -= lines.length - 1; + } + var r = this.yylloc.range; -"use strict"; -/*! - * is-number - * - * Copyright (c) 2014-present, Jon Schlinkert. - * Released under the MIT License. - */ + this.yylloc = { + first_line: this.yylloc.first_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.first_column, + last_column: lines ? + (lines.length === oldLines.length ? this.yylloc.first_column : 0) + + oldLines[oldLines.length - lines.length].length - lines[0].length : + this.yylloc.first_column - len + }; + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + this.yyleng = this.yytext.length; + return this; + }, +// When called from action, caches matched text and appends it on next action +more:function () { + this._more = true; + return this; + }, -module.exports = function(num) { - if (typeof num === 'number') { - return num - num === 0; - } - if (typeof num === 'string' && num.trim() !== '') { - return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); - } - return false; -}; +// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. +reject:function () { + if (this.options.backtrack_lexer) { + this._backtrack = true; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { + text: "", + token: null, + line: this.yylineno + }); + } + return this; + }, -/***/ }), +// retain first n characters of the match +less:function (n) { + this.unput(this.match.slice(n)); + }, -/***/ "../../node_modules/validate-npm-package-license/index.js": -/***/ (function(module, exports, __webpack_require__) { +// displays already matched input, i.e. for error messages +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, -var parse = __webpack_require__("../../node_modules/spdx-expression-parse/index.js"); -var correct = __webpack_require__("../../node_modules/validate-npm-package-license/node_modules/spdx-correct/index.js"); +// displays upcoming input, i.e. for error messages +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); + }, -var genericWarning = ( - 'license should be ' + - 'a valid SPDX license expression (without "LicenseRef"), ' + - '"UNLICENSED", or ' + - '"SEE LICENSE IN "' -); +// displays the character position where the lexing error occurred, i.e. for error messages +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c + "^"; + }, -var fileReferenceRE = /^SEE LICEN[CS]E IN (.+)$/; +// test the lexed token: return FALSE when not a match, otherwise return token +test_match:function (match, indexed_rule) { + var token, + lines, + backup; -function startsWith(prefix, string) { - return string.slice(0, prefix.length) === prefix; -} + if (this.options.backtrack_lexer) { + // save context + backup = { + yylineno: this.yylineno, + yylloc: { + first_line: this.yylloc.first_line, + last_line: this.last_line, + first_column: this.yylloc.first_column, + last_column: this.yylloc.last_column + }, + yytext: this.yytext, + match: this.match, + matches: this.matches, + matched: this.matched, + yyleng: this.yyleng, + offset: this.offset, + _more: this._more, + _input: this._input, + yy: this.yy, + conditionStack: this.conditionStack.slice(0), + done: this.done + }; + if (this.options.ranges) { + backup.yylloc.range = this.yylloc.range.slice(0); + } + } -function usesLicenseRef(ast) { - if (ast.hasOwnProperty('license')) { - var license = ast.license; - return ( - startsWith('LicenseRef', license) || - startsWith('DocumentRef', license) - ); - } else { - return ( - usesLicenseRef(ast.left) || - usesLicenseRef(ast.right) - ); - } -} + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno += lines.length; + } + this.yylloc = { + first_line: this.yylloc.last_line, + last_line: this.yylineno + 1, + first_column: this.yylloc.last_column, + last_column: lines ? + lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : + this.yylloc.last_column + match[0].length + }; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._backtrack = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); + if (this.done && this._input) { + this.done = false; + } + if (token) { + return token; + } else if (this._backtrack) { + // recover context + for (var k in backup) { + this[k] = backup[k]; + } + return false; // rule action called reject() implying the next rule should be tested instead. + } + return false; + }, -module.exports = function(argument) { - var ast; +// return next match in input +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) { + this.done = true; + } - try { - ast = parse(argument); - } catch (e) { - var match - if ( - argument === 'UNLICENSED' || - argument === 'UNLICENCED' - ) { - return { - validForOldPackages: true, - validForNewPackages: true, - unlicensed: true - }; - } else if (match = fileReferenceRE.exec(argument)) { - return { - validForOldPackages: true, - validForNewPackages: true, - inFile: match[1] - }; - } else { - var result = { - validForOldPackages: false, - validForNewPackages: false, - warnings: [genericWarning] - }; - var corrected = correct(argument); - if (corrected) { - result.warnings.push( - 'license is similar to the valid expression "' + corrected + '"' - ); - } - return result; - } - } + var token, + match, + tempMatch, + index; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i = 0; i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (this.options.backtrack_lexer) { + token = this.test_match(tempMatch, rules[i]); + if (token !== false) { + return token; + } else if (this._backtrack) { + match = false; + continue; // rule action called reject() implying a rule MISmatch. + } else { + // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) + return false; + } + } else if (!this.options.flex) { + break; + } + } + } + if (match) { + token = this.test_match(match, rules[index]); + if (token !== false) { + return token; + } + // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) + return false; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { + text: "", + token: null, + line: this.yylineno + }); + } + }, - if (usesLicenseRef(ast)) { - return { - validForNewPackages: false, - validForOldPackages: false, - spdx: true, - warnings: [genericWarning] - }; - } else { - return { - validForNewPackages: true, - validForOldPackages: true, - spdx: true - }; - } -}; +// return next match that has a token +lex:function lex() { + var r = this.next(); + if (r) { + return r; + } else { + return this.lex(); + } + }, + +// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) +begin:function begin(condition) { + this.conditionStack.push(condition); + }, +// pop the previously active lexer condition state off the condition stack +popState:function popState() { + var n = this.conditionStack.length - 1; + if (n > 0) { + return this.conditionStack.pop(); + } else { + return this.conditionStack[0]; + } + }, -/***/ }), +// produce the lexer rule set which is active for the currently active lexer condition state +_currentRules:function _currentRules() { + if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { + return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; + } else { + return this.conditions["INITIAL"].rules; + } + }, -/***/ "../../node_modules/validate-npm-package-license/node_modules/spdx-correct/index.js": -/***/ (function(module, exports, __webpack_require__) { +// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available +topState:function topState(n) { + n = this.conditionStack.length - 1 - Math.abs(n || 0); + if (n >= 0) { + return this.conditionStack[n]; + } else { + return "INITIAL"; + } + }, -var licenseIDs = __webpack_require__("../../node_modules/spdx-license-ids/spdx-license-ids.json"); +// alias for begin(condition) +pushState:function pushState(condition) { + this.begin(condition); + }, -function valid(string) { - return licenseIDs.indexOf(string) > -1; +// return the number of states currently on the stack +stateStackSize:function stateStackSize() { + return this.conditionStack.length; + }, +options: {}, +performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { +var YYSTATE=YY_START; +switch($avoiding_name_collisions) { +case 0:return 5 +break; +case 1:/* skip whitespace */ +break; +case 2:return 8 +break; +case 3:return 16 +break; +case 4:return 17 +break; +case 5:return 11 +break; +case 6:return 10 +break; +case 7:return 9 +break; +case 8:return 14 +break; +case 9:return 15 +break; +case 10:return 12 +break; +case 11:return 7 +break; +case 12:return 7 +break; +case 13:return 7 +break; +case 14:return 7 +break; +case 15:return 7 +break; +case 16:return 7 +break; +case 17:return 7 +break; +case 18:return 7 +break; +case 19:return 7 +break; +case 20:return 7 +break; +case 21:return 7 +break; +case 22:return 7 +break; +case 23:return 7 +break; +case 24:return 13 +break; +case 25:return 13 +break; +case 26:return 13 +break; +case 27:return 13 +break; +case 28:return 13 +break; +case 29:return 13 +break; +case 30:return 13 +break; +case 31:return 13 +break; +case 32:return 7 +break; +case 33:return 13 +break; +case 34:return 7 +break; +case 35:return 13 +break; +case 36:return 7 +break; +case 37:return 13 +break; +case 38:return 13 +break; +case 39:return 7 +break; +case 40:return 13 +break; +case 41:return 13 +break; +case 42:return 13 +break; +case 43:return 13 +break; +case 44:return 13 +break; +case 45:return 7 +break; +case 46:return 13 +break; +case 47:return 7 +break; +case 48:return 7 +break; +case 49:return 7 +break; +case 50:return 7 +break; +case 51:return 7 +break; +case 52:return 7 +break; +case 53:return 7 +break; +case 54:return 7 +break; +case 55:return 7 +break; +case 56:return 7 +break; +case 57:return 7 +break; +case 58:return 7 +break; +case 59:return 7 +break; +case 60:return 7 +break; +case 61:return 7 +break; +case 62:return 7 +break; +case 63:return 13 +break; +case 64:return 7 +break; +case 65:return 7 +break; +case 66:return 13 +break; +case 67:return 7 +break; +case 68:return 7 +break; +case 69:return 7 +break; +case 70:return 7 +break; +case 71:return 7 +break; +case 72:return 7 +break; +case 73:return 13 +break; +case 74:return 7 +break; +case 75:return 13 +break; +case 76:return 7 +break; +case 77:return 7 +break; +case 78:return 7 +break; +case 79:return 7 +break; +case 80:return 7 +break; +case 81:return 7 +break; +case 82:return 7 +break; +case 83:return 7 +break; +case 84:return 7 +break; +case 85:return 7 +break; +case 86:return 7 +break; +case 87:return 7 +break; +case 88:return 7 +break; +case 89:return 7 +break; +case 90:return 7 +break; +case 91:return 7 +break; +case 92:return 7 +break; +case 93:return 7 +break; +case 94:return 7 +break; +case 95:return 7 +break; +case 96:return 7 +break; +case 97:return 7 +break; +case 98:return 7 +break; +case 99:return 7 +break; +case 100:return 7 +break; +case 101:return 7 +break; +case 102:return 7 +break; +case 103:return 7 +break; +case 104:return 7 +break; +case 105:return 7 +break; +case 106:return 7 +break; +case 107:return 7 +break; +case 108:return 7 +break; +case 109:return 7 +break; +case 110:return 7 +break; +case 111:return 7 +break; +case 112:return 7 +break; +case 113:return 7 +break; +case 114:return 7 +break; +case 115:return 7 +break; +case 116:return 7 +break; +case 117:return 7 +break; +case 118:return 7 +break; +case 119:return 7 +break; +case 120:return 7 +break; +case 121:return 7 +break; +case 122:return 7 +break; +case 123:return 7 +break; +case 124:return 7 +break; +case 125:return 7 +break; +case 126:return 7 +break; +case 127:return 7 +break; +case 128:return 7 +break; +case 129:return 7 +break; +case 130:return 7 +break; +case 131:return 7 +break; +case 132:return 7 +break; +case 133:return 7 +break; +case 134:return 7 +break; +case 135:return 7 +break; +case 136:return 7 +break; +case 137:return 7 +break; +case 138:return 7 +break; +case 139:return 7 +break; +case 140:return 7 +break; +case 141:return 7 +break; +case 142:return 7 +break; +case 143:return 7 +break; +case 144:return 7 +break; +case 145:return 7 +break; +case 146:return 7 +break; +case 147:return 7 +break; +case 148:return 7 +break; +case 149:return 7 +break; +case 150:return 7 +break; +case 151:return 7 +break; +case 152:return 7 +break; +case 153:return 7 +break; +case 154:return 7 +break; +case 155:return 7 +break; +case 156:return 7 +break; +case 157:return 7 +break; +case 158:return 7 +break; +case 159:return 7 +break; +case 160:return 7 +break; +case 161:return 7 +break; +case 162:return 7 +break; +case 163:return 7 +break; +case 164:return 7 +break; +case 165:return 7 +break; +case 166:return 7 +break; +case 167:return 7 +break; +case 168:return 7 +break; +case 169:return 7 +break; +case 170:return 7 +break; +case 171:return 7 +break; +case 172:return 7 +break; +case 173:return 7 +break; +case 174:return 7 +break; +case 175:return 7 +break; +case 176:return 7 +break; +case 177:return 7 +break; +case 178:return 7 +break; +case 179:return 7 +break; +case 180:return 7 +break; +case 181:return 7 +break; +case 182:return 7 +break; +case 183:return 7 +break; +case 184:return 7 +break; +case 185:return 7 +break; +case 186:return 7 +break; +case 187:return 7 +break; +case 188:return 7 +break; +case 189:return 7 +break; +case 190:return 7 +break; +case 191:return 7 +break; +case 192:return 7 +break; +case 193:return 7 +break; +case 194:return 7 +break; +case 195:return 7 +break; +case 196:return 7 +break; +case 197:return 7 +break; +case 198:return 7 +break; +case 199:return 7 +break; +case 200:return 7 +break; +case 201:return 7 +break; +case 202:return 7 +break; +case 203:return 7 +break; +case 204:return 7 +break; +case 205:return 7 +break; +case 206:return 7 +break; +case 207:return 7 +break; +case 208:return 7 +break; +case 209:return 7 +break; +case 210:return 7 +break; +case 211:return 7 +break; +case 212:return 7 +break; +case 213:return 7 +break; +case 214:return 7 +break; +case 215:return 7 +break; +case 216:return 7 +break; +case 217:return 7 +break; +case 218:return 7 +break; +case 219:return 7 +break; +case 220:return 7 +break; +case 221:return 7 +break; +case 222:return 7 +break; +case 223:return 7 +break; +case 224:return 7 +break; +case 225:return 7 +break; +case 226:return 7 +break; +case 227:return 7 +break; +case 228:return 7 +break; +case 229:return 7 +break; +case 230:return 7 +break; +case 231:return 7 +break; +case 232:return 7 +break; +case 233:return 7 +break; +case 234:return 7 +break; +case 235:return 7 +break; +case 236:return 7 +break; +case 237:return 7 +break; +case 238:return 7 +break; +case 239:return 7 +break; +case 240:return 7 +break; +case 241:return 7 +break; +case 242:return 7 +break; +case 243:return 7 +break; +case 244:return 7 +break; +case 245:return 7 +break; +case 246:return 7 +break; +case 247:return 7 +break; +case 248:return 7 +break; +case 249:return 7 +break; +case 250:return 7 +break; +case 251:return 7 +break; +case 252:return 7 +break; +case 253:return 7 +break; +case 254:return 7 +break; +case 255:return 7 +break; +case 256:return 7 +break; +case 257:return 7 +break; +case 258:return 7 +break; +case 259:return 7 +break; +case 260:return 7 +break; +case 261:return 7 +break; +case 262:return 7 +break; +case 263:return 7 +break; +case 264:return 7 +break; +case 265:return 7 +break; +case 266:return 7 +break; +case 267:return 7 +break; +case 268:return 7 +break; +case 269:return 7 +break; +case 270:return 7 +break; +case 271:return 7 +break; +case 272:return 7 +break; +case 273:return 7 +break; +case 274:return 7 +break; +case 275:return 7 +break; +case 276:return 7 +break; +case 277:return 7 +break; +case 278:return 7 +break; +case 279:return 7 +break; +case 280:return 7 +break; +case 281:return 7 +break; +case 282:return 7 +break; +case 283:return 7 +break; +case 284:return 7 +break; +case 285:return 7 +break; +case 286:return 7 +break; +case 287:return 7 +break; +case 288:return 7 +break; +case 289:return 7 +break; +case 290:return 7 +break; +case 291:return 7 +break; +case 292:return 7 +break; +case 293:return 7 +break; +case 294:return 7 +break; +case 295:return 7 +break; +case 296:return 7 +break; +case 297:return 7 +break; +case 298:return 7 +break; +case 299:return 7 +break; +case 300:return 7 +break; +case 301:return 7 +break; +case 302:return 7 +break; +case 303:return 7 +break; +case 304:return 7 +break; +case 305:return 7 +break; +case 306:return 7 +break; +case 307:return 7 +break; +case 308:return 7 +break; +case 309:return 7 +break; +case 310:return 7 +break; +case 311:return 7 +break; +case 312:return 7 +break; +case 313:return 7 +break; +case 314:return 7 +break; +case 315:return 7 +break; +case 316:return 7 +break; +case 317:return 7 +break; +case 318:return 7 +break; +case 319:return 7 +break; +case 320:return 7 +break; +case 321:return 7 +break; +case 322:return 7 +break; +case 323:return 7 +break; +case 324:return 7 +break; +case 325:return 7 +break; +case 326:return 7 +break; +case 327:return 7 +break; +case 328:return 7 +break; +case 329:return 7 +break; +case 330:return 7 +break; +case 331:return 7 +break; +case 332:return 7 +break; +case 333:return 7 +break; +case 334:return 7 +break; +case 335:return 7 +break; +case 336:return 7 +break; +case 337:return 7 +break; +case 338:return 7 +break; +case 339:return 7 +break; +case 340:return 7 +break; +case 341:return 7 +break; +case 342:return 7 +break; +case 343:return 7 +break; +case 344:return 7 +break; +case 345:return 7 +break; +case 346:return 7 +break; +case 347:return 7 +break; +case 348:return 7 +break; +case 349:return 7 +break; +case 350:return 7 +break; +case 351:return 7 +break; +case 352:return 7 +break; +case 353:return 7 +break; +case 354:return 7 +break; +case 355:return 7 +break; +case 356:return 7 +break; +case 357:return 7 +break; +case 358:return 7 +break; +case 359:return 7 +break; +case 360:return 7 +break; +case 361:return 7 +break; +case 362:return 7 +break; +case 363:return 7 +break; +case 364:return 7 +break; } +}, +rules: [/^(?:$)/,/^(?:\s+)/,/^(?:\+)/,/^(?:\()/,/^(?:\))/,/^(?::)/,/^(?:DocumentRef-([0-9A-Za-z-+.]+))/,/^(?:LicenseRef-([0-9A-Za-z-+.]+))/,/^(?:AND)/,/^(?:OR)/,/^(?:WITH)/,/^(?:BSD-3-Clause-No-Nuclear-License-2014)/,/^(?:BSD-3-Clause-No-Nuclear-Warranty)/,/^(?:GPL-2\.0-with-classpath-exception)/,/^(?:GPL-3\.0-with-autoconf-exception)/,/^(?:GPL-2\.0-with-autoconf-exception)/,/^(?:BSD-3-Clause-No-Nuclear-License)/,/^(?:MPL-2\.0-no-copyleft-exception)/,/^(?:GPL-2\.0-with-bison-exception)/,/^(?:GPL-2\.0-with-font-exception)/,/^(?:GPL-2\.0-with-GCC-exception)/,/^(?:CNRI-Python-GPL-Compatible)/,/^(?:GPL-3\.0-with-GCC-exception)/,/^(?:BSD-3-Clause-Attribution)/,/^(?:Classpath-exception-2\.0)/,/^(?:WxWindows-exception-3\.1)/,/^(?:freertos-exception-2\.0)/,/^(?:Autoconf-exception-3\.0)/,/^(?:i2p-gpl-java-exception)/,/^(?:gnu-javamail-exception)/,/^(?:Nokia-Qt-exception-1\.1)/,/^(?:Autoconf-exception-2\.0)/,/^(?:BSD-2-Clause-FreeBSD)/,/^(?:u-boot-exception-2\.0)/,/^(?:zlib-acknowledgement)/,/^(?:Bison-exception-2\.2)/,/^(?:BSD-2-Clause-NetBSD)/,/^(?:CLISP-exception-2\.0)/,/^(?:eCos-exception-2\.0)/,/^(?:BSD-3-Clause-Clear)/,/^(?:Font-exception-2\.0)/,/^(?:FLTK-exception-2\.0)/,/^(?:GCC-exception-2\.0)/,/^(?:Qwt-exception-1\.0)/,/^(?:Libtool-exception)/,/^(?:BSD-3-Clause-LBNL)/,/^(?:GCC-exception-3\.1)/,/^(?:Artistic-1\.0-Perl)/,/^(?:Artistic-1\.0-cl8)/,/^(?:CC-BY-NC-SA-2\.5)/,/^(?:MIT-advertising)/,/^(?:BSD-Source-Code)/,/^(?:CC-BY-NC-SA-4\.0)/,/^(?:LiLiQ-Rplus-1\.1)/,/^(?:CC-BY-NC-SA-3\.0)/,/^(?:BSD-4-Clause-UC)/,/^(?:CC-BY-NC-SA-2\.0)/,/^(?:CC-BY-NC-SA-1\.0)/,/^(?:CC-BY-NC-ND-4\.0)/,/^(?:CC-BY-NC-ND-3\.0)/,/^(?:CC-BY-NC-ND-2\.5)/,/^(?:CC-BY-NC-ND-2\.0)/,/^(?:CC-BY-NC-ND-1\.0)/,/^(?:LZMA-exception)/,/^(?:BitTorrent-1\.1)/,/^(?:CrystalStacker)/,/^(?:FLTK-exception)/,/^(?:SugarCRM-1\.1\.3)/,/^(?:BSD-Protection)/,/^(?:BitTorrent-1\.0)/,/^(?:HaskellReport)/,/^(?:Interbase-1\.0)/,/^(?:StandardML-NJ)/,/^(?:mif-exception)/,/^(?:Frameworx-1\.0)/,/^(?:389-exception)/,/^(?:CC-BY-NC-2\.0)/,/^(?:CC-BY-NC-2\.5)/,/^(?:CC-BY-NC-3\.0)/,/^(?:CC-BY-NC-4\.0)/,/^(?:W3C-19980720)/,/^(?:CC-BY-SA-1\.0)/,/^(?:CC-BY-SA-2\.0)/,/^(?:CC-BY-SA-2\.5)/,/^(?:CC-BY-ND-2\.0)/,/^(?:CC-BY-SA-4\.0)/,/^(?:CC-BY-SA-3\.0)/,/^(?:Artistic-1\.0)/,/^(?:Artistic-2\.0)/,/^(?:CC-BY-ND-2\.5)/,/^(?:CC-BY-ND-3\.0)/,/^(?:CC-BY-ND-4\.0)/,/^(?:CC-BY-ND-1\.0)/,/^(?:BSD-4-Clause)/,/^(?:BSD-3-Clause)/,/^(?:BSD-2-Clause)/,/^(?:CC-BY-NC-1\.0)/,/^(?:bzip2-1\.0\.6)/,/^(?:Unicode-TOU)/,/^(?:CNRI-Jython)/,/^(?:ImageMagick)/,/^(?:Adobe-Glyph)/,/^(?:CUA-OPL-1\.0)/,/^(?:OLDAP-2\.2\.2)/,/^(?:LiLiQ-R-1\.1)/,/^(?:bzip2-1\.0\.5)/,/^(?:LiLiQ-P-1\.1)/,/^(?:OLDAP-2\.0\.1)/,/^(?:OLDAP-2\.2\.1)/,/^(?:CNRI-Python)/,/^(?:XFree86-1\.1)/,/^(?:OSET-PL-2\.1)/,/^(?:Apache-2\.0)/,/^(?:Watcom-1\.0)/,/^(?:PostgreSQL)/,/^(?:Python-2\.0)/,/^(?:RHeCos-1\.1)/,/^(?:EUDatagrid)/,/^(?:Spencer-99)/,/^(?:Intel-ACPI)/,/^(?:CECILL-1\.0)/,/^(?:CECILL-1\.1)/,/^(?:JasPer-2\.0)/,/^(?:CECILL-2\.0)/,/^(?:CECILL-2\.1)/,/^(?:gSOAP-1\.3b)/,/^(?:Spencer-94)/,/^(?:Apache-1\.1)/,/^(?:Spencer-86)/,/^(?:Apache-1\.0)/,/^(?:ClArtistic)/,/^(?:TORQUE-1\.1)/,/^(?:CATOSL-1\.1)/,/^(?:Adobe-2006)/,/^(?:Zimbra-1\.4)/,/^(?:Zimbra-1\.3)/,/^(?:Condor-1\.1)/,/^(?:CC-BY-3\.0)/,/^(?:CC-BY-2\.5)/,/^(?:OLDAP-2\.4)/,/^(?:SGI-B-1\.1)/,/^(?:SISSL-1\.2)/,/^(?:SGI-B-1\.0)/,/^(?:OLDAP-2\.3)/,/^(?:CC-BY-4\.0)/,/^(?:Crossword)/,/^(?:SimPL-2\.0)/,/^(?:OLDAP-2\.2)/,/^(?:OLDAP-2\.1)/,/^(?:ErlPL-1\.1)/,/^(?:LPPL-1\.3a)/,/^(?:LPPL-1\.3c)/,/^(?:OLDAP-2\.0)/,/^(?:Leptonica)/,/^(?:CPOL-1\.02)/,/^(?:OLDAP-1\.4)/,/^(?:OLDAP-1\.3)/,/^(?:CC-BY-2\.0)/,/^(?:Unlicense)/,/^(?:OLDAP-2\.8)/,/^(?:OLDAP-1\.2)/,/^(?:MakeIndex)/,/^(?:OLDAP-2\.7)/,/^(?:OLDAP-1\.1)/,/^(?:Sleepycat)/,/^(?:D-FSL-1\.0)/,/^(?:CC-BY-1\.0)/,/^(?:OLDAP-2\.6)/,/^(?:WXwindows)/,/^(?:NPOSL-3\.0)/,/^(?:FreeImage)/,/^(?:SGI-B-2\.0)/,/^(?:OLDAP-2\.5)/,/^(?:Beerware)/,/^(?:Newsletr)/,/^(?:NBPL-1\.0)/,/^(?:NASA-1\.3)/,/^(?:NLOD-1\.0)/,/^(?:AGPL-1\.0)/,/^(?:OCLC-2\.0)/,/^(?:ODbL-1\.0)/,/^(?:PDDL-1\.0)/,/^(?:Motosoto)/,/^(?:Afmparse)/,/^(?:ANTLR-PD)/,/^(?:LPL-1\.02)/,/^(?:Abstyles)/,/^(?:eCos-2\.0)/,/^(?:APSL-1\.0)/,/^(?:LPPL-1\.2)/,/^(?:LPPL-1\.1)/,/^(?:LPPL-1\.0)/,/^(?:APSL-1\.1)/,/^(?:APSL-2\.0)/,/^(?:Info-ZIP)/,/^(?:Zend-2\.0)/,/^(?:IBM-pibs)/,/^(?:LGPL-2\.0)/,/^(?:LGPL-3\.0)/,/^(?:LGPL-2\.1)/,/^(?:GFDL-1\.3)/,/^(?:PHP-3\.01)/,/^(?:GFDL-1\.2)/,/^(?:GFDL-1\.1)/,/^(?:AGPL-3\.0)/,/^(?:Giftware)/,/^(?:EUPL-1\.1)/,/^(?:RPSL-1\.0)/,/^(?:EUPL-1\.0)/,/^(?:MIT-enna)/,/^(?:CECILL-B)/,/^(?:diffmark)/,/^(?:CECILL-C)/,/^(?:CDDL-1\.0)/,/^(?:Sendmail)/,/^(?:CDDL-1\.1)/,/^(?:CPAL-1\.0)/,/^(?:APSL-1\.2)/,/^(?:NPL-1\.1)/,/^(?:AFL-1\.2)/,/^(?:Caldera)/,/^(?:AFL-2\.0)/,/^(?:FSFULLR)/,/^(?:AFL-2\.1)/,/^(?:VSL-1\.0)/,/^(?:VOSTROM)/,/^(?:UPL-1\.0)/,/^(?:Dotseqn)/,/^(?:CPL-1\.0)/,/^(?:dvipdfm)/,/^(?:EPL-1\.0)/,/^(?:OCCT-PL)/,/^(?:ECL-1\.0)/,/^(?:Latex2e)/,/^(?:ECL-2\.0)/,/^(?:GPL-1\.0)/,/^(?:GPL-2\.0)/,/^(?:GPL-3\.0)/,/^(?:AFL-3\.0)/,/^(?:LAL-1\.2)/,/^(?:LAL-1\.3)/,/^(?:EFL-1\.0)/,/^(?:EFL-2\.0)/,/^(?:gnuplot)/,/^(?:Aladdin)/,/^(?:LPL-1\.0)/,/^(?:libtiff)/,/^(?:Entessa)/,/^(?:AMDPLPA)/,/^(?:IPL-1\.0)/,/^(?:OPL-1\.0)/,/^(?:OSL-1\.0)/,/^(?:OSL-1\.1)/,/^(?:OSL-2\.0)/,/^(?:OSL-2\.1)/,/^(?:OSL-3\.0)/,/^(?:OpenSSL)/,/^(?:ZPL-2\.1)/,/^(?:PHP-3\.0)/,/^(?:ZPL-2\.0)/,/^(?:ZPL-1\.1)/,/^(?:CC0-1\.0)/,/^(?:SPL-1\.0)/,/^(?:psutils)/,/^(?:MPL-1\.0)/,/^(?:QPL-1\.0)/,/^(?:MPL-1\.1)/,/^(?:MPL-2\.0)/,/^(?:APL-1\.0)/,/^(?:RPL-1\.1)/,/^(?:RPL-1\.5)/,/^(?:MIT-CMU)/,/^(?:Multics)/,/^(?:Eurosym)/,/^(?:BSL-1\.0)/,/^(?:MIT-feh)/,/^(?:Saxpath)/,/^(?:Borceux)/,/^(?:OFL-1\.1)/,/^(?:OFL-1\.0)/,/^(?:AFL-1\.1)/,/^(?:YPL-1\.1)/,/^(?:YPL-1\.0)/,/^(?:NPL-1\.0)/,/^(?:iMatix)/,/^(?:mpich2)/,/^(?:APAFML)/,/^(?:Bahyph)/,/^(?:RSA-MD)/,/^(?:psfrag)/,/^(?:Plexus)/,/^(?:eGenix)/,/^(?:Glulxe)/,/^(?:SAX-PD)/,/^(?:Imlib2)/,/^(?:Wsuipa)/,/^(?:LGPLLR)/,/^(?:Libpng)/,/^(?:xinetd)/,/^(?:MITNFA)/,/^(?:NetCDF)/,/^(?:Naumen)/,/^(?:SMPPL)/,/^(?:Nunit)/,/^(?:FSFUL)/,/^(?:GL2PS)/,/^(?:SMLNJ)/,/^(?:Rdisc)/,/^(?:Noweb)/,/^(?:Nokia)/,/^(?:SISSL)/,/^(?:Qhull)/,/^(?:Intel)/,/^(?:Glide)/,/^(?:Xerox)/,/^(?:AMPAS)/,/^(?:WTFPL)/,/^(?:MS-PL)/,/^(?:XSkat)/,/^(?:MS-RL)/,/^(?:MirOS)/,/^(?:RSCPL)/,/^(?:TMate)/,/^(?:OGTSL)/,/^(?:FSFAP)/,/^(?:NCSA)/,/^(?:Zlib)/,/^(?:SCEA)/,/^(?:SNIA)/,/^(?:NGPL)/,/^(?:NOSL)/,/^(?:ADSL)/,/^(?:MTLL)/,/^(?:NLPL)/,/^(?:Ruby)/,/^(?:JSON)/,/^(?:Barr)/,/^(?:0BSD)/,/^(?:Xnet)/,/^(?:Cube)/,/^(?:curl)/,/^(?:DSDP)/,/^(?:Fair)/,/^(?:HPND)/,/^(?:TOSL)/,/^(?:IJG)/,/^(?:SWL)/,/^(?:Vim)/,/^(?:FTL)/,/^(?:ICU)/,/^(?:OML)/,/^(?:NRL)/,/^(?:DOC)/,/^(?:TCL)/,/^(?:W3C)/,/^(?:NTP)/,/^(?:IPA)/,/^(?:ISC)/,/^(?:X11)/,/^(?:AAL)/,/^(?:AML)/,/^(?:xpp)/,/^(?:Zed)/,/^(?:MIT)/,/^(?:Mup)/], +conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364],"inclusive":true}} +}); +return lexer; +})(); +parser.lexer = lexer; +function Parser () { + this.yy = {}; +} +Parser.prototype = parser;parser.Parser = Parser; +return new Parser; +})(); -// Common transpositions of license identifier acronyms -var transpositions = [ - ['APGL', 'AGPL'], - ['Gpl', 'GPL'], - ['GLP', 'GPL'], - ['APL', 'Apache'], - ['ISD', 'ISC'], - ['GLP', 'GPL'], - ['IST', 'ISC'], - ['Claude', 'Clause'], - [' or later', '+'], - [' International', ''], - ['GNU', 'GPL'], - ['GUN', 'GPL'], - ['+', ''], - ['GNU GPL', 'GPL'], - ['GNU/GPL', 'GPL'], - ['GNU GLP', 'GPL'], - ['GNU General Public License', 'GPL'], - ['Gnu public license', 'GPL'], - ['GNU Public License', 'GPL'], - ['GNU GENERAL PUBLIC LICENSE', 'GPL'], - ['MTI', 'MIT'], - ['Mozilla Public License', 'MPL'], - ['WTH', 'WTF'], - ['-License', ''] -]; - -var TRANSPOSED = 0; -var CORRECT = 1; - -// Simple corrections to nearly valid identifiers. -var transforms = [ - // e.g. 'mit' - function(argument) { - return argument.toUpperCase(); - }, - // e.g. 'MIT ' - function(argument) { - return argument.trim(); - }, - // e.g. 'M.I.T.' - function(argument) { - return argument.replace(/\./g, ''); - }, - // e.g. 'Apache- 2.0' - function(argument) { - return argument.replace(/\s+/g, ''); - }, - // e.g. 'CC BY 4.0'' - function(argument) { - return argument.replace(/\s+/g, '-'); - }, - // e.g. 'LGPLv2.1' - function(argument) { - return argument.replace('v', '-'); - }, - // e.g. 'Apache 2.0' - function(argument) { - return argument.replace(/,?\s*(\d)/, '-$1'); - }, - // e.g. 'GPL 2' - function(argument) { - return argument.replace(/,?\s*(\d)/, '-$1.0'); - }, - // e.g. 'Apache Version 2.0' - function(argument) { - return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2'); - }, - // e.g. 'Apache Version 2' - function(argument) { - return argument.replace(/,?\s*(V\.|v\.|V|v|Version|version)\s*(\d)/, '-$2.0'); - }, - // e.g. 'ZLIB' - function(argument) { - return argument[0].toUpperCase() + argument.slice(1); - }, - // e.g. 'MPL/2.0' - function(argument) { - return argument.replace('/', '-'); - }, - // e.g. 'Apache 2' - function(argument) { - return argument - .replace(/\s*V\s*(\d)/, '-$1') - .replace(/(\d)$/, '$1.0'); - }, - // e.g. 'GPL-2.0-' - function(argument) { - return argument.slice(0, argument.length - 1); - }, - // e.g. 'GPL2' - function(argument) { - return argument.replace(/(\d)$/, '-$1.0'); - }, - // e.g. 'BSD 3' - function(argument) { - return argument.replace(/(-| )?(\d)$/, '-$2-Clause'); - }, - // e.g. 'BSD clause 3' - function(argument) { - return argument.replace(/(-| )clause(-| )(\d)/, '-$3-Clause'); - }, - // e.g. 'BY-NC-4.0' - function(argument) { - return 'CC-' + argument; - }, - // e.g. 'BY-NC' - function(argument) { - return 'CC-' + argument + '-4.0'; - }, - // e.g. 'Attribution-NonCommercial' - function(argument) { - return argument - .replace('Attribution', 'BY') - .replace('NonCommercial', 'NC') - .replace('NoDerivatives', 'ND') - .replace(/ (\d)/, '-$1') - .replace(/ ?International/, ''); - }, - // e.g. 'Attribution-NonCommercial' - function(argument) { - return 'CC-' + - argument - .replace('Attribution', 'BY') - .replace('NonCommercial', 'NC') - .replace('NoDerivatives', 'ND') - .replace(/ (\d)/, '-$1') - .replace(/ ?International/, '') + - '-4.0'; - } -]; - -// If all else fails, guess that strings containing certain substrings -// meant to identify certain licenses. -var lastResorts = [ - ['UNLI', 'Unlicense'], - ['WTF', 'WTFPL'], - ['2 CLAUSE', 'BSD-2-Clause'], - ['2-CLAUSE', 'BSD-2-Clause'], - ['3 CLAUSE', 'BSD-3-Clause'], - ['3-CLAUSE', 'BSD-3-Clause'], - ['AFFERO', 'AGPL-3.0'], - ['AGPL', 'AGPL-3.0'], - ['APACHE', 'Apache-2.0'], - ['ARTISTIC', 'Artistic-2.0'], - ['Affero', 'AGPL-3.0'], - ['BEER', 'Beerware'], - ['BOOST', 'BSL-1.0'], - ['BSD', 'BSD-2-Clause'], - ['ECLIPSE', 'EPL-1.0'], - ['FUCK', 'WTFPL'], - ['GNU', 'GPL-3.0'], - ['LGPL', 'LGPL-3.0'], - ['GPL', 'GPL-3.0'], - ['MIT', 'MIT'], - ['MPL', 'MPL-2.0'], - ['X11', 'X11'], - ['ZLIB', 'Zlib'] -]; - -var SUBSTRING = 0; -var IDENTIFIER = 1; -var validTransformation = function(identifier) { - for (var i = 0; i < transforms.length; i++) { - var transformed = transforms[i](identifier); - if (transformed !== identifier && valid(transformed)) { - return transformed; +if (true) { +exports.parser = spdxparse; +exports.Parser = spdxparse.Parser; +exports.parse = function () { return spdxparse.parse.apply(spdxparse, arguments); }; +exports.main = function commonjsMain(args) { + if (!args[1]) { + console.log('Usage: '+args[0]+' FILE'); + process.exit(1); } - } - return null; + var source = __webpack_require__("fs").readFileSync(__webpack_require__("path").normalize(args[1]), "utf8"); + return exports.parser.parse(source); }; +if ( true && __webpack_require__.c[__webpack_require__.s] === module) { + exports.main(process.argv.slice(1)); +} +} -var validLastResort = function(identifier) { - var upperCased = identifier.toUpperCase(); - for (var i = 0; i < lastResorts.length; i++) { - var lastResort = lastResorts[i]; - if (upperCased.indexOf(lastResort[SUBSTRING]) > -1) { - return lastResort[IDENTIFIER]; - } - } - return null; -}; +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__("../../node_modules/webpack/buildin/module.js")(module))) -var anyCorrection = function(identifier, check) { - for (var i = 0; i < transpositions.length; i++) { - var transposition = transpositions[i]; - var transposed = transposition[TRANSPOSED]; - if (identifier.indexOf(transposed) > -1) { - var corrected = identifier.replace( - transposed, - transposition[CORRECT] - ); - var checked = check(corrected); - if (checked !== null) { - return checked; - } - } - } - return null; -}; +/***/ }), -module.exports = function(identifier) { - identifier = identifier.replace(/\+$/, ''); - if (valid(identifier)) { - return identifier; - } - var transformed = validTransformation(identifier); - if (transformed !== null) { - return transformed; - } - transformed = anyCorrection(identifier, function(argument) { - if (valid(argument)) { - return argument; - } - return validTransformation(argument); - }); - if (transformed !== null) { - return transformed; - } - transformed = validLastResort(identifier); - if (transformed !== null) { - return transformed; - } - transformed = anyCorrection(identifier, validLastResort); - if (transformed !== null) { - return transformed; - } - return null; -}; +/***/ "../../node_modules/validate-npm-package-license/node_modules/spdx-license-ids/spdx-license-ids.json": +/***/ (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\"]"); /***/ }), diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index 834a30ef214c7..175b9c50d4d27 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -21,6 +21,7 @@ export const LICENSE_ALLOWED = [ '(MIT AND Zlib)', '(MIT OR Apache-2.0)', '(MIT OR GPL-3.0)', + '(MIT OR GPL-3.0-or-later)', '(WTFPL OR MIT)', '(MIT OR WTFPL)', '(Unlicense OR Apache-2.0)', diff --git a/yarn.lock b/yarn.lock index 4297c9ea9ed74..2674fca4a5099 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8711,11 +8711,6 @@ ansi-html@0.0.7: resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= -ansi-regex@^0.2.0, ansi-regex@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" - integrity sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk= - ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -8736,11 +8731,6 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" - integrity sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94= - ansi-styles@^2.0.1, ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -9038,6 +9028,11 @@ array-filter@^1.0.0: resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= +array-find-index@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + array-flat-polyfill@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-flat-polyfill/-/array-flat-polyfill-1.0.1.tgz#1e3a4255be619dfbffbfd1d635c1cf357cd034e7" @@ -10718,17 +10713,6 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" - integrity sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ= - dependencies: - ansi-styles "^1.1.0" - escape-string-regexp "^1.0.0" - has-ansi "^0.1.0" - strip-ansi "^0.3.0" - supports-color "^0.2.0" - chance@1.0.18: version "1.0.18" resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.18.tgz#79788fe6fca4c338bf404321c347eecc80f969ee" @@ -14110,7 +14094,7 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -16436,13 +16420,6 @@ hard-rejection@^2.1.0: resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== -has-ansi@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" - integrity sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4= - dependencies: - ansi-regex "^0.2.0" - has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -19622,21 +19599,21 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -license-checker@^16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/license-checker/-/license-checker-16.0.0.tgz#4e1263e5314b4519f8c3a5fe2fe4f38bc645a87d" - integrity sha512-TAZDfuhEM1oZcBXICOeTBMt+bXIHllvoKHZA658YgPLzcnT45MS2Tjqqwkd5ctkHOlKJ8fTdl5dft2YTCe/4LQ== +license-checker@^25.0.1: + version "25.0.1" + resolved "https://registry.yarnpkg.com/license-checker/-/license-checker-25.0.1.tgz#4d14504478a5240a857bb3c21cd0491a00d761fa" + integrity sha512-mET5AIwl7MR2IAKYYoVBBpV0OnkKQ1xGj2IMMeEFIs42QAkEVjRtFZGWmQ28WeU7MP779iAgOaOy93Mn44mn6g== dependencies: - chalk "~0.5.1" - debug "^2.2.0" - mkdirp "^0.3.5" - nopt "^2.2.0" + chalk "^2.4.1" + debug "^3.1.0" + mkdirp "^0.5.1" + nopt "^4.0.1" read-installed "~4.0.3" - semver "^5.3.0" - spdx "^0.5.1" - spdx-correct "^2.0.3" - spdx-satisfies "^0.1.3" - treeify "^1.0.1" + semver "^5.5.0" + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + spdx-satisfies "^4.0.0" + treeify "^1.1.0" lie@~3.3.0: version "3.3.0" @@ -20925,11 +20902,6 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" - integrity sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc= - mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" @@ -21601,12 +21573,13 @@ nodemon@^2.0.4: undefsafe "^2.0.5" update-notifier "^5.1.0" -nopt@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-2.2.1.tgz#2aa09b7d1768487b3b89a9c5aa52335bff0baea7" - integrity sha1-KqCbfRdoSHs7ianFqlIzW/8Lrqc= +nopt@^4.0.1, nopt@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== dependencies: abbrev "1" + osenv "^0.1.4" nopt@^5.0.0: version "5.0.0" @@ -21622,14 +21595,6 @@ nopt@~1.0.10: dependencies: abbrev "1" -nopt@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" - integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -26229,7 +26194,7 @@ semver-greatest-satisfied-range@^1.1.0: dependencies: sver-compat "^1.5.0" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -26880,21 +26845,22 @@ spawn-wrap@^2.0.0: signal-exit "^3.0.2" which "^2.0.1" -spdx-compare@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/spdx-compare/-/spdx-compare-0.1.2.tgz#b06af3ea34af7437d91a9f449eaf2d2e93c3c8fb" - integrity sha1-sGrz6jSvdDfZGp9Enq8tLpPDyPs= +spdx-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/spdx-compare/-/spdx-compare-1.0.0.tgz#2c55f117362078d7409e6d7b08ce70a857cd3ed7" + integrity sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A== dependencies: - spdx-expression-parse "^1.0.0" - spdx-ranges "^1.0.0" + array-find-index "^1.0.2" + spdx-expression-parse "^3.0.0" + spdx-ranges "^2.0.0" -spdx-correct@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-2.0.4.tgz#d1652ad2ebc516f656f66ea93398558065f1b4a4" - integrity sha512-c+4gPpt9YDhz7cHlz5UrsHzxxRi4ksclxnEEKsuGT9JdwSC+ZNmsGbYRzzgxyZaBYpcWnlu+4lPcdLKx4DOCmA== +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: - spdx-expression-parse "^2.0.1" - spdx-license-ids "^2.0.1" + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" spdx-correct@~1.0.0: version "1.0.2" @@ -26903,59 +26869,47 @@ spdx-correct@~1.0.0: dependencies: spdx-license-ids "^1.0.2" -spdx-exceptions@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-1.0.5.tgz#9d21ac4da4bdb71d060fb74e5a67531d032cbba6" - integrity sha1-nSGsTaS9tx0GD7dOWmdTHQMsu6Y= +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== -spdx-exceptions@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" - integrity sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg== +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" -spdx-expression-parse@^1.0.0, spdx-expression-parse@~1.0.0: +spdx-expression-parse@~1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" integrity sha1-m98vIOH0DtRH++JzJmGR/O1RYmw= -spdx-expression-parse@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-2.0.2.tgz#e2e0f229c057eac704c5a6d1c687eed66aca034b" - integrity sha512-oFxOkWCfFS0ltNp0H66gXlU4NF6bxg7RkoTYR0413t+yTY9zyj+AIWsjtN8dcVp6703ijDYBWBIARlJ7DkyP9Q== - dependencies: - spdx-exceptions "^2.0.0" - spdx-license-ids "^2.0.1" - -spdx-license-ids@^1.0.0, spdx-license-ids@^1.0.2: +spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" integrity sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc= -spdx-license-ids@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-2.0.1.tgz#02017bcc3534ee4ffef6d58d20e7d3e9a1c3c8ec" - integrity sha1-AgF7zDU07k/+9tWNIOfT6aHDyOw= - -spdx-ranges@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/spdx-ranges/-/spdx-ranges-1.0.1.tgz#0f4eec7b8ea48ed202e374bb8942e8d18dc0113e" - integrity sha1-D07se46kjtIC43S7iULo0Y3AET4= +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== -spdx-satisfies@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/spdx-satisfies/-/spdx-satisfies-0.1.3.tgz#67a1f274e6115d4aae28afe474db76164be10bdc" - integrity sha1-Z6HydOYRXUquKK/kdNt2FkvhC9w= - dependencies: - spdx-compare "^0.1.2" - spdx-expression-parse "^1.0.0" +spdx-ranges@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/spdx-ranges/-/spdx-ranges-2.1.1.tgz#87573927ba51e92b3f4550ab60bfc83dd07bac20" + integrity sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA== -spdx@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/spdx/-/spdx-0.5.1.tgz#d36c275088b48d75a9046cd44a838ce4b5339998" - integrity sha1-02wnUIi0jXWpBGzUSoOM5LUzmZg= +spdx-satisfies@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/spdx-satisfies/-/spdx-satisfies-4.0.1.tgz#9a09a68d80f5f1a31cfaebb384b0c6009e4969fe" + integrity sha512-WVzZ/cXAzoNmjCWiEluEA3BjHp5tiUmmhn9MK+X0tBbR9sOqtC6UQwmgCNrAIZvNlMuBUYAaHYfb2oqlF9SwKA== dependencies: - spdx-exceptions "^1.0.0" - spdx-license-ids "^1.0.0" + spdx-compare "^1.0.0" + spdx-expression-parse "^3.0.0" + spdx-ranges "^2.0.0" spdy-transport@^3.0.0: version "3.0.0" @@ -27451,13 +27405,6 @@ strip-ansi@*, strip-ansi@5.2.0, strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi dependencies: ansi-regex "^4.1.0" -strip-ansi@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.3.0.tgz#25f48ea22ca79187f3174a4db8759347bb126220" - integrity sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA= - dependencies: - ansi-regex "^0.2.1" - strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -27747,11 +27694,6 @@ supports-color@8.1.1, supports-color@^8.1.1: dependencies: has-flag "^4.0.0" -supports-color@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" - integrity sha1-2S3iaU6z9nMjlz1649i1W0wiGQo= - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -28437,7 +28379,7 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== -treeify@^1.0.1, treeify@^1.1.0: +treeify@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== From 5d85008aa9558b7fd9ed897c954b475b1dcbcddc Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 5 Jul 2022 14:39:20 -0500 Subject: [PATCH 10/81] Bump prettier to 2.7.1 (#135143) * Bump prettier to 2.7.1 * bump eslint-config-prettier * update .eslintrc --- .eslintrc.js | 6 +----- package.json | 4 ++-- packages/kbn-eslint-config/typescript.js | 4 ++-- yarn.lock | 16 ++++++++-------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 6a8b460c79e41..2ebea652f797f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1774,11 +1774,7 @@ module.exports = { */ { files: ['**/*'], - rules: { - ...require('eslint-config-prettier').rules, - ...require('eslint-config-prettier/react').rules, - ...require('eslint-config-prettier/@typescript-eslint').rules, - }, + rules: require('eslint-config-prettier').rules, }, /** * Enterprise Search Prettier override diff --git a/package.json b/package.json index a7411852a1382..b1ff372ff0699 100644 --- a/package.json +++ b/package.json @@ -966,7 +966,7 @@ "enzyme-adapter-utils": "^1.14.0", "enzyme-to-json": "^3.6.1", "eslint": "^7.32.0", - "eslint-config-prettier": "^7.2.0", + "eslint-config-prettier": "^8.5.0", "eslint-module-utils": "^2.6.2", "eslint-plugin-ban": "^1.5.2", "eslint-plugin-cypress": "^2.12.1", @@ -1056,7 +1056,7 @@ "postcss": "^7.0.32", "postcss-loader": "^3.0.0", "postcss-prefix-selector": "^1.7.2", - "prettier": "^2.6.2", + "prettier": "^2.7.1", "pretty-format": "^27.5.1", "q": "^1.5.1", "raw-loader": "^3.1.0", diff --git a/packages/kbn-eslint-config/typescript.js b/packages/kbn-eslint-config/typescript.js index 8851e78cd9e02..777b02a4cf618 100644 --- a/packages/kbn-eslint-config/typescript.js +++ b/packages/kbn-eslint-config/typescript.js @@ -6,7 +6,7 @@ const semver = require('semver'); const { kibanaPackageJson: PKG } = require('@kbn/utils'); -const eslintConfigPrettierTypescriptEslintRules = require('eslint-config-prettier/@typescript-eslint').rules; +const eslintConfigPrettierRules = require('eslint-config-prettier').rules; // The current implementation excluded all the variables matching the regexp. // We should remove it as soon as multiple underscores are supported by the linter. @@ -259,7 +259,7 @@ module.exports = { 'eslint-comments/no-unused-disable': 'error', 'eslint-comments/no-unused-enable': 'error' }, - eslintConfigPrettierTypescriptEslintRules + eslintConfigPrettierRules ) }, ] diff --git a/yarn.lock b/yarn.lock index 2674fca4a5099..f9a5118594c4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14139,10 +14139,10 @@ escodegen@~1.2.0: optionalDependencies: source-map "~0.1.30" -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-config-prettier@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== eslint-formatter-pretty@^4.1.0: version "4.1.0" @@ -23515,10 +23515,10 @@ prettier-linter-helpers@^1.0.0: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== -prettier@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" - integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== +prettier@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== pretty-bytes@^5.6.0: version "5.6.0" From b8dcdeab8d9a3a8ee10f2288b4db17dafc149e82 Mon Sep 17 00:00:00 2001 From: Cristina Amico Date: Tue, 5 Jul 2022 21:59:54 +0200 Subject: [PATCH 11/81] [Fleet] Fix syncing issue in Agent flyout (#135734) * [Fleet] Fix syncing issue in Agent flyout * Use context based solution instead of polling * Add clarifying comment * Fix types Co-authored-by: Kyle Pollich --- .../hooks/use_wait_for_fleet_server.ts | 23 +++++++++---------- .../steps/confirm_fleet_server_connection.tsx | 10 ++++++-- .../fleet/sections/agents/index.test.tsx | 8 +++++++ .../fleet/sections/agents/index.tsx | 7 ++++-- .../fleet/public/hooks/use_fleet_status.tsx | 13 ++++++++++- 5 files changed, 44 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_wait_for_fleet_server.ts b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_wait_for_fleet_server.ts index 4da59560e408e..7721025a75067 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_wait_for_fleet_server.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_wait_for_fleet_server.ts @@ -6,9 +6,9 @@ */ import { i18n } from '@kbn/i18n'; -import { useEffect, useState } from 'react'; +import { useEffect } from 'react'; -import { sendGetFleetStatus, useStartServices } from '../../../hooks'; +import { useFleetStatus, useStartServices } from '../../../hooks'; const REFRESH_INTERVAL = 10000; @@ -17,26 +17,25 @@ const REFRESH_INTERVAL = 10000; * in the `missing_requirements` list. */ export const useWaitForFleetServer = () => { - const [isFleetServerReady, setIsFleetServerReady] = useState(false); + const fleetStatus = useFleetStatus(); const { notifications } = useStartServices(); + const isFleetServerReady = + fleetStatus.isReady && !fleetStatus.missingRequirements?.includes('fleet_server'); + useEffect(() => { let interval: ReturnType | null = null; if (!isFleetServerReady) { interval = setInterval(async () => { try { - const res = await sendGetFleetStatus(); - - if (res.error) { - throw res.error; - } - if (res.data?.isReady && !res.data?.missing_requirements?.includes('fleet_server')) { - setIsFleetServerReady(true); - + if (isFleetServerReady) { if (interval) { clearInterval(interval); } + } else { + fleetStatus.setForceDisplayInstructions(true); + fleetStatus.refresh(); } } catch (err) { notifications.toasts.addError(err, { @@ -55,7 +54,7 @@ export const useWaitForFleetServer = () => { }; return cleanup; - }, [notifications.toasts, isFleetServerReady]); + }, [notifications.toasts, isFleetServerReady, fleetStatus]); return { isFleetServerReady }; }; diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/steps/confirm_fleet_server_connection.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/steps/confirm_fleet_server_connection.tsx index 15e8609191019..8111fd3f09ac6 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/steps/confirm_fleet_server_connection.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/steps/confirm_fleet_server_connection.tsx @@ -13,7 +13,7 @@ import { EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { useFlyoutContext } from '../../../hooks'; +import { useFleetStatus, useFlyoutContext } from '../../../hooks'; export function getConfirmFleetServerConnectionStep({ disabled, @@ -41,6 +41,12 @@ const ConfirmFleetServerConnectionStepContent: React.FunctionComponent<{ isFleetServerReady: boolean; }> = ({ isFleetServerReady }) => { const flyoutContext = useFlyoutContext(); + const fleetStatus = useFleetStatus(); + + const handleContinueClick = () => { + fleetStatus.forceDisplayInstructions = false; + flyoutContext.openEnrollmentFlyout(); + }; return isFleetServerReady ? ( <> @@ -53,7 +59,7 @@ const ConfirmFleetServerConnectionStepContent: React.FunctionComponent<{ - + { enabled: true, isReady: false, refresh: async () => {}, + forceDisplayInstructions: false, + setForceDisplayInstructions: () => {}, }); const { utils } = renderAgentsApp(); @@ -82,6 +84,8 @@ describe('AgentApp', () => { isReady: false, missingRequirements: ['api_keys'], refresh: async () => {}, + forceDisplayInstructions: false, + setForceDisplayInstructions: () => {}, }); const { utils } = renderAgentsApp(); expect(utils.queryByText('MissingESRequirementsPage')).not.toBeNull(); @@ -95,6 +99,8 @@ describe('AgentApp', () => { isReady: false, missingRequirements: ['fleet_server'], refresh: async () => {}, + forceDisplayInstructions: false, + setForceDisplayInstructions: () => {}, }); const { utils } = renderAgentsApp(); expect(utils.queryByText('FleetServerRequirementPage')).not.toBeNull(); @@ -109,6 +115,8 @@ describe('AgentApp', () => { missingRequirements: [], missingOptionalFeatures: ['encrypted_saved_object_encryption_key_required'], refresh: async () => {}, + forceDisplayInstructions: false, + setForceDisplayInstructions: () => {}, }); const { utils } = renderAgentsApp(); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx index 78ceb6293d3ce..ed770311ad9e9 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/index.tsx @@ -75,6 +75,9 @@ export const AgentsApp: React.FunctionComponent = () => { fleetStatus?.missingRequirements?.length === 1 && fleetStatus.missingRequirements[0] === 'fleet_server'; + const displayInstructions = + fleetStatus.forceDisplayInstructions || hasOnlyFleetServerMissingRequirement; + if ( !hasOnlyFleetServerMissingRequirement && fleetStatus.missingRequirements && @@ -86,7 +89,7 @@ export const AgentsApp: React.FunctionComponent = () => { return ; } - const rightColumn = hasOnlyFleetServerMissingRequirement ? ( + const rightColumn = displayInstructions ? ( <> @@ -114,7 +117,7 @@ export const AgentsApp: React.FunctionComponent = () => { {fleetServerModalVisible && ( )} - {hasOnlyFleetServerMissingRequirement ? ( + {displayInstructions ? ( ) : ( diff --git a/x-pack/plugins/fleet/public/hooks/use_fleet_status.tsx b/x-pack/plugins/fleet/public/hooks/use_fleet_status.tsx index b05df0c619e0a..7319cd9f07be7 100644 --- a/x-pack/plugins/fleet/public/hooks/use_fleet_status.tsx +++ b/x-pack/plugins/fleet/public/hooks/use_fleet_status.tsx @@ -23,17 +23,26 @@ interface FleetStatusState { interface FleetStatus extends FleetStatusState { refresh: () => Promise; + + // This flag allows us to opt into displaying the Fleet Server enrollment instructions even if + // a healthy Fleet Server has been detected, so we can delay removing the enrollment UI until + // some user action like clicking a "continue" button + forceDisplayInstructions: boolean; + setForceDisplayInstructions: React.Dispatch; } const FleetStatusContext = React.createContext(undefined); export const FleetStatusProvider: React.FC = ({ children }) => { const config = useConfig(); + const [forceDisplayInstructions, setForceDisplayInstructions] = useState(false); + const [state, setState] = useState({ enabled: config.agents.enabled, isLoading: false, isReady: false, }); + const sendGetStatus = useCallback( async function sendGetStatus() { try { @@ -64,7 +73,9 @@ export const FleetStatusProvider: React.FC = ({ children }) => { const refresh = useCallback(() => sendGetStatus(), [sendGetStatus]); return ( - + {children} ); From 575aed237b45dbe44b68fb1b3e4dede3e9f91ceb Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Tue, 5 Jul 2022 16:55:46 -0400 Subject: [PATCH 12/81] Add separate buttons for add agent/add fleet server (#135747) --- .../components/search_and_filter_bar.tsx | 40 +++++++++++++++---- .../sections/agents/agent_list_page/index.tsx | 1 + .../hooks/use_agent_enrollment_flyout_data.ts | 3 +- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx index 18f7ed8c27905..7df607937cdc9 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/search_and_filter_bar.tsx @@ -89,6 +89,7 @@ export const SearchAndFilterBar: React.FunctionComponent<{ selectedAgents: Agent[]; refreshAgents: (args?: { refreshTags?: boolean }) => void; onClickAddAgent: () => void; + onClickAddFleetServer: () => void; visibleAgents: Agent[]; }> = ({ agentPolicies, @@ -111,6 +112,7 @@ export const SearchAndFilterBar: React.FunctionComponent<{ selectedAgents, refreshAgents, onClickAddAgent, + onClickAddFleetServer, visibleAgents, }) => { // Policies state for filtering @@ -322,14 +324,38 @@ export const SearchAndFilterBar: React.FunctionComponent<{ - onClickAddAgent()} - data-test-subj="addAgentButton" + + } > - - + + + + + + + + } + > + + + + = () => { Promise.all([fetchData({ refreshTags }), refreshUpgrades()]) } onClickAddAgent={() => setEnrollmentFlyoutState({ isOpen: true })} + onClickAddFleetServer={onClickAddFleetServer} visibleAgents={agents} /> diff --git a/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout_data.ts b/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout_data.ts index 062d0cee5e886..9e2dc6351ed99 100644 --- a/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout_data.ts +++ b/x-pack/plugins/fleet/public/hooks/use_agent_enrollment_flyout_data.ts @@ -9,6 +9,7 @@ import { useMemo } from 'react'; import type { AgentPolicy } from '../types'; import { SO_SEARCH_LIMIT } from '../constants'; +import { policyHasFleetServer } from '../services'; import { useGetAgentPolicies } from './use_request'; @@ -33,7 +34,7 @@ export function useAgentEnrollmentFlyoutData(): AgentEnrollmentFlyoutData { const agentPolicies = useMemo(() => { if (!isLoadingAgentPolicies) { - return agentPoliciesData?.items ?? []; + return (agentPoliciesData?.items ?? []).filter((policy) => !policyHasFleetServer(policy)); } return []; }, [isLoadingAgentPolicies, agentPoliciesData?.items]); From 6a738e317522de71ccacb75be5c79a9e28f13d3e Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Tue, 5 Jul 2022 18:06:09 -0400 Subject: [PATCH 13/81] [Response Ops] Conditionally run background tasks based on `node.roles` configuration (#134388) * Initial commit to optionally disable task polling * Stops polling when flag is false. Removes runtime from health API. Updates health check to not use runtime when not polling * Fixing types * Updating tests * Updating task manager plugin start to use node roles and added tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/calculate_health_status.ts | 10 +- .../server/lib/log_health_metrics.test.ts | 68 ++++-- .../server/lib/log_health_metrics.ts | 14 +- .../task_manager/server/monitoring/index.ts | 12 +- .../monitoring/monitoring_stats_stream.ts | 15 +- .../task_manager/server/plugin.test.ts | 199 +++++++++--------- x-pack/plugins/task_manager/server/plugin.ts | 63 +++--- .../task_manager/server/routes/health.test.ts | 10 + .../task_manager/server/routes/health.ts | 6 +- .../server/task_scheduling.test.ts | 25 ++- .../task_manager/server/task_scheduling.ts | 133 ++++++------ 11 files changed, 331 insertions(+), 224 deletions(-) diff --git a/x-pack/plugins/task_manager/server/lib/calculate_health_status.ts b/x-pack/plugins/task_manager/server/lib/calculate_health_status.ts index 0b5e046743627..8bd7f5de80810 100644 --- a/x-pack/plugins/task_manager/server/lib/calculate_health_status.ts +++ b/x-pack/plugins/task_manager/server/lib/calculate_health_status.ts @@ -14,6 +14,7 @@ import { TaskManagerConfig } from '../config'; export function calculateHealthStatus( summarizedStats: RawMonitoringStats, config: TaskManagerConfig, + shouldRunTasks: boolean, logger: Logger ): HealthStatus { const now = Date.now(); @@ -30,9 +31,12 @@ export function calculateHealthStatus( return HealthStatus.Error; } - if (hasExpiredHotTimestamps(summarizedStats, now, requiredHotStatsFreshness)) { - logger.debug('setting HealthStatus.Error because of expired hot timestamps'); - return HealthStatus.Error; + // Hot timestamps look at runtime stats which are not available when tasks are not running + if (shouldRunTasks) { + if (hasExpiredHotTimestamps(summarizedStats, now, requiredHotStatsFreshness)) { + logger.debug('setting HealthStatus.Error because of expired hot timestamps'); + return HealthStatus.Error; + } } if (hasExpiredColdTimestamps(summarizedStats, now, requiredColdStatsFreshness)) { diff --git a/x-pack/plugins/task_manager/server/lib/log_health_metrics.test.ts b/x-pack/plugins/task_manager/server/lib/log_health_metrics.test.ts index 9b1b10127abe2..08c93f12ecad8 100644 --- a/x-pack/plugins/task_manager/server/lib/log_health_metrics.test.ts +++ b/x-pack/plugins/task_manager/server/lib/log_health_metrics.test.ts @@ -39,16 +39,16 @@ describe('logHealthMetrics', () => { // We must change from OK to Warning (calculateHealthStatus as jest.Mock).mockImplementation(() => HealthStatus.OK); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); (calculateHealthStatus as jest.Mock).mockImplementation( () => HealthStatus.Warning ); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); // We must change from OK to Error (calculateHealthStatus as jest.Mock).mockImplementation(() => HealthStatus.OK); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); (calculateHealthStatus as jest.Mock).mockImplementation(() => HealthStatus.Error); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); const debugCalls = (logger as jest.Mocked).debug.mock.calls; const performanceMessage = /^Task Manager detected a degradation in performance/; @@ -76,9 +76,9 @@ describe('logHealthMetrics', () => { (calculateHealthStatus as jest.Mock).mockImplementation( () => HealthStatus.Warning ); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); (calculateHealthStatus as jest.Mock).mockImplementation(() => HealthStatus.OK); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); expect((logger as jest.Mocked).warn).not.toHaveBeenCalled(); }); @@ -96,9 +96,9 @@ describe('logHealthMetrics', () => { // We must change from Error to OK (calculateHealthStatus as jest.Mock).mockImplementation(() => HealthStatus.Error); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); (calculateHealthStatus as jest.Mock).mockImplementation(() => HealthStatus.OK); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); expect((logger as jest.Mocked).warn).not.toHaveBeenCalled(); }); @@ -112,7 +112,7 @@ describe('logHealthMetrics', () => { }); const health = getMockMonitoredHealth(); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); const firstDebug = JSON.parse( (logger as jest.Mocked).debug.mock.calls[0][0].replace('Latest Monitored Stats: ', '') @@ -130,7 +130,7 @@ describe('logHealthMetrics', () => { }); const health = getMockMonitoredHealth(); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); const firstDebug = JSON.parse( (logger as jest.Mocked).debug.mock.calls[0][0].replace('Latest Monitored Stats: ', '') @@ -152,7 +152,7 @@ describe('logHealthMetrics', () => { () => HealthStatus.Warning ); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); const logMessage = JSON.parse( ((logger as jest.Mocked).warn.mock.calls[0][0] as string).replace( @@ -175,7 +175,7 @@ describe('logHealthMetrics', () => { const { calculateHealthStatus } = jest.requireMock('./calculate_health_status'); (calculateHealthStatus as jest.Mock).mockImplementation(() => HealthStatus.Error); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); const logMessage = JSON.parse( ((logger as jest.Mocked).error.mock.calls[0][0] as string).replace( @@ -214,7 +214,7 @@ describe('logHealthMetrics', () => { }, }); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); expect((logger as jest.Mocked).warn.mock.calls[0][0] as string).toBe( `Detected delay task start of 60s for task(s) \"taskType:test\" (which exceeds configured value of 60s)` @@ -257,7 +257,7 @@ describe('logHealthMetrics', () => { }, }); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); expect((logger as jest.Mocked).warn.mock.calls[0][0] as string).toBe( `Detected delay task start of 60s for task(s) \"taskType:test, taskType:test2\" (which exceeds configured value of 60s)` @@ -288,7 +288,43 @@ describe('logHealthMetrics', () => { stats: {}, }; - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); + + const firstDebug = JSON.parse( + (logger as jest.Mocked).debug.mock.calls[0][0].replace('Latest Monitored Stats: ', '') + ); + expect(firstDebug).toMatchObject(health); + }); + + it('should log as debug if shouldRunTasks is false', () => { + const logger = loggingSystemMock.create().get(); + const config = getTaskManagerConfig({ + monitored_stats_health_verbose_log: { + enabled: true, + warn_delayed_task_start_in_seconds: 60, + }, + }); + const health = getMockMonitoredHealth({ + stats: { + runtime: { + value: { + drift_by_type: { + 'taskType:test': { + p99: 60000, + }, + 'taskType:test2': { + p99: 60000, + }, + }, + drift: { + p99: 60000, + }, + }, + }, + }, + }); + + logHealthMetrics(health, logger, config, false); const firstDebug = JSON.parse( (logger as jest.Mocked).debug.mock.calls[0][0].replace('Latest Monitored Stats: ', '') @@ -312,7 +348,7 @@ describe('logHealthMetrics', () => { }, }); - logHealthMetrics(health, logger, config); + logHealthMetrics(health, logger, config, true); const { calculateHealthStatus } = jest.requireMock('./calculate_health_status'); expect(calculateHealthStatus).toBeCalledTimes(1); diff --git a/x-pack/plugins/task_manager/server/lib/log_health_metrics.ts b/x-pack/plugins/task_manager/server/lib/log_health_metrics.ts index 4a2757ee739e9..55c25f6ce3577 100644 --- a/x-pack/plugins/task_manager/server/lib/log_health_metrics.ts +++ b/x-pack/plugins/task_manager/server/lib/log_health_metrics.ts @@ -27,7 +27,8 @@ export function resetLastLogLevel() { export function logHealthMetrics( monitoredHealth: MonitoredHealth, logger: Logger, - config: TaskManagerConfig + config: TaskManagerConfig, + shouldRunTasks: boolean ) { let logLevel: LogLevel = LogLevel.Debug; const enabled = config.monitored_stats_health_verbose_log.enabled; @@ -38,7 +39,12 @@ export function logHealthMetrics( capacity_estimation: undefined, }, }; - const statusWithoutCapacity = calculateHealthStatus(healthWithoutCapacity, config, logger); + const statusWithoutCapacity = calculateHealthStatus( + healthWithoutCapacity, + config, + shouldRunTasks, + logger + ); if (statusWithoutCapacity === HealthStatus.Warning) { logLevel = LogLevel.Warn; } else if (statusWithoutCapacity === HealthStatus.Error && !isEmpty(monitoredHealth.stats)) { @@ -51,7 +57,9 @@ export function logHealthMetrics( const docLink = `https://www.elastic.co/guide/en/kibana/${docsBranch}/task-manager-health-monitoring.html`; const detectedProblemMessage = `Task Manager detected a degradation in performance. This is usually temporary, and Kibana can recover automatically. If the problem persists, check the docs for troubleshooting information: ${docLink} .`; - if (enabled) { + + // Drift looks at runtime stats which are not available when task manager is not running tasks + if (enabled && shouldRunTasks) { const driftInSeconds = (monitoredHealth.stats.runtime?.value.drift.p99 ?? 0) / 1000; if ( driftInSeconds >= config.monitored_stats_health_verbose_log.warn_delayed_task_start_in_seconds diff --git a/x-pack/plugins/task_manager/server/monitoring/index.ts b/x-pack/plugins/task_manager/server/monitoring/index.ts index 84dd78f432193..de1bea796c038 100644 --- a/x-pack/plugins/task_manager/server/monitoring/index.ts +++ b/x-pack/plugins/task_manager/server/monitoring/index.ts @@ -27,23 +27,23 @@ export { } from './monitoring_stats_stream'; export function createMonitoringStats( - taskPollingLifecycle: TaskPollingLifecycle, - ephemeralTaskLifecycle: EphemeralTaskLifecycle, taskStore: TaskStore, elasticsearchAndSOAvailability$: Observable, config: TaskManagerConfig, managedConfig: ManagedConfiguration, - logger: Logger + logger: Logger, + taskPollingLifecycle?: TaskPollingLifecycle, + ephemeralTaskLifecycle?: EphemeralTaskLifecycle ): Observable { return createMonitoringStatsStream( createAggregators( - taskPollingLifecycle, - ephemeralTaskLifecycle, taskStore, elasticsearchAndSOAvailability$, config, managedConfig, - logger + logger, + taskPollingLifecycle, + ephemeralTaskLifecycle ), config ); diff --git a/x-pack/plugins/task_manager/server/monitoring/monitoring_stats_stream.ts b/x-pack/plugins/task_manager/server/monitoring/monitoring_stats_stream.ts index 125ce034b0c69..e0e7ddd3e79a4 100644 --- a/x-pack/plugins/task_manager/server/monitoring/monitoring_stats_stream.ts +++ b/x-pack/plugins/task_manager/server/monitoring/monitoring_stats_stream.ts @@ -75,17 +75,17 @@ export interface RawMonitoringStats { } export function createAggregators( - taskPollingLifecycle: TaskPollingLifecycle, - ephemeralTaskLifecycle: EphemeralTaskLifecycle, taskStore: TaskStore, elasticsearchAndSOAvailability$: Observable, config: TaskManagerConfig, managedConfig: ManagedConfiguration, - logger: Logger + logger: Logger, + taskPollingLifecycle?: TaskPollingLifecycle, + ephemeralTaskLifecycle?: EphemeralTaskLifecycle ): AggregatedStatProvider { const aggregators: AggregatedStatProvider[] = [ createConfigurationAggregator(config, managedConfig), - createTaskRunAggregator(taskPollingLifecycle, config.monitored_stats_running_average_window), + createWorkloadAggregator( taskStore, elasticsearchAndSOAvailability$, @@ -94,7 +94,12 @@ export function createAggregators( logger ), ]; - if (ephemeralTaskLifecycle.enabled) { + if (taskPollingLifecycle) { + aggregators.push( + createTaskRunAggregator(taskPollingLifecycle, config.monitored_stats_running_average_window) + ); + } + if (ephemeralTaskLifecycle && ephemeralTaskLifecycle.enabled) { aggregators.push( createEphemeralTaskAggregator( ephemeralTaskLifecycle, diff --git a/x-pack/plugins/task_manager/server/plugin.test.ts b/x-pack/plugins/task_manager/server/plugin.test.ts index 0a1f77c665044..93e44c4000750 100644 --- a/x-pack/plugins/task_manager/server/plugin.test.ts +++ b/x-pack/plugins/task_manager/server/plugin.test.ts @@ -11,43 +11,79 @@ import { TaskManagerConfig } from './config'; import { Subject } from 'rxjs'; import { bufferCount, take } from 'rxjs/operators'; import { CoreStatus, ServiceStatusLevels } from '@kbn/core/server'; +import { taskPollingLifecycleMock } from './polling_lifecycle.mock'; +import { TaskPollingLifecycle } from './polling_lifecycle'; +import type { TaskPollingLifecycle as TaskPollingLifecycleClass } from './polling_lifecycle'; +import { ephemeralTaskLifecycleMock } from './ephemeral_task_lifecycle.mock'; +import { EphemeralTaskLifecycle } from './ephemeral_task_lifecycle'; +import type { EphemeralTaskLifecycle as EphemeralTaskLifecycleClass } from './ephemeral_task_lifecycle'; + +let mockTaskPollingLifecycle = taskPollingLifecycleMock.create({}); +jest.mock('./polling_lifecycle', () => { + return { + TaskPollingLifecycle: jest.fn().mockImplementation(() => { + return mockTaskPollingLifecycle; + }), + }; +}); + +let mockEphemeralTaskLifecycle = ephemeralTaskLifecycleMock.create({}); +jest.mock('./ephemeral_task_lifecycle', () => { + return { + EphemeralTaskLifecycle: jest.fn().mockImplementation(() => { + return mockEphemeralTaskLifecycle; + }), + }; +}); + +const coreStart = coreMock.createStart(); +const pluginInitializerContextParams = { + max_workers: 10, + max_attempts: 9, + poll_interval: 3000, + version_conflict_threshold: 80, + max_poll_inactivity_cycles: 10, + request_capacity: 1000, + monitored_aggregated_stats_refresh_rate: 5000, + monitored_stats_health_verbose_log: { + enabled: false, + warn_delayed_task_start_in_seconds: 60, + }, + monitored_stats_required_freshness: 5000, + monitored_stats_running_average_window: 50, + monitored_task_execution_thresholds: { + default: { + error_threshold: 90, + warn_threshold: 80, + }, + custom: {}, + }, + ephemeral_tasks: { + enabled: false, + request_capacity: 10, + }, + unsafe: { + exclude_task_types: [], + }, + event_loop_delay: { + monitor: true, + warn_threshold: 5000, + }, +}; describe('TaskManagerPlugin', () => { + beforeEach(() => { + mockTaskPollingLifecycle = taskPollingLifecycleMock.create({}); + (TaskPollingLifecycle as jest.Mock).mockClear(); + mockEphemeralTaskLifecycle = ephemeralTaskLifecycleMock.create({}); + (EphemeralTaskLifecycle as jest.Mock).mockClear(); + }); + describe('setup', () => { test('throws if no valid UUID is available', async () => { - const pluginInitializerContext = coreMock.createPluginInitializerContext({ - max_workers: 10, - max_attempts: 9, - poll_interval: 3000, - version_conflict_threshold: 80, - max_poll_inactivity_cycles: 10, - request_capacity: 1000, - monitored_aggregated_stats_refresh_rate: 5000, - monitored_stats_health_verbose_log: { - enabled: false, - warn_delayed_task_start_in_seconds: 60, - }, - monitored_stats_required_freshness: 5000, - monitored_stats_running_average_window: 50, - monitored_task_execution_thresholds: { - default: { - error_threshold: 90, - warn_threshold: 80, - }, - custom: {}, - }, - ephemeral_tasks: { - enabled: false, - request_capacity: 10, - }, - unsafe: { - exclude_task_types: [], - }, - event_loop_delay: { - monitor: true, - warn_threshold: 5000, - }, - }); + const pluginInitializerContext = coreMock.createPluginInitializerContext( + pluginInitializerContextParams + ); pluginInitializerContext.env.instanceUuid = ''; @@ -60,39 +96,9 @@ describe('TaskManagerPlugin', () => { }); test('throws if setup methods are called after start', async () => { - const pluginInitializerContext = coreMock.createPluginInitializerContext({ - max_workers: 10, - max_attempts: 9, - poll_interval: 3000, - version_conflict_threshold: 80, - max_poll_inactivity_cycles: 10, - request_capacity: 1000, - monitored_aggregated_stats_refresh_rate: 5000, - monitored_stats_health_verbose_log: { - enabled: false, - warn_delayed_task_start_in_seconds: 60, - }, - monitored_stats_required_freshness: 5000, - monitored_stats_running_average_window: 50, - monitored_task_execution_thresholds: { - default: { - error_threshold: 90, - warn_threshold: 80, - }, - custom: {}, - }, - ephemeral_tasks: { - enabled: true, - request_capacity: 10, - }, - unsafe: { - exclude_task_types: [], - }, - event_loop_delay: { - monitor: true, - warn_threshold: 5000, - }, - }); + const pluginInitializerContext = coreMock.createPluginInitializerContext( + pluginInitializerContextParams + ); const taskManagerPlugin = new TaskManagerPlugin(pluginInitializerContext); @@ -135,37 +141,10 @@ describe('TaskManagerPlugin', () => { test('it logs a warning when the unsafe `exclude_task_types` config is used', async () => { const pluginInitializerContext = coreMock.createPluginInitializerContext({ - max_workers: 10, - max_attempts: 9, - poll_interval: 3000, - version_conflict_threshold: 80, - max_poll_inactivity_cycles: 10, - request_capacity: 1000, - monitored_aggregated_stats_refresh_rate: 5000, - monitored_stats_health_verbose_log: { - enabled: false, - warn_delayed_task_start_in_seconds: 60, - }, - monitored_stats_required_freshness: 5000, - monitored_stats_running_average_window: 50, - monitored_task_execution_thresholds: { - default: { - error_threshold: 90, - warn_threshold: 80, - }, - custom: {}, - }, - ephemeral_tasks: { - enabled: false, - request_capacity: 10, - }, + ...pluginInitializerContextParams, unsafe: { exclude_task_types: ['*'], }, - event_loop_delay: { - monitor: true, - warn_threshold: 5000, - }, }); const logger = pluginInitializerContext.logger.get(); @@ -178,6 +157,38 @@ describe('TaskManagerPlugin', () => { }); }); + describe('start', () => { + test('should initialize task polling lifecycle if node.roles.backgroundTasks is true', async () => { + const pluginInitializerContext = coreMock.createPluginInitializerContext( + pluginInitializerContextParams + ); + pluginInitializerContext.node.roles.backgroundTasks = true; + const taskManagerPlugin = new TaskManagerPlugin(pluginInitializerContext); + taskManagerPlugin.setup(coreMock.createSetup(), { usageCollection: undefined }); + taskManagerPlugin.start(coreStart); + + expect(TaskPollingLifecycle as jest.Mock).toHaveBeenCalledTimes(1); + expect( + EphemeralTaskLifecycle as jest.Mock + ).toHaveBeenCalledTimes(1); + }); + + test('should not initialize task polling lifecycle if node.roles.backgroundTasks is false', async () => { + const pluginInitializerContext = coreMock.createPluginInitializerContext( + pluginInitializerContextParams + ); + pluginInitializerContext.node.roles.backgroundTasks = false; + const taskManagerPlugin = new TaskManagerPlugin(pluginInitializerContext); + taskManagerPlugin.setup(coreMock.createSetup(), { usageCollection: undefined }); + taskManagerPlugin.start(coreStart); + + expect(TaskPollingLifecycle as jest.Mock).not.toHaveBeenCalled(); + expect( + EphemeralTaskLifecycle as jest.Mock + ).not.toHaveBeenCalled(); + }); + }); + describe('getElasticsearchAndSOAvailability', () => { test('returns true when both services are available', async () => { const core$ = new Subject(); diff --git a/x-pack/plugins/task_manager/server/plugin.ts b/x-pack/plugins/task_manager/server/plugin.ts index cf7c3368da3d7..357a1d85fffcf 100644 --- a/x-pack/plugins/task_manager/server/plugin.ts +++ b/x-pack/plugins/task_manager/server/plugin.ts @@ -28,11 +28,10 @@ import { createManagedConfiguration } from './lib/create_managed_configuration'; import { TaskScheduling } from './task_scheduling'; import { healthRoute } from './routes'; import { createMonitoringStats, MonitoringStats } from './monitoring'; -import { EphemeralTaskLifecycle } from './ephemeral_task_lifecycle'; import { EphemeralTask } from './task'; +import { EphemeralTaskLifecycle } from './ephemeral_task_lifecycle'; import { registerTaskManagerUsageCollector } from './usage'; import { TASK_MANAGER_INDEX } from './constants'; - export interface TaskManagerSetupContract { /** * @deprecated @@ -67,6 +66,7 @@ export class TaskManagerPlugin private middleware: Middleware = createInitialMiddleware(); private elasticsearchAndSOAvailability$?: Observable; private monitoringStats$ = new Subject(); + private shouldRunBackgroundTasks: boolean; private readonly kibanaVersion: PluginInitializerContext['env']['packageInfo']['version']; constructor(private readonly initContext: PluginInitializerContext) { @@ -75,6 +75,7 @@ export class TaskManagerPlugin this.config = initContext.config.get(); this.definitions = new TaskTypeDictionary(this.logger); this.kibanaVersion = initContext.env.packageInfo.version; + this.shouldRunBackgroundTasks = initContext.node.roles.backgroundTasks; } public setup( @@ -114,6 +115,7 @@ export class TaskManagerPlugin kibanaIndexName: core.savedObjects.getKibanaIndex(), getClusterClient: () => startServicesPromise.then(({ elasticsearch }) => elasticsearch.client), + shouldRunTasks: this.shouldRunBackgroundTasks, }); core.status.derivedStatus$.subscribe((status) => @@ -186,45 +188,47 @@ export class TaskManagerPlugin startingPollInterval: this.config!.poll_interval, }); - this.taskPollingLifecycle = new TaskPollingLifecycle({ - config: this.config!, - definitions: this.definitions, - unusedTypes: REMOVED_TYPES, - logger: this.logger, - executionContext, - taskStore, - usageCounter: this.usageCounter, - middleware: this.middleware, - elasticsearchAndSOAvailability$: this.elasticsearchAndSOAvailability$!, - ...managedConfiguration, - }); + // Only poll for tasks if configured to run tasks + if (this.shouldRunBackgroundTasks) { + this.taskPollingLifecycle = new TaskPollingLifecycle({ + config: this.config!, + definitions: this.definitions, + unusedTypes: REMOVED_TYPES, + logger: this.logger, + executionContext, + taskStore, + usageCounter: this.usageCounter, + middleware: this.middleware, + elasticsearchAndSOAvailability$: this.elasticsearchAndSOAvailability$!, + ...managedConfiguration, + }); - this.ephemeralTaskLifecycle = new EphemeralTaskLifecycle({ - config: this.config!, - definitions: this.definitions, - logger: this.logger, - executionContext, - middleware: this.middleware, - elasticsearchAndSOAvailability$: this.elasticsearchAndSOAvailability$!, - pool: this.taskPollingLifecycle.pool, - lifecycleEvent: this.taskPollingLifecycle.events, - }); + this.ephemeralTaskLifecycle = new EphemeralTaskLifecycle({ + config: this.config!, + definitions: this.definitions, + logger: this.logger, + executionContext, + middleware: this.middleware, + elasticsearchAndSOAvailability$: this.elasticsearchAndSOAvailability$!, + pool: this.taskPollingLifecycle.pool, + lifecycleEvent: this.taskPollingLifecycle.events, + }); + } createMonitoringStats( - this.taskPollingLifecycle, - this.ephemeralTaskLifecycle, taskStore, this.elasticsearchAndSOAvailability$!, this.config!, managedConfiguration, - this.logger + this.logger, + this.taskPollingLifecycle, + this.ephemeralTaskLifecycle ).subscribe((stat) => this.monitoringStats$.next(stat)); const taskScheduling = new TaskScheduling({ logger: this.logger, taskStore, middleware: this.middleware, - taskPollingLifecycle: this.taskPollingLifecycle, ephemeralTaskLifecycle: this.ephemeralTaskLifecycle, definitions: this.definitions, taskManagerId: taskStore.taskManagerId, @@ -240,7 +244,8 @@ export class TaskManagerPlugin runSoon: (...args) => taskScheduling.runSoon(...args), bulkUpdateSchedules: (...args) => taskScheduling.bulkUpdateSchedules(...args), ephemeralRunNow: (task: EphemeralTask) => taskScheduling.ephemeralRunNow(task), - supportsEphemeralTasks: () => this.config.ephemeral_tasks.enabled, + supportsEphemeralTasks: () => + this.config.ephemeral_tasks.enabled && this.shouldRunBackgroundTasks, }; } diff --git a/x-pack/plugins/task_manager/server/routes/health.test.ts b/x-pack/plugins/task_manager/server/routes/health.test.ts index 31d4a17434598..f2d4dae1532a4 100644 --- a/x-pack/plugins/task_manager/server/routes/health.test.ts +++ b/x-pack/plugins/task_manager/server/routes/health.test.ts @@ -64,6 +64,7 @@ describe('healthRoute', () => { kibanaIndexName: '.kibana', getClusterClient: () => Promise.resolve(elasticsearchServiceMock.createClusterClient()), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); const [config] = router.get.mock.calls[0]; @@ -86,6 +87,7 @@ describe('healthRoute', () => { kibanaIndexName: 'foo', getClusterClient: () => Promise.resolve(mockClusterClient), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); const [, handler] = router.get.mock.calls[0]; @@ -126,6 +128,7 @@ describe('healthRoute', () => { kibanaIndexName: 'foo', getClusterClient: () => Promise.resolve(mockClusterClient), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); const [, handler] = router.get.mock.calls[0]; @@ -171,6 +174,7 @@ describe('healthRoute', () => { kibanaVersion: '8.0', kibanaIndexName: 'foo', getClusterClient: () => Promise.resolve(mockClusterClient), + shouldRunTasks: true, }); const [, handler] = router.get.mock.calls[0]; @@ -212,6 +216,7 @@ describe('healthRoute', () => { kibanaIndexName: '.kibana', getClusterClient: () => Promise.resolve(elasticsearchServiceMock.createClusterClient()), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); stats$.next(mockStat); @@ -270,6 +275,7 @@ describe('healthRoute', () => { kibanaIndexName: '.kibana', getClusterClient: () => Promise.resolve(elasticsearchServiceMock.createClusterClient()), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); stats$.next(warnRuntimeStat); @@ -346,6 +352,7 @@ describe('healthRoute', () => { kibanaIndexName: '.kibana', getClusterClient: () => Promise.resolve(elasticsearchServiceMock.createClusterClient()), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); stats$.next(errorRuntimeStat); @@ -409,6 +416,7 @@ describe('healthRoute', () => { kibanaIndexName: '.kibana', getClusterClient: () => Promise.resolve(elasticsearchServiceMock.createClusterClient()), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); const serviceStatus = getLatest(serviceStatus$); @@ -490,6 +498,7 @@ describe('healthRoute', () => { kibanaIndexName: '.kibana', getClusterClient: () => Promise.resolve(elasticsearchServiceMock.createClusterClient()), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); await sleep(0); @@ -563,6 +572,7 @@ describe('healthRoute', () => { kibanaIndexName: '.kibana', getClusterClient: () => Promise.resolve(elasticsearchServiceMock.createClusterClient()), usageCounter: mockUsageCounter, + shouldRunTasks: true, }); await sleep(0); diff --git a/x-pack/plugins/task_manager/server/routes/health.ts b/x-pack/plugins/task_manager/server/routes/health.ts index 03fe93c79c951..ba9eaa23c6678 100644 --- a/x-pack/plugins/task_manager/server/routes/health.ts +++ b/x-pack/plugins/task_manager/server/routes/health.ts @@ -57,6 +57,7 @@ export interface HealthRouteParams { config: TaskManagerConfig; kibanaVersion: string; kibanaIndexName: string; + shouldRunTasks: boolean; getClusterClient: () => Promise; usageCounter?: UsageCounter; } @@ -75,6 +76,7 @@ export function healthRoute(params: HealthRouteParams): { kibanaIndexName, getClusterClient, usageCounter, + shouldRunTasks, } = params; // if "hot" health stats are any more stale than monitored_stats_required_freshness (pollInterval +1s buffer by default) @@ -83,7 +85,7 @@ export function healthRoute(params: HealthRouteParams): { function getHealthStatus(monitoredStats: MonitoringStats) { const summarizedStats = summarizeMonitoringStats(logger, monitoredStats, config); - const status = calculateHealthStatus(summarizedStats, config, logger); + const status = calculateHealthStatus(summarizedStats, config, shouldRunTasks, logger); const now = Date.now(); const timestamp = new Date(now).toISOString(); return { id: taskManagerId, timestamp, status, ...summarizedStats }; @@ -109,7 +111,7 @@ export function healthRoute(params: HealthRouteParams): { .subscribe(([monitoredHealth, serviceStatus]) => { serviceStatus$.next(serviceStatus); monitoredHealth$.next(monitoredHealth); - logHealthMetrics(monitoredHealth, logger, config); + logHealthMetrics(monitoredHealth, logger, config, shouldRunTasks); }); router.get( diff --git a/x-pack/plugins/task_manager/server/task_scheduling.test.ts b/x-pack/plugins/task_manager/server/task_scheduling.test.ts index ca0d8dc0cadd9..7c9d6e9bd5fbe 100644 --- a/x-pack/plugins/task_manager/server/task_scheduling.test.ts +++ b/x-pack/plugins/task_manager/server/task_scheduling.test.ts @@ -10,7 +10,6 @@ import moment from 'moment'; import { asTaskRunEvent, TaskPersistence } from './task_events'; import { TaskLifecycleEvent } from './polling_lifecycle'; -import { taskPollingLifecycleMock } from './polling_lifecycle.mock'; import { TaskScheduling } from './task_scheduling'; import { asErr, asOk } from './lib/result_type'; import { ConcreteTaskInstance, TaskStatus } from './task'; @@ -35,11 +34,9 @@ jest.mock('elastic-apm-node', () => ({ describe('TaskScheduling', () => { const mockTaskStore = taskStoreMock.create({}); - const mockTaskManager = taskPollingLifecycleMock.create({}); const definitions = new TaskTypeDictionary(mockLogger()); const taskSchedulingOpts = { taskStore: mockTaskStore, - taskPollingLifecycle: mockTaskManager, logger: mockLogger(), middleware: createInitialMiddleware(), definitions, @@ -476,6 +473,28 @@ describe('TaskScheduling', () => { `[Error: Ephemeral Task of type foo was rejected]` ); }); + + test('rejects ephemeral task if ephemeralTaskLifecycle is not defined', async () => { + const ephemeralTask = mockTask({ + state: { + foo: 'bar', + }, + }); + const middleware = createInitialMiddleware(); + middleware.beforeSave = jest.fn().mockImplementation(async () => { + return { taskInstance: ephemeralTask }; + }); + const taskScheduling = new TaskScheduling({ + ...taskSchedulingOpts, + middleware, + ephemeralTaskLifecycle: undefined, + }); + + const result = taskScheduling.ephemeralRunNow(ephemeralTask); + expect(result).rejects.toMatchInlineSnapshot( + `[Error: Ephemeral Task of type foo was rejected because ephemeral tasks are not supported]` + ); + }); }); }); diff --git a/x-pack/plugins/task_manager/server/task_scheduling.ts b/x-pack/plugins/task_manager/server/task_scheduling.ts index b604b683570ae..ef6ab359b9064 100644 --- a/x-pack/plugins/task_manager/server/task_scheduling.ts +++ b/x-pack/plugins/task_manager/server/task_scheduling.ts @@ -12,7 +12,7 @@ import { getOrElse, isSome, map as mapOptional, Option } from 'fp-ts/lib/Option' import uuid from 'uuid'; import { chunk, pick } from 'lodash'; -import { merge, Subject } from 'rxjs'; +import { Subject } from 'rxjs'; import agent from 'elastic-apm-node'; import { Logger } from '@kbn/core/server'; import { mustBeAllOf } from './queries/query_clauses'; @@ -42,7 +42,7 @@ import { } from './task'; import { TaskStore } from './task_store'; import { ensureDeprecatedFieldsAreCorrected } from './lib/correct_deprecated_fields'; -import { TaskLifecycleEvent, TaskPollingLifecycle } from './polling_lifecycle'; +import { TaskLifecycleEvent } from './polling_lifecycle'; import { TaskTypeDictionary } from './task_type_dictionary'; import { EphemeralTaskLifecycle } from './ephemeral_task_lifecycle'; import { EphemeralTaskRejectedDueToCapacityError } from './task_running'; @@ -52,8 +52,7 @@ const VERSION_CONFLICT_STATUS = 409; export interface TaskSchedulingOpts { logger: Logger; taskStore: TaskStore; - taskPollingLifecycle: TaskPollingLifecycle; - ephemeralTaskLifecycle: EphemeralTaskLifecycle; + ephemeralTaskLifecycle?: EphemeralTaskLifecycle; middleware: Middleware; definitions: TaskTypeDictionary; taskManagerId: string; @@ -84,8 +83,7 @@ export interface RunNowResult { export class TaskScheduling { private store: TaskStore; - private taskPollingLifecycle: TaskPollingLifecycle; - private ephemeralTaskLifecycle: EphemeralTaskLifecycle; + private ephemeralTaskLifecycle?: EphemeralTaskLifecycle; private logger: Logger; private middleware: Middleware; private definitions: TaskTypeDictionary; @@ -99,7 +97,6 @@ export class TaskScheduling { constructor(opts: TaskSchedulingOpts) { this.logger = opts.logger; this.middleware = opts.middleware; - this.taskPollingLifecycle = opts.taskPollingLifecycle; this.ephemeralTaskLifecycle = opts.ephemeralTaskLifecycle; this.store = opts.taskStore; this.definitions = opts.definitions; @@ -239,6 +236,12 @@ export class TaskScheduling { task: EphemeralTask, options?: Record ): Promise { + if (!this.ephemeralTaskLifecycle) { + throw new EphemeralTaskRejectedDueToCapacityError( + `Ephemeral Task of type ${task.taskType} was rejected because ephemeral tasks are not supported`, + task + ); + } const id = uuid.v4(); const { taskInstance: modifiedTask } = await this.middleware.beforeSave({ ...options, @@ -261,7 +264,7 @@ export class TaskScheduling { .catch((err: Error) => { reject(err); }); - const attemptToRunResult = this.ephemeralTaskLifecycle.attemptToRun({ + const attemptToRunResult = this.ephemeralTaskLifecycle!.attemptToRun({ id, scheduledAt: new Date(), runAt: new Date(), @@ -307,64 +310,68 @@ export class TaskScheduling { private awaitTaskRunResult(taskId: string, cancel?: Promise): Promise { return new Promise((resolve, reject) => { + if (!this.ephemeralTaskLifecycle) { + reject( + new Error( + `Failed to run task "${taskId}" because ephemeral tasks are not supported. Rescheduled the task to ensure it is picked up as soon as possible.` + ) + ); + } // listen for all events related to the current task - const subscription = merge( - this.taskPollingLifecycle.events, - this.ephemeralTaskLifecycle.events - ) - .pipe(filter(({ id }: TaskLifecycleEvent) => id === taskId)) - .subscribe((taskEvent: TaskLifecycleEvent) => { - if (isTaskClaimEvent(taskEvent)) { - mapErr(async (error: ClaimTaskErr) => { - // reject if any error event takes place for the requested task - subscription.unsubscribe(); - if ( - isSome(error.task) && - error.errorType === TaskClaimErrorType.CLAIMED_BY_ID_OUT_OF_CAPACITY - ) { - const task = error.task.value; - const definition = this.definitions.get(task.taskType); - return reject( - new Error( - `Failed to run task "${taskId}" as we would exceed the max concurrency of "${ - definition?.title ?? task.taskType - }" which is ${ - definition?.maxConcurrency - }. Rescheduled the task to ensure it is picked up as soon as possible.` - ) - ); - } else { - return reject(await this.identifyTaskFailureReason(taskId, error.task)); - } - }, taskEvent.event); - } else { - either, ErrResultOf>( - taskEvent.event, - (taskInstance: OkResultOf) => { - // resolve if the task has run sucessfully - if (isTaskRunEvent(taskEvent)) { - subscription.unsubscribe(); - resolve(pick((taskInstance as RanTask).task, ['id', 'state'])); - } - }, - async (errorResult: ErrResultOf) => { - // reject if any error event takes place for the requested task + const subscription = this.ephemeralTaskLifecycle!.events.pipe( + filter(({ id }: TaskLifecycleEvent) => id === taskId) + ).subscribe((taskEvent: TaskLifecycleEvent) => { + if (isTaskClaimEvent(taskEvent)) { + mapErr(async (error: ClaimTaskErr) => { + // reject if any error event takes place for the requested task + subscription.unsubscribe(); + if ( + isSome(error.task) && + error.errorType === TaskClaimErrorType.CLAIMED_BY_ID_OUT_OF_CAPACITY + ) { + const task = error.task.value; + const definition = this.definitions.get(task.taskType); + return reject( + new Error( + `Failed to run task "${taskId}" as we would exceed the max concurrency of "${ + definition?.title ?? task.taskType + }" which is ${ + definition?.maxConcurrency + }. Rescheduled the task to ensure it is picked up as soon as possible.` + ) + ); + } else { + return reject(await this.identifyTaskFailureReason(taskId, error.task)); + } + }, taskEvent.event); + } else { + either, ErrResultOf>( + taskEvent.event, + (taskInstance: OkResultOf) => { + // resolve if the task has run sucessfully + if (isTaskRunEvent(taskEvent)) { subscription.unsubscribe(); - return reject( - new Error( - `Failed to run task "${taskId}": ${ - isTaskRunRequestEvent(taskEvent) - ? `Task Manager is at capacity, please try again later` - : isTaskRunEvent(taskEvent) - ? `${(errorResult as ErroredTask).error}` - : `${errorResult}` - }` - ) - ); + resolve(pick((taskInstance as RanTask).task, ['id', 'state'])); } - ); - } - }); + }, + async (errorResult: ErrResultOf) => { + // reject if any error event takes place for the requested task + subscription.unsubscribe(); + return reject( + new Error( + `Failed to run task "${taskId}": ${ + isTaskRunRequestEvent(taskEvent) + ? `Task Manager is at capacity, please try again later` + : isTaskRunEvent(taskEvent) + ? `${(errorResult as ErroredTask).error}` + : `${errorResult}` + }` + ) + ); + } + ); + } + }); if (cancel) { cancel.then(() => { From 54a32d3e1c0c7b8699def97c6171fa58ca06f3a0 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 5 Jul 2022 15:07:38 -0700 Subject: [PATCH 14/81] Upgrade Search UI and fix all type errors (#135737) * Update Search UI dependencies * Fix type errors after the upgrade * Fix documents search being broken after recent backend changes * Ignore TS error caused by bug in Search UI View passed to Paging component should accept any additional props (for example for data- or area- attributes). * Fix test - we don't expect snippet for number field --- package.json | 4 +- .../curation/documents/organic_documents.tsx | 4 +- .../curation/results/curation_result.tsx | 6 +- .../curations/curation/results/utils.ts | 12 +- .../app_search/components/curations/types.ts | 6 +- .../curation_result_panel.tsx | 5 +- .../curation_suggestion.tsx | 7 +- .../build_search_ui_config.test.ts | 8 +- .../build_search_ui_config.ts | 40 ++- .../search_experience/hooks.test.tsx | 14 +- .../documents/search_experience/hooks.ts | 9 +- .../search_experience/pagination.test.tsx | 1 - .../search_experience/pagination.tsx | 2 +- .../search_experience.test.tsx | 1 - .../search_experience/search_experience.tsx | 9 +- .../search_experience_content.test.tsx | 1 - .../search_experience_content.tsx | 6 +- .../views/multi_checkbox_facets_view.test.tsx | 8 +- .../views/multi_checkbox_facets_view.tsx | 20 +- .../search_experience/views/paging_view.tsx | 4 +- .../search_experience/views/result_view.tsx | 5 +- .../views/results_per_page_view.tsx | 6 +- .../relevance_tuning_logic.ts | 9 +- .../app_search/components/result/result.tsx | 5 +- .../app_search/components/result/types.ts | 12 - .../components/search/search_logic.ts | 12 +- .../app_search/utils/results/index.test.ts | 6 +- yarn.lock | 259 ++++++------------ 28 files changed, 201 insertions(+), 280 deletions(-) diff --git a/package.json b/package.json index b1ff372ff0699..501fd8dc9991d 100644 --- a/package.json +++ b/package.json @@ -112,10 +112,10 @@ "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", - "@elastic/react-search-ui": "^1.6.0", + "@elastic/react-search-ui": "^1.14.0", "@elastic/request-crypto": "2.0.1", "@elastic/safer-lodash-set": "link:bazel-bin/packages/elastic-safer-lodash-set", - "@elastic/search-ui-app-search-connector": "^1.6.0", + "@elastic/search-ui-app-search-connector": "^1.14.0", "@emotion/cache": "^11.7.1", "@emotion/css": "^11.9.0", "@emotion/react": "^11.9.0", 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 7c8abaa1377b9..8c6cc93ccf843 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 @@ -10,13 +10,13 @@ import React from 'react'; import { useValues, useActions } from 'kea'; import { EuiLoadingContent, EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import type { SearchResult } from '@elastic/search-ui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { LeafIcon } from '../../../../../shared/icons'; import { DataPanel } from '../../../data_panel'; -import { Result } from '../../../result/types'; import { PROMOTE_DOCUMENT_ACTION, HIDE_DOCUMENT_ACTION } from '../../constants'; import { CurationLogic } from '../curation_logic'; @@ -47,7 +47,7 @@ export const OrganicDocuments: React.FC = () => { > {hasDocuments ? ( - {documents.map((document: Result, index) => ( + {documents.map((document: SearchResult, index) => ( { - const result = {} as Result; +export const convertToResultFormat = (document: CurationResult): SearchResult => { + const result = {} as SearchResult; // Convert `key: 'value'` into `key: { raw: 'value' }` Object.entries(document).forEach(([key, value]) => { @@ -49,7 +51,7 @@ export const convertToResultFormat = (document: CurationResult): Result => { return result; }; -export const convertIdToMeta = (id: string): Result['_meta'] => { +export const convertIdToMeta = (id: string): SearchResult['_meta'] => { const splitId = id.split('|'); const isMetaEngine = splitId.length > 1; @@ -58,7 +60,7 @@ export const convertIdToMeta = (id: string): Result['_meta'] => { engine: splitId[0], id: splitId[1], } - : ({ id } as Result['_meta']); + : ({ id } as SearchResult['_meta']); // Note: We're casting this as _meta even though `engine` is missing, // since for source engines the engine shouldn't matter / be displayed, // but if needed we could likely populate this from EngineLogic.values 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 fea3dac75e3b8..73aefbdfd205d 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 @@ -5,8 +5,10 @@ * 2.0. */ +import type { SearchResult } from '@elastic/search-ui'; + import { Meta } from '../../../../../common/types'; -import { Result, ResultMeta } from '../result/types'; +import { ResultMeta } from '../result/types'; export interface CurationSuggestion { query: string; @@ -32,7 +34,7 @@ export interface Curation { queries: string[]; promoted: CurationResult[]; hidden: CurationResult[]; - organic?: Result[]; // this field is missing if there are 0 results + organic?: SearchResult[]; // this field is missing if there are 0 results suggestion?: CurationSuggestion; } 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 de3160b1d0e2f..142d077501af2 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 @@ -17,17 +17,18 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; +import type { SearchResult } from '@elastic/search-ui'; + 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'; interface Props { variant: 'current' | 'promoted' | 'suggested' | 'hidden'; - results: ResultType[]; + results: SearchResult[]; } export const CurationResultPanel: React.FC = ({ variant, results }) => { 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 4e344d8cc2a39..bed16d609ef15 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 @@ -19,6 +19,8 @@ import { EuiSpacer, EuiTitle, } from '@elastic/eui'; +import type { SearchResult } from '@elastic/search-ui'; + import { i18n } from '@kbn/i18n'; import { LeafIcon } from '../../../../../shared/icons'; @@ -26,7 +28,6 @@ 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'; import { convertToResultFormat } from '../../curation/results'; import { getCurationsBreadcrumbs } from '../../utils'; @@ -149,7 +150,7 @@ export const CurationSuggestion: React.FC = () => { gutterSize="s" data-test-subj="currentOrganicResults" > - {currentOrganicResults.map((result: ResultType, index) => ( + {currentOrganicResults.map((result: SearchResult, index) => ( { gutterSize="s" data-test-subj="proposedOrganicResults" > - {proposedOrganicResults.map((result: ResultType, index) => ( + {proposedOrganicResults.map((result: SearchResult, index) => ( { sortFields: [], }; - const config = buildSearchUIConfig(connector, schema, fields); + const config = buildSearchUIConfig(connector as APIConnector, schema, fields); expect(config).toEqual({ alwaysSearchOnInitialLoad: true, apiConnector: connector, @@ -44,10 +46,6 @@ describe('buildSearchUIConfig', () => { result_fields: { bar: { raw: {}, - snippet: { - fallback: true, - size: 300, - }, }, foo: { raw: {}, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_search_ui_config.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_search_ui_config.ts index 9c06527162b81..1edcc3cdfc27a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_search_ui_config.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/build_search_ui_config.ts @@ -5,23 +5,28 @@ * 2.0. */ +import type { APIConnector, SortDirection } from '@elastic/search-ui'; + import { Schema } from '../../../../shared/schema/types'; import { Fields } from './types'; export const buildSearchUIConfig = ( - apiConnector: object, + apiConnector: APIConnector, schema: Schema, fields: Fields, - initialState = { sortDirection: 'desc', sortField: 'id' } + initialState = { sortDirection: 'desc' as SortDirection, sortField: 'id' } ) => { - const facets = fields.filterFields.reduce( - (facetsConfig, fieldName) => ({ + const facets = fields.filterFields.reduce((facetsConfig, fieldName) => { + // Geolocation fields do not support value facets https://www.elastic.co/guide/en/app-search/current/facets.html + if (schema[fieldName] === 'geolocation') { + return facetsConfig; + } + return { ...facetsConfig, [fieldName]: { type: 'value', size: 30 }, - }), - {} - ); + }; + }, {}); return { alwaysSearchOnInitialLoad: true, @@ -32,13 +37,20 @@ export const buildSearchUIConfig = ( disjunctiveFacets: fields.filterFields, facets, result_fields: Object.keys(schema).reduce((acc: { [key: string]: object }, key: string) => { - acc[key] = { - snippet: { - size: 300, - fallback: true, - }, - raw: {}, - }; + if (schema[key] === 'text') { + // Only text fields support snippets + acc[key] = { + snippet: { + size: 300, + fallback: true, + }, + raw: {}, + }; + } else { + acc[key] = { + raw: {}, + }; + } return acc; }, {}), }, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.test.tsx index 028a9af21311f..f1bf6289929a2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.test.tsx @@ -9,8 +9,8 @@ const mockAction = jest.fn(); let mockSubcription: (state: object) => void; const mockDriver = { - state: { foo: 'foo' }, - actions: { bar: mockAction }, + state: { searchTerm: 'foo' }, + actions: { setSearchTerm: mockAction }, subscribeToStateChanges: jest.fn().mockImplementation((fn) => { mockSubcription = fn; }), @@ -34,8 +34,8 @@ import { useSearchContextState, useSearchContextActions } from './hooks'; describe('hooks', () => { describe('useSearchContextState', () => { const TestComponent = () => { - const { foo } = useSearchContextState(); - return
{foo}
; + const { searchTerm } = useSearchContextState(); + return
{searchTerm}
; }; let wrapper: ReactWrapper; @@ -49,7 +49,7 @@ describe('hooks', () => { it('subscribes to state changes', () => { act(() => { - mockSubcription({ foo: 'bar' }); + mockSubcription({ searchTerm: 'bar' }); }); expect(wrapper.text()).toEqual('bar'); @@ -65,8 +65,8 @@ describe('hooks', () => { describe('useSearchContextActions', () => { it('exposes actions', () => { const TestComponent = () => { - const { bar } = useSearchContextActions(); - bar(); + const { setSearchTerm } = useSearchContextActions(); + setSearchTerm('bar'); return null; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.ts index 7fb05c0aaba69..7b1029970a444 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/hooks.ts @@ -7,19 +7,20 @@ import { useContext, useEffect, useState } from 'react'; -// @ts-expect-error types are not available for this package yet import { SearchContext } from '@elastic/react-search-ui'; +import type { SearchState } from '@elastic/search-ui'; export const useSearchContextState = () => { const { driver } = useContext(SearchContext); const [state, setState] = useState(driver.state); useEffect(() => { - driver.subscribeToStateChanges((newState: object) => { + const subscription = (newState: SearchState) => { setState(newState); - }); + }; + driver.subscribeToStateChanges(subscription); return () => { - driver.unsubscribeToStateChanges(); + driver.unsubscribeToStateChanges(subscription); }; }, [state]); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.test.tsx index b55163ca9843a..cc438abd9ba94 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.test.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { shallow } from 'enzyme'; -// @ts-expect-error types are not available for this package yet import { Paging, ResultsPerPage } from '@elastic/react-search-ui'; import { Pagination } from './pagination'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.tsx index d81b056842642..53b0e22553d52 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/pagination.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -// @ts-expect-error types are not available for this package yet import { Paging, ResultsPerPage } from '@elastic/react-search-ui'; import { PagingView, ResultsPerPageView } from './views'; @@ -20,6 +19,7 @@ export const Pagination: React.FC<{ 'aria-label': string }> = ({ 'aria-label': a className="documentsSearchExperience__pagingInfo" > + {/* @ts-ignore */} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx index 2871e4f96015f..1a6a2abba0904 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx @@ -12,7 +12,6 @@ import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; -// @ts-expect-error types are not available for this package yet import { SearchProvider, Facet } from '@elastic/react-search-ui'; jest.mock('../../../../shared/use_local_storage', () => ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx index fc54b9cdf300e..397bcd2e14f83 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx @@ -10,9 +10,8 @@ import React, { useState } from 'react'; import { useValues } from 'kea'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -// @ts-expect-error types are not available for this package yet; import { SearchProvider, SearchBox, Sorting, Facet } from '@elastic/react-search-ui'; -// @ts-expect-error types are not available for this package yet +import type { SortDirection } from '@elastic/search-ui'; import AppSearchAPIConnector from '@elastic/search-ui-app-search-connector'; import { i18n } from '@kbn/i18n'; @@ -88,15 +87,15 @@ export const SearchExperience: React.FC = () => { const connector = new AppSearchAPIConnector({ cacheResponses: false, endpointBase, - engineName: engine.name, + engineName: engine.name as string, additionalHeaders: { 'kbn-xsrf': true, }, - }); + } as ConstructorParameters[0]); const initialState = { sortField: sortOptions[0].value, - sortDirection: 'desc', + sortDirection: 'desc' as SortDirection, }; const searchProviderConfig = buildSearchUIConfig( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx index e573502d76b9f..16a18a71981a2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx @@ -12,7 +12,6 @@ import React from 'react'; import { shallow } from 'enzyme'; -// @ts-expect-error types are not available for this package yet import { Results } from '@elastic/react-search-ui'; import { Loading } from '../../../../shared/loading'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx index b03aa6a64c7d9..2dbafaacb1e93 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx @@ -10,13 +10,13 @@ import React from 'react'; import { useValues } from 'kea'; import { EuiFlexGroup, EuiSpacer, EuiEmptyPrompt } from '@elastic/eui'; -// @ts-expect-error types are not available for this package yet + import { Results } from '@elastic/react-search-ui'; +import type { SearchResult } from '@elastic/search-ui'; import { i18n } from '@kbn/i18n'; import { Loading } from '../../../../shared/loading'; import { EngineLogic } from '../../engine'; -import { Result } from '../../result/types'; import { useSearchContextState } from './hooks'; import { Pagination } from './pagination'; @@ -43,7 +43,7 @@ export const SearchExperienceContent: React.FC = () => { { + resultView={({ result }: { result: SearchResult }) => { return ( { @@ -23,7 +25,7 @@ describe('MultiCheckboxFacetsView', () => { value: 'value2', selected: false, }, - ], + ] as FacetValue[], showMore: true, onMoreClick: jest.fn(), onRemove: jest.fn(), @@ -65,7 +67,7 @@ describe('MultiCheckboxFacetsView', () => { value: 'value2', selected: true, }, - ], + ] as FacetValue[], }} /> ); @@ -87,7 +89,7 @@ describe('MultiCheckboxFacetsView', () => { value: '', selected: false, }, - ], + ] as FacetValue[], }} /> ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/multi_checkbox_facets_view.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/multi_checkbox_facets_view.tsx index 98770c7a792b4..af650ce7a0146 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/multi_checkbox_facets_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/multi_checkbox_facets_view.tsx @@ -14,20 +14,16 @@ import { EuiButtonEmpty, EuiSpacer, } from '@elastic/eui'; +import type { FieldValue, FacetValue } from '@elastic/search-ui'; import { i18n } from '@kbn/i18n'; -interface Option { - value: string; - selected: boolean; -} - interface Props { label: string; - options: Option[]; + options: FacetValue[]; showMore: boolean; onMoreClick(): void; - onRemove(id: string): void; - onSelect(id: string): void; + onRemove(value: FieldValue): void; + onSelect(value: FieldValue): void; } const getIndexFromId = (id: string) => parseInt(id.split('_')[1], 10); @@ -42,7 +38,7 @@ export const MultiCheckboxFacetsView: React.FC = ({ }) => { const getId = htmlIdGenerator(); - const optionToCheckBoxGroupOption = (option: Option, index: number) => ({ + const optionToCheckBoxGroupOption = (option: FacetValue, index: number) => ({ id: getId(String(index)), label: option.value || @@ -56,7 +52,7 @@ export const MultiCheckboxFacetsView: React.FC = ({ const optionToSelectedMapReducer = ( selectedMap: { [name: string]: boolean }, - option: Option, + option: FacetValue, index: number ) => { if (option.selected) { @@ -72,10 +68,10 @@ export const MultiCheckboxFacetsView: React.FC = ({ const index = getIndexFromId(checkboxId); const option = options[index]; if (option.selected) { - onRemove(option.value); + onRemove(option.value as FieldValue); return; } - onSelect(option.value); + onSelect(option.value as FieldValue); }; return ( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.tsx index 1ae194c7bab66..c79ea36ba100a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.tsx @@ -10,14 +10,14 @@ import React from 'react'; import { EuiPagination } from '@elastic/eui'; interface Props { - current: number; + current?: number; totalPages: number; onChange(pageNumber: number): void; 'aria-label': string; } export const PagingView: React.FC = ({ - current, + current = 1, onChange, totalPages, 'aria-label': ariaLabel, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.tsx index 45dafe385f737..930b60f22a947 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/result_view.tsx @@ -7,12 +7,13 @@ import React from 'react'; +import type { SearchResult } from '@elastic/search-ui'; + import { Schema } from '../../../../../shared/schema/types'; import { Result } from '../../../result/result'; -import { Result as ResultType } from '../../../result/types'; export interface Props { - result: ResultType; + result: SearchResult; schemaForTypeHighlights?: Schema; isMetaEngine: boolean; } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.tsx index 5056d56d1f3d0..63050ca1d79ff 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.tsx @@ -16,12 +16,12 @@ const wrapResultsPerPageOptionForEuiSelect: (option: number) => EuiSelectOption }); interface Props { - options: number[]; - value: number; + options?: number[]; + value?: number; onChange(value: number): void; } -export const ResultsPerPageView: React.FC = ({ onChange, options, value }) => { +export const ResultsPerPageView: React.FC = ({ onChange, options = [], value = 20 }) => { // If we don't have the value in options, unset it const selectedValue = value && !options.includes(value) ? undefined : value; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts index fd2ed0693257d..5b4d1fb23ef0b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts @@ -8,6 +8,8 @@ import { kea, MakeLogicType } from 'kea'; import { omit, cloneDeep, isEmpty } from 'lodash'; +import type { SearchResult } from '@elastic/search-ui'; + import { flashSuccessToast, flashAPIErrors, @@ -17,7 +19,6 @@ import { HttpLogic } from '../../../shared/http'; import { Schema, SchemaConflicts } from '../../../shared/schema/types'; import { EngineLogic } from '../engine'; -import { Result } from '../result/types'; import { UPDATE_SUCCESS_MESSAGE, @@ -47,7 +48,7 @@ interface RelevanceTuningActions { setSearchSettings(searchSettings: SearchSettings): { searchSettings: SearchSettings }; setFilterValue(value: string): string; setSearchQuery(value: string): string; - setSearchResults(searchResults: Result[]): Result[]; + setSearchResults(searchResults: SearchResult[]): SearchResult[]; setResultsLoading(resultsLoading: boolean): boolean; clearSearchResults(): void; resetSearchSettingsState(): void; @@ -104,7 +105,7 @@ interface RelevanceTuningValues { query: string; unsavedChanges: boolean; dataLoading: boolean; - searchResults: Result[] | null; + searchResults: SearchResult[] | null; resultsLoading: boolean; } @@ -278,7 +279,7 @@ export const RelevanceTuningLogic = kea< const filteredBoosts = removeEmptyValueBoosts(boosts); try { - const response = await http.post<{ results: Result[] }>(url, { + const response = await http.post<{ results: SearchResult[] }>(url, { query: { query, }, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx index 9d5d49b58bf5d..0c78cc672a609 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx @@ -12,6 +12,7 @@ import './result.scss'; import { EuiPanel, EuiIcon } from '@elastic/eui'; +import type { SearchResult } from '@elastic/search-ui'; import { i18n } from '@kbn/i18n'; import { KibanaLogic } from '../../../shared/kibana'; @@ -23,10 +24,10 @@ import { flattenDocument } from '../../utils/results'; import { ResultField } from './result_field'; import { ResultHeader } from './result_header'; -import { FieldValue, Result as ResultType, ResultAction } from './types'; +import { FieldValue, ResultAction } from './types'; interface Props { - result: ResultType; + result: SearchResult; isMetaEngine: boolean; showScore?: boolean; resultPosition?: number; 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 f8f579fa32f80..9ffc535edaca2 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 @@ -25,18 +25,6 @@ export interface ResultMeta { clicks?: number; } -// A search result item -export type Result = { - id: { - raw: string; - }; - _meta: ResultMeta; -} & { - // this should be a FieldType object, but there's no good way to do that in TS: https://github.com/microsoft/TypeScript/issues/17867 - // You'll need to cast it to FieldValue whenever you use it. - [key: string]: object; -}; - export interface ResultAction { onClick(): void; title: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts index e21b529474bf7..4097e693aff11 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts @@ -7,23 +7,23 @@ import { kea, MakeLogicType } from 'kea'; +import type { SearchResult } from '@elastic/search-ui'; + import { flashAPIErrors } from '../../../shared/flash_messages'; import { HttpLogic } from '../../../shared/http'; import { flattenDocument } from '../../utils/results'; import { EngineLogic } from '../engine'; -import { Result } from '../result/types'; - interface SearchValues { searchDataLoading: boolean; searchQuery: string; - searchResults: Result[]; + searchResults: SearchResult[]; } interface SearchActions { search(query: string): { query: string }; - onSearch({ results }: { results: Result[] }): { results: Result[] }; + onSearch({ results }: { results: SearchResult[] }): { results: SearchResult[] }; } export const SearchLogic = kea>({ @@ -50,7 +50,7 @@ export const SearchLogic = kea>({ searchResults: [ [], { - onSearch: (_, { results }) => results.map((res) => flattenDocument(res) as Result), + onSearch: (_, { results }) => results.map((res) => flattenDocument(res) as SearchResult), }, ], }), @@ -62,7 +62,7 @@ export const SearchLogic = kea>({ const { engineName } = EngineLogic.values; try { - const response = await http.post<{ results: Result[] }>( + const response = await http.post<{ results: SearchResult[] }>( `/internal/app_search/engines/${engineName}/search`, { query: { query } } ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.test.ts index 126bb5ade054d..c330ce62b474a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { Result } from '../../components/result/types'; +import type { SearchResult } from '@elastic/search-ui'; import { flattenDocument, flattenDocumentField } from '.'; @@ -42,13 +42,13 @@ describe('flattenDocumentField', () => { describe('flattenDocument', () => { it('flattens all fields without raw key', () => { - const result: Result = { + const result: SearchResult = { id: { raw: '123' }, _meta: { engine: 'Test', id: '1' }, title: { raw: 'Getty Museum' }, address: { city: { raw: 'Los Angeles' }, state: { raw: 'California' } }, }; - const expected: Result = { + const expected: SearchResult = { id: { raw: '123' }, _meta: { engine: 'Test', id: '1' }, title: { raw: 'Getty Museum' }, diff --git a/yarn.lock b/yarn.lock index f9a5118594c4f..9b23ac23f442d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1422,10 +1422,10 @@ version "0.0.0" uid "" -"@elastic/app-search-javascript@^7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@elastic/app-search-javascript/-/app-search-javascript-7.13.1.tgz#07d84daa27e856ad14f3f840683288eab06577f4" - integrity sha512-ShzZtGWykLQ0+wXzfk6lJztv68fRcGa8rsLDxJLH/O/2CGY+PJDnj8Qu5lJPmsAPZlZgaB8u7l26YGVPOoaqSA== +"@elastic/app-search-javascript@^8.1.2": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@elastic/app-search-javascript/-/app-search-javascript-8.1.2.tgz#8b60d74deab05b6e8603078c013d75cbd41c2f80" + integrity sha512-o3S3GrwaKhZWedLDrPpyHwAhidovTqG0oEz0+f1Hk4mDLmnlViPBIJhg12KuCuM0MYFUavKDHoqARlsbW8z6Kw== dependencies: object-hash "^1.3.0" @@ -1595,22 +1595,23 @@ resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.5.1.tgz#96acf39c3d599950646ef8ccfd24a3f057cf4932" integrity sha512-Tby6TKjixRFY+atVNeYUdGr9m0iaOq8230KTwn8BbUhkh7LwozfgKq0U98HRX7n63ZL62szl+cDKTYzh5WPCFQ== -"@elastic/react-search-ui-views@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@elastic/react-search-ui-views/-/react-search-ui-views-1.6.0.tgz#7211d47c29ef0636c853721491b9905ac7ae58da" - integrity sha512-VADJ18p8HoSPtxKEWFODzId08j0ahyHmHjXv1vP6O/PvtA+ECvi0gDSh/WgdRF792G0e+4d2Dke8LIhxaEvE+w== +"@elastic/react-search-ui-views@1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@elastic/react-search-ui-views/-/react-search-ui-views-1.14.0.tgz#59e58f5c5f8769995baa0b5606da67e47535ea8b" + integrity sha512-zvW7Dzbf5thNTK1rTKrbsk8bCFK4d4YVtA0VjMSM0Y52CH6zVQrOqEsV/ilcIiHyvR7uFiiLHsFX6Yk3bHdrBw== dependencies: + "@elastic/search-ui" "1.14.0" downshift "^3.2.10" rc-pagination "^1.20.1" - react-select "^2.4.4" + react-select "^5.0.0" -"@elastic/react-search-ui@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@elastic/react-search-ui/-/react-search-ui-1.6.0.tgz#8d547d5e1f0a8eebe94798b29966f51643aa886f" - integrity sha512-bwSKuCQTQiBWr6QufQtZZGu6rcVYfoiUnyZbwZMS6ojedd5XY7FtMcE+QnR6/IIo0M2IUrxD74XtVNqkUhoCRg== +"@elastic/react-search-ui@^1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@elastic/react-search-ui/-/react-search-ui-1.14.0.tgz#cac7f6bba7cf84bf8c4e8d8deb14a443286c3dfc" + integrity sha512-vwOOpUjL/Y+o/53rt8VeBcjw7rPfg7eZMmSezjw3jYy17eC7mTIHTQf6knbyVO30R1KXl7LyAuyfQLS+ifX2zg== dependencies: - "@elastic/react-search-ui-views" "1.6.0" - "@elastic/search-ui" "1.6.0" + "@elastic/react-search-ui-views" "1.14.0" + "@elastic/search-ui" "1.14.0" "@elastic/request-crypto@2.0.1": version "2.0.1" @@ -1625,17 +1626,18 @@ version "0.0.0" uid "" -"@elastic/search-ui-app-search-connector@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@elastic/search-ui-app-search-connector/-/search-ui-app-search-connector-1.6.0.tgz#faf1c4a384285648ef7b5ef9cd0e65de0341d2b0" - integrity sha512-6oNvqzo4nuutmCM0zEzYrV6VwG8j0ML43SkaG6UrFzLUd6DeWUVGNN+SLNAlfQDWBUjc2m5EGvgdk/0GOWDZeA== +"@elastic/search-ui-app-search-connector@^1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@elastic/search-ui-app-search-connector/-/search-ui-app-search-connector-1.14.0.tgz#5ecd1157394b08f4281b890746450945413d582c" + integrity sha512-VwfbADt+PybgT+l2oK5gfW4WWHsf6al/5uk7qsYXtLneuckcjslUKzjlP5gHqAnV0/UKRXsYjjfb4WRDeo+iAw== dependencies: - "@elastic/app-search-javascript" "^7.13.1" + "@elastic/app-search-javascript" "^8.1.2" + "@elastic/search-ui" "1.14.0" -"@elastic/search-ui@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@elastic/search-ui/-/search-ui-1.6.0.tgz#8b2286cacff44735be96605b2929ca9b469c78de" - integrity sha512-i7htjET9uE4xngyzS8kX3DkSD5XNcr+3FS0Jjx3xRpKVc/dFst4bJyiSeRrQcq+2oBb4mEJJOCFaIrLZg3mdSA== +"@elastic/search-ui@1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@elastic/search-ui/-/search-ui-1.14.0.tgz#e5bb2854ffa2571294769ee435d69bda56dc414b" + integrity sha512-6Q+KrE5AhHs20rvWATxv3LKe1u/6t8c/pRV0tJXfsxenFer6d33PSEqPm7uV/paTha+5K8JlayWapwsRRWrVGQ== dependencies: date-fns "^1.30.1" deep-equal "^1.0.1" @@ -1708,18 +1710,6 @@ "@emotion/babel-plugin" "^11.2.0" "@emotion/babel-plugin-jsx-pragmatic" "^0.1.5" -"@emotion/babel-utils@^0.6.4": - version "0.6.10" - resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.10.tgz#83dbf3dfa933fae9fc566e54fbb45f14674c6ccc" - integrity sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow== - dependencies: - "@emotion/hash" "^0.6.6" - "@emotion/memoize" "^0.6.6" - "@emotion/serialize" "^0.9.1" - convert-source-map "^1.5.1" - find-root "^1.1.0" - source-map "^0.7.2" - "@emotion/cache@^10.0.27", "@emotion/cache@^10.0.9": version "10.0.29" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0" @@ -1730,6 +1720,17 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" +"@emotion/cache@^11.4.0", "@emotion/cache@^11.9.3": + version "11.9.3" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.9.3.tgz#96638449f6929fd18062cfe04d79b29b44c0d6cb" + integrity sha512-0dgkI/JKlCXa+lEXviaMtGBL0ynpx4osh7rjOXE71q9bIF8G+XhJgvi+wDu0B0IdCVx37BffiwXlN9I3UuzFvg== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/sheet" "^1.1.1" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + stylis "4.0.13" + "@emotion/cache@^11.7.1": version "11.7.1" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.7.1.tgz#08d080e396a42e0037848214e8aa7bf879065539" @@ -1786,11 +1787,6 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@emotion/hash@^0.6.2", "@emotion/hash@^0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.6.tgz#62266c5f0eac6941fece302abad69f2ee7e25e44" - integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ== - "@emotion/is-prop-valid@0.8.8", "@emotion/is-prop-valid@^0.8.6", "@emotion/is-prop-valid@^0.8.8": version "0.8.8" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" @@ -1814,16 +1810,24 @@ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== -"@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b" - integrity sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ== - "@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== +"@emotion/react@^11.8.1": + version "11.9.3" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.9.3.tgz#f4f4f34444f6654a2e550f5dab4f2d360c101df9" + integrity sha512-g9Q1GcTOlzOEjqwuLF/Zd9LC+4FljjPjDfxSM7KmEakm+hsHXk+bYZ2q+/hTJzr0OUNkujo72pXLQvXj6H+GJQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/babel-plugin" "^11.7.1" + "@emotion/cache" "^11.9.3" + "@emotion/serialize" "^1.0.4" + "@emotion/utils" "^1.1.0" + "@emotion/weak-memoize" "^0.2.5" + hoist-non-react-statics "^3.3.1" + "@emotion/react@^11.9.0": version "11.9.0" resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.9.0.tgz#b6d42b1db3bd7511e7a7c4151dc8bc82e14593b8" @@ -1848,16 +1852,6 @@ "@emotion/utils" "0.11.3" csstype "^2.5.7" -"@emotion/serialize@^0.9.1": - version "0.9.1" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.9.1.tgz#a494982a6920730dba6303eb018220a2b629c145" - integrity sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ== - dependencies: - "@emotion/hash" "^0.6.6" - "@emotion/memoize" "^0.6.6" - "@emotion/unitless" "^0.6.7" - "@emotion/utils" "^0.8.2" - "@emotion/serialize@^1.0.2", "@emotion/serialize@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.3.tgz#99e2060c26c6292469fb30db41f4690e1c8fea63" @@ -1869,6 +1863,17 @@ "@emotion/utils" "^1.0.0" csstype "^3.0.2" +"@emotion/serialize@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.4.tgz#ff31fd11bb07999611199c2229e152faadc21a3c" + integrity sha512-1JHamSpH8PIfFwAMryO2bNka+y8+KA5yga5Ocf2d7ZEiJjb7xlLW7aknBGZqJLajuLOvJ+72vN+IBSwPlXD1Pg== + dependencies: + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.4" + "@emotion/unitless" "^0.7.5" + "@emotion/utils" "^1.0.0" + csstype "^3.0.2" + "@emotion/sheet@0.9.4": version "0.9.4" resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" @@ -1879,6 +1884,11 @@ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.0.tgz#56d99c41f0a1cda2726a05aa6a20afd4c63e58d2" integrity sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g== +"@emotion/sheet@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.1.tgz#015756e2a9a3c7c5f11d8ec22966a8dbfbfac787" + integrity sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA== + "@emotion/styled-base@^10.0.27": version "10.0.31" resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.31.tgz#940957ee0aa15c6974adc7d494ff19765a2f742a" @@ -1902,31 +1912,16 @@ resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== -"@emotion/stylis@^0.7.0": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.7.1.tgz#50f63225e712d99e2b2b39c19c70fff023793ca5" - integrity sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ== - "@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4", "@emotion/unitless@^0.7.5": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@emotion/unitless@^0.6.2", "@emotion/unitless@^0.6.7": - version "0.6.7" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.6.7.tgz#53e9f1892f725b194d5e6a1684a7b394df592397" - integrity sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg== - "@emotion/utils@0.11.3": version "0.11.3" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== -"@emotion/utils@^0.8.2": - version "0.8.2" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc" - integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw== - "@emotion/utils@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af" @@ -7601,6 +7596,13 @@ dependencies: "@types/react" "*" +"@types/react-transition-group@^4.4.0": + version "4.4.5" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" + integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== + dependencies: + "@types/react" "*" + "@types/react-virtualized-auto-sizer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz#b3187dae1dfc4c15880c9cfc5b45f2719ea6ebd4" @@ -9524,24 +9526,6 @@ babel-plugin-emotion@^10.0.27: find-root "^1.1.0" source-map "^0.5.7" -babel-plugin-emotion@^9.2.11: - version "9.2.11" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz#319c005a9ee1d15bb447f59fe504c35fd5807728" - integrity sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@emotion/babel-utils" "^0.6.4" - "@emotion/hash" "^0.6.2" - "@emotion/memoize" "^0.6.1" - "@emotion/stylis" "^0.7.0" - babel-plugin-macros "^2.0.0" - babel-plugin-syntax-jsx "^6.18.0" - convert-source-map "^1.5.0" - find-root "^1.1.0" - mkdirp "^0.5.1" - source-map "^0.5.7" - touch "^2.0.1" - babel-plugin-extract-import-names@1.6.22: version "1.6.22" resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" @@ -11749,19 +11733,6 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-emotion@^9.2.12: - version "9.2.12" - resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-9.2.12.tgz#0fc8e7f92c4f8bb924b0fef6781f66b1d07cb26f" - integrity sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA== - dependencies: - "@emotion/hash" "^0.6.2" - "@emotion/memoize" "^0.6.1" - "@emotion/stylis" "^0.7.0" - "@emotion/unitless" "^0.6.2" - csstype "^2.5.2" - stylis "^3.5.0" - stylis-rule-sheet "^0.0.10" - create-hash@^1.1.0, create-hash@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" @@ -12146,11 +12117,6 @@ csstype@^2.2.0, csstype@^2.5.5, csstype@^2.5.7, csstype@^2.6.7: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== -csstype@^2.5.2: - version "2.6.14" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.14.tgz#004822a4050345b55ad4dcc00be1d9cf2f4296de" - integrity sha512-2mSc+VEpGPblzAxyeR+vZhJKgYg0Og0nnRi7pmRXFYYxSfnOnW8A5wwQb4n4cE2nIOzqKOAzLCaEX6aBmNEv8A== - csstype@^3.0.2: version "3.0.7" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b" @@ -13303,13 +13269,6 @@ dom-converter@~0.2: dependencies: utila "~0.4" -dom-helpers@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" - integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== - dependencies: - "@babel/runtime" "^7.1.2" - dom-helpers@^5.0.0, dom-helpers@^5.0.1: version "5.1.4" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.4.tgz#4609680ab5c79a45f2531441f1949b79d6587f4b" @@ -13726,14 +13685,6 @@ emotion-theming@^10.0.27: "@emotion/weak-memoize" "0.2.5" hoist-non-react-statics "^3.3.0" -emotion@^9.1.2: - version "9.2.12" - resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.12.tgz#53925aaa005614e65c6e43db8243c843574d1ea9" - integrity sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ== - dependencies: - babel-plugin-emotion "^9.2.11" - create-emotion "^9.2.12" - enabled@2.0.x: version "2.0.0" resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" @@ -24030,7 +23981,7 @@ raf-schd@^4.0.0, raf-schd@^4.0.2: resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0" integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ== -raf@^3.1.0, raf@^3.4.0, raf@^3.4.1: +raf@^3.1.0, raf@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== @@ -24352,13 +24303,6 @@ react-hook-form@^7.30.0: resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.30.0.tgz#c9e2fd54d3627e43bd94bf38ef549df2e80c1371" integrity sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ== -react-input-autosize@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2" - integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw== - dependencies: - prop-types "^15.5.8" - react-input-autosize@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" @@ -24620,19 +24564,6 @@ react-router@6.3.0, react-router@^6.0.0: dependencies: history "^5.2.0" -react-select@^2.4.4: - version "2.4.4" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-2.4.4.tgz#ba72468ef1060c7d46fbb862b0748f96491f1f73" - integrity sha512-C4QPLgy9h42J/KkdrpVxNmkY6p4lb49fsrbDk/hRcZpX7JvZPNb6mGj+c5SzyEtBv1DmQ9oPH4NmhAFvCrg8Jw== - dependencies: - classnames "^2.2.5" - emotion "^9.1.2" - memoize-one "^5.0.0" - prop-types "^15.6.0" - raf "^3.4.0" - react-input-autosize "^2.2.1" - react-transition-group "^2.2.1" - react-select@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.2.0.tgz#de9284700196f5f9b5277c5d850a9ce85f5c72fe" @@ -24647,6 +24578,19 @@ react-select@^3.2.0: react-input-autosize "^3.0.0" react-transition-group "^4.3.0" +react-select@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.3.2.tgz#ecee0d5c59ed4acb7f567f7de3c75a488d93dacb" + integrity sha512-W6Irh7U6Ha7p5uQQ2ZnemoCQ8mcfgOtHfw3wuMzG6FAu0P+CYicgofSLOq97BhjMx8jS+h+wwWdCBeVVZ9VqlQ== + dependencies: + "@babel/runtime" "^7.12.0" + "@emotion/cache" "^11.4.0" + "@emotion/react" "^11.8.1" + "@types/react-transition-group" "^4.4.0" + memoize-one "^5.0.0" + prop-types "^15.6.0" + react-transition-group "^4.3.0" + react-shortcuts@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/react-shortcuts/-/react-shortcuts-2.0.1.tgz#6de302244ce33ac9f9273dbeec540a8f81808f91" @@ -24733,16 +24677,6 @@ react-tiny-virtual-list@^2.2.0: dependencies: prop-types "^15.5.7" -react-transition-group@^2.2.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" - integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== - dependencies: - dom-helpers "^3.4.0" - loose-envify "^1.4.0" - prop-types "^15.6.2" - react-lifecycles-compat "^3.0.4" - react-transition-group@^4.3.0: version "4.4.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" @@ -26791,7 +26725,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.2, source-map@^0.7.3: +source-map@^0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== @@ -27601,11 +27535,6 @@ stylelint@13.8.0: v8-compile-cache "^2.2.0" write-file-atomic "^3.0.3" -stylis-rule-sheet@^0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" - integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== - stylis@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.0.tgz#016fa239663d77f868fef5b67cf201c4b7c701e1" @@ -27616,11 +27545,6 @@ stylis@4.0.13: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== -stylis@^3.5.0: - version "3.5.4" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" - integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== - subarg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" @@ -28310,13 +28234,6 @@ totalist@^1.0.0: resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== -touch@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/touch/-/touch-2.0.2.tgz#ca0b2a3ae3211246a61b16ba9e6cbf1596287164" - integrity sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A== - dependencies: - nopt "~1.0.10" - touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" From 4139ade5e2bd3e88784f8a76cdc8c444f89e8118 Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" Date: Tue, 5 Jul 2022 17:52:41 -0500 Subject: [PATCH 15/81] [Security Solution] fix endpoint tests (#135582) * [Security Solution] fix endpoint tests * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/security_solution/common/constants.ts | 5 +++++ .../common/endpoint/data_loaders/index_endpoint_hosts.ts | 8 -------- .../apps/endpoint/endpoint_list.ts | 6 +----- .../apps/endpoint/policy_list.ts | 3 +-- .../test/security_solution_endpoint/services/endpoint.ts | 8 +++++++- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 7f47e0d18059e..e4cd5b70ca65e 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -382,6 +382,11 @@ export const WARNING_TRANSFORM_STATES = new Set([ TRANSFORM_STATES.STOPPING, ]); +export const STARTED_TRANSFORM_STATES = new Set([ + TRANSFORM_STATES.INDEXING, + TRANSFORM_STATES.STARTED, +]); + /** * How many rules to update at a time is set to 50 from errors coming from * the slow environments such as cloud when the rule updates are > 100 we were diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts index 30d75b30a11b6..4b6722ba8d452 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts @@ -192,14 +192,6 @@ export async function indexEndpointHostDocs({ await indexEndpointAndFleetActionsForHost(client, hostMetadata, undefined); } - hostMetadata = { - ...hostMetadata, - // since the united transform uses latest metadata transform as a source - // there is an extra delay and fleet-agents gets populated much sooner. - // we manually add a delay to the time sync field so that the united transform - // will pick up the latest metadata doc. - '@timestamp': hostMetadata['@timestamp'] + 60000, - }; await client .index({ index: metadataIndex, diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index 469c9762611a8..81a1dc109b562 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -20,7 +20,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const testSubjects = getService('testSubjects'); const browser = getService('browser'); const endpointTestResources = getService('endpointTestResources'); - const policyTestResources = getService('policyTestResources'); const expectedData = [ [ @@ -72,8 +71,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { return tableData; }; - // Failing: See https://github.com/elastic/kibana/issues/114249 - describe.skip('endpoint list', function () { + describe('endpoint list', function () { const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms)); let indexedData: IndexedHostsAndAlertsResponse; describe('when initially navigating to page', () => { @@ -90,8 +88,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('when there is data,', () => { before(async () => { - const endpointPackage = await policyTestResources.getEndpointPackage(); - await endpointTestResources.setMetadataTransformFrequency('1s', endpointPackage.version); indexedData = await endpointTestResources.loadEndpointData({ numHosts: 3 }); await pageObjects.endpoint.navigateToEndpointList(); await pageObjects.endpoint.waitForTableToHaveNumberOfEntries('endpointListTable', 3, 90000); diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts index ccfccd8ce95a9..cdf22b9e43f5e 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts @@ -79,8 +79,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await backButton.click(); await pageObjects.policy.ensureIsOnListPage(); }); - // FLAKY: https://github.com/elastic/kibana/issues/131602 - describe.skip('when the endpoint count link is clicked', () => { + describe('when the endpoint count link is clicked', () => { it('navigates to the endpoint list page filtered by policy', async () => { const endpointCount = (await testSubjects.findAll('policyEndpointCountLink'))[0]; await endpointCount.click(); diff --git a/x-pack/test/security_solution_endpoint/services/endpoint.ts b/x-pack/test/security_solution_endpoint/services/endpoint.ts index d526c59ee6864..50e0b0821ec81 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint.ts @@ -23,6 +23,7 @@ import { GetTransformsResponseSchema } from '@kbn/transform-plugin/common/api_sc import { catchAndWrapError } from '@kbn/security-solution-plugin/server/endpoint/utils'; import { installOrUpgradeEndpointFleetPackage } from '@kbn/security-solution-plugin/common/endpoint/data_loaders/setup_fleet_for_endpoint'; import { EndpointError } from '@kbn/security-solution-plugin/common/endpoint/errors'; +import { STARTED_TRANSFORM_STATES } from '@kbn/security-solution-plugin/common/constants'; import { FtrService } from '../../functional/ftr_provider_context'; export class EndpointTestResources extends FtrService { @@ -89,11 +90,14 @@ export class EndpointTestResources extends FtrService { } private async startTransform(transformId: string) { - const transformsResponse = await this.esClient.transform.getTransform({ + const transformsResponse = await this.esClient.transform.getTransformStats({ transform_id: `${transformId}*`, }); return Promise.all( transformsResponse.transforms.map((transform) => { + if (STARTED_TRANSFORM_STATES.has(transform.state)) { + return Promise.resolve(); + } return this.esClient.transform.startTransform({ transform_id: transform.id }); }) ); @@ -137,6 +141,7 @@ export class EndpointTestResources extends FtrService { if (waitUntilTransformed) { // need this before indexing docs so that the united transform doesn't // create a checkpoint with a timestamp after the doc timestamps + await this.stopTransform(metadataTransformPrefix); await this.stopTransform(METADATA_UNITED_TRANSFORM); } @@ -158,6 +163,7 @@ export class EndpointTestResources extends FtrService { ); if (waitUntilTransformed) { + await this.startTransform(metadataTransformPrefix); const metadataIds = Array.from(new Set(indexedData.hosts.map((host) => host.agent.id))); await this.waitForEndpoints(metadataIds, waitTimeout); await this.startTransform(METADATA_UNITED_TRANSFORM); From 0a65f42928d61e642df279641323f2bce9d28301 Mon Sep 17 00:00:00 2001 From: Sandra G Date: Tue, 5 Jul 2022 17:25:18 -0700 Subject: [PATCH 16/81] [Unified Observability] update network fields (#134471) * update network fields * update tsvb charts to handle gauge correctly * update es aggs for rx/tx * handle missing values * update inventory threshold tests * revert unit tests field * change field to test counter field name Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../host/metrics/snapshot/rx.ts | 41 +++- .../host/metrics/snapshot/tx.ts | 41 +++- .../host/metrics/tsvb/host_network_traffic.ts | 92 +++++---- .../host/metrics/tsvb/host_system_overview.ts | 84 ++++---- .../infra/common/inventory_models/types.ts | 16 ++ .../create_formatter_for_metrics.test.ts | 4 +- .../helpers/create_tsvb_link.test.ts | 4 +- .../helpers/metric_to_format.test.ts | 4 +- .../create_metrics_aggregations.test.ts.snap | 2 +- .../lib/create_metrics_aggregations.test.ts | 2 +- .../plugins/infra/server/lib/metrics/types.ts | 6 + ...nvert_metric_to_metrics_api_metric.test.ts | 4 +- ...nvert_es_response_to_top_nodes_response.ts | 8 +- .../overview/lib/create_top_nodes_query.ts | 124 +++++++++++- .../apis/metrics_ui/constants.ts | 3 + .../metrics_ui/inventory_threshold_alert.ts | 15 +- .../infra/8.0.0/hosts_only/data.json.gz | Bin 4926 -> 6184 bytes .../infra/8.0.0/hosts_only/mappings.json | 184 +++++++++++++++++- 18 files changed, 520 insertions(+), 114 deletions(-) diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/rx.ts b/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/rx.ts index a050160789f96..d00d3aaa942cd 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/rx.ts +++ b/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/rx.ts @@ -5,9 +5,38 @@ * 2.0. */ -import { networkTrafficWithInterfaces } from '../../../shared/metrics/snapshot/network_traffic_with_interfaces'; -export const rx = networkTrafficWithInterfaces( - 'rx', - 'system.network.in.bytes', - 'system.network.name' -); +import { MetricsUIAggregation } from '../../../types'; +export const rx: MetricsUIAggregation = { + rx_avg: { + avg: { + field: 'host.network.ingress.bytes', + }, + }, + rx_period: { + filter: { + exists: { + field: 'host.network.ingress.bytes', + }, + }, + aggs: { + period: { + max: { + field: 'metricset.period', + }, + }, + }, + }, + rx: { + bucket_script: { + buckets_path: { + value: 'rx_avg', + period: 'rx_period>period', + }, + script: { + source: 'params.value / (params.period / 1000)', + lang: 'painless', + }, + gap_policy: 'skip', + }, + }, +}; diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/tx.ts b/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/tx.ts index e75e2110e832a..1d0ad172749b7 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/tx.ts +++ b/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/tx.ts @@ -5,9 +5,38 @@ * 2.0. */ -import { networkTrafficWithInterfaces } from '../../../shared/metrics/snapshot/network_traffic_with_interfaces'; -export const tx = networkTrafficWithInterfaces( - 'tx', - 'system.network.out.bytes', - 'system.network.name' -); +import { MetricsUIAggregation } from '../../../types'; +export const tx: MetricsUIAggregation = { + tx_avg: { + avg: { + field: 'host.network.egress.bytes', + }, + }, + tx_period: { + filter: { + exists: { + field: 'host.network.egress.bytes', + }, + }, + aggs: { + period: { + max: { + field: 'metricset.period', + }, + }, + }, + }, + tx: { + bucket_script: { + buckets_path: { + value: 'tx_avg', + period: 'tx_period>period', + }, + script: { + source: 'params.value / (params.period / 1000)', + lang: 'painless', + }, + gap_policy: 'skip', + }, + }, +}; diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_network_traffic.ts b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_network_traffic.ts index ec8c0937ce0ea..b3dfc5e91ba0a 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_network_traffic.ts +++ b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_network_traffic.ts @@ -23,50 +23,46 @@ export const hostNetworkTraffic: TSVBMetricModelCreator = ( id: 'tx', metrics: [ { - field: 'system.network.out.bytes', - id: 'max-net-out', - type: 'max', + field: 'host.network.egress.bytes', + id: 'avg-net-out', + type: 'avg', }, { - field: 'max-net-out', - id: 'deriv-max-net-out', - type: 'derivative', - unit: '1s', + id: 'max-period', + type: 'max', + field: 'metricset.period', }, { - id: 'posonly-deriv-max-net-out', + id: '3216b170-f192-11ec-a8e3-dd984b7213e2', type: 'calculation', - variables: [{ id: 'var-rate', name: 'rate', field: 'deriv-max-net-out' }], - script: 'params.rate > 0.0 ? params.rate : 0.0', - }, - { - function: 'sum', - id: 'seriesagg-sum', - type: 'series_agg', + variables: [ + { + id: '34e64c30-f192-11ec-a8e3-dd984b7213e2', + name: 'value', + field: 'avg-net-out', + }, + { + id: '3886cb80-f192-11ec-a8e3-dd984b7213e2', + name: 'period', + field: 'max-period', + }, + ], + script: 'params.value / (params.period / 1000)', }, ], - split_mode: 'terms', - terms_field: 'system.network.name', + filter: { + language: 'kuery', + query: 'host.network.egress.bytes : * ', + }, + split_mode: 'everything', }, { id: 'rx', metrics: [ { - field: 'system.network.in.bytes', - id: 'max-net-in', - type: 'max', - }, - { - field: 'max-net-in', - id: 'deriv-max-net-in', - type: 'derivative', - unit: '1s', - }, - { - id: 'posonly-deriv-max-net-in', - type: 'calculation', - variables: [{ id: 'var-rate', name: 'rate', field: 'deriv-max-net-in' }], - script: 'params.rate > 0.0 ? params.rate : 0.0', + field: 'host.network.ingress.bytes', + id: 'avg-net-in', + type: 'avg', }, { id: 'calc-invert-rate', @@ -74,20 +70,40 @@ export const hostNetworkTraffic: TSVBMetricModelCreator = ( type: 'calculation', variables: [ { - field: 'posonly-deriv-max-net-in', + field: 'avg-net-in', id: 'var-rate', name: 'rate', }, ], }, { - function: 'sum', - id: 'seriesagg-sum', - type: 'series_agg', + id: 'max-period', + type: 'max', + field: 'metricset.period', + }, + { + id: '3216b170-f192-11ec-a8e3-dd984b7213e2', + type: 'calculation', + variables: [ + { + id: '34e64c30-f192-11ec-a8e3-dd984b7213e2', + name: 'value', + field: 'calc-invert-rate', + }, + { + id: '3886cb80-f192-11ec-a8e3-dd984b7213e2', + name: 'period', + field: 'max-period', + }, + ], + script: 'params.value / (params.period / 1000)', }, ], - split_mode: 'terms', - terms_field: 'system.network.name', + filter: { + language: 'kuery', + query: 'host.network.ingress.bytes : * ', + }, + split_mode: 'everything', }, ], }); diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_system_overview.ts b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_system_overview.ts index eef480e12aab0..69ebd0aa35947 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_system_overview.ts +++ b/x-pack/plugins/infra/common/inventory_models/host/metrics/tsvb/host_system_overview.ts @@ -54,61 +54,77 @@ export const hostSystemOverview: TSVBMetricModelCreator = ( }, { id: 'rx', - split_mode: 'terms', - terms_field: 'system.network.name', metrics: [ { - field: 'system.network.in.bytes', - id: 'max-net-in', - type: 'max', + field: 'host.network.ingress.bytes', + id: 'avg-net-in', + type: 'avg', }, { - field: 'max-net-in', - id: 'deriv-max-net-in', - type: 'derivative', - unit: '1s', + id: 'max-period', + type: 'max', + field: 'metricset.period', }, { - id: 'posonly-deriv-max-net-in', + id: '3216b170-f192-11ec-a8e3-dd984b7213e2', type: 'calculation', - variables: [{ id: 'var-rate', name: 'rate', field: 'deriv-max-net-in' }], - script: 'params.rate > 0.0 ? params.rate : 0.0', - }, - { - function: 'sum', - id: 'seriesagg-sum', - type: 'series_agg', + variables: [ + { + id: '34e64c30-f192-11ec-a8e3-dd984b7213e2', + name: 'value', + field: 'avg-net-in', + }, + { + id: '3886cb80-f192-11ec-a8e3-dd984b7213e2', + name: 'period', + field: 'max-period', + }, + ], + script: 'params.value / (params.period / 1000)', }, ], + filter: { + language: 'kuery', + query: 'host.network.ingress.bytes : * ', + }, + split_mode: 'everything', }, { id: 'tx', - split_mode: 'terms', - terms_field: 'system.network.name', metrics: [ { - field: 'system.network.out.bytes', - id: 'max-net-out', - type: 'max', + field: 'host.network.egress.bytes', + id: 'avg-net-out', + type: 'avg', }, { - field: 'max-net-out', - id: 'deriv-max-net-out', - type: 'derivative', - unit: '1s', + id: 'max-period', + type: 'max', + field: 'metricset.period', }, { - id: 'posonly-deriv-max-net-out', + id: '3216b170-f192-11ec-a8e3-dd984b7213e2', type: 'calculation', - variables: [{ id: 'var-rate', name: 'rate', field: 'deriv-max-net-out' }], - script: 'params.rate > 0.0 ? params.rate : 0.0', - }, - { - function: 'sum', - id: 'seriesagg-sum', - type: 'series_agg', + variables: [ + { + id: '34e64c30-f192-11ec-a8e3-dd984b7213e2', + name: 'value', + field: 'avg-net-out', + }, + { + id: '3886cb80-f192-11ec-a8e3-dd984b7213e2', + name: 'period', + field: 'max-period', + }, + ], + script: 'params.value / (params.period / 1000)', }, ], + filter: { + language: 'kuery', + query: 'host.network.egress.bytes : * ', + }, + split_mode: 'everything', }, ], }); diff --git a/x-pack/plugins/infra/common/inventory_models/types.ts b/x-pack/plugins/infra/common/inventory_models/types.ts index 9384f2fb793c1..9e743425b14af 100644 --- a/x-pack/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/plugins/infra/common/inventory_models/types.ts @@ -288,6 +288,21 @@ export const ESTopMetricsAggRT = rt.type({ }), }); +export const ESMaxPeriodFilterExistsAggRT = rt.type({ + filter: rt.type({ + exists: rt.type({ + field: rt.string, + }), + }), + aggs: rt.type({ + period: rt.type({ + max: rt.type({ + field: rt.string, + }), + }), + }), +}); + export interface SnapshotTermsWithAggregation { terms: { field: string }; aggregations: MetricsUIAggregation; @@ -312,6 +327,7 @@ export const ESAggregationRT = rt.union([ ESTermsWithAggregationRT, ESCaridnalityAggRT, ESTopMetricsAggRT, + ESMaxPeriodFilterExistsAggRT, ]); export const MetricsUIAggregationRT = rt.record(rt.string, ESAggregationRT); diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_formatter_for_metrics.test.ts b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_formatter_for_metrics.test.ts index 02d2992b3be4b..eb59cdf28af1b 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_formatter_for_metrics.test.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_formatter_for_metrics.test.ts @@ -27,7 +27,7 @@ describe('createFormatterForMetric()', () => { it('should just work for rates', () => { const metric: MetricsExplorerMetric = { aggregation: 'rate', - field: 'system.network.out.bytes', + field: 'host.network.egress.bytes', }; const format = createFormatterForMetric(metric); expect(format(103929292)).toBe('831.4Mbit/s'); @@ -35,7 +35,7 @@ describe('createFormatterForMetric()', () => { it('should just work for bytes', () => { const metric: MetricsExplorerMetric = { aggregation: 'avg', - field: 'system.network.out.bytes', + field: 'host.network.egress.bytes', }; const format = createFormatterForMetric(metric); expect(format(103929292)).toBe('103.9MB'); diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts index 472e86200cba3..d3dfad0e4bbb0 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts @@ -42,14 +42,14 @@ describe('createTSVBLink()', () => { it('should work with rates', () => { const customOptions: MetricsExplorerOptions = { ...options, - metrics: [{ aggregation: 'rate', field: 'system.network.out.bytes' }], + metrics: [{ aggregation: 'rate', field: 'host.network.egress.bytes' }], }; const link = createTSVBLink(source, customOptions, series, timeRange, chartOptions); expect(link).toStrictEqual({ app: 'visualize', hash: '/create', search: { - _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#6092C0,fill:0,formatter:bytes,id:test-id,label:'rate(system.network.out.bytes)',line_width:2,metrics:!((field:system.network.out.bytes,id:test-id,type:max),(field:test-id,id:test-id,type:derivative,unit:'1s'),(field:test-id,id:test-id,type:positive_only)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}}/s)),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", + _a: "(filters:!(),linked:!f,query:(language:kuery,query:''),uiState:(),vis:(aggs:!(),params:(axis_formatter:number,axis_min:0,axis_position:left,axis_scale:normal,default_index_pattern:'metricbeat-*',filter:(language:kuery,query:'host.name : \"example-01\"'),id:test-id,index_pattern:'metricbeat-*',interval:auto,series:!((axis_position:right,chart_type:line,color:#6092C0,fill:0,formatter:bytes,id:test-id,label:'rate(host.network.egress.bytes)',line_width:2,metrics:!((field:host.network.egress.bytes,id:test-id,type:max),(field:test-id,id:test-id,type:derivative,unit:'1s'),(field:test-id,id:test-id,type:positive_only)),point_size:0,separate_axis:0,split_mode:everything,stacked:none,value_template:{{value}}/s)),show_grid:1,show_legend:1,time_field:'@timestamp',type:timeseries),title:example-01,type:metrics))", _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-1h,to:now))', type: 'metrics', }, diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/metric_to_format.test.ts b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/metric_to_format.test.ts index 567dcfff80e5c..be6a8d240e11e 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/metric_to_format.test.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/metric_to_format.test.ts @@ -16,14 +16,14 @@ describe('metricToFormat()', () => { it('should just work for byte metrics', () => { const metric: MetricsExplorerMetric = { aggregation: 'avg', - field: 'system.network.out.bytes', + field: 'host.network.egress.bytes', }; expect(metricToFormat(metric)).toBe(InfraFormatterType.bytes); }); it('should just work for rate bytes metrics', () => { const metric: MetricsExplorerMetric = { aggregation: 'rate', - field: 'system.network.out.bytes', + field: 'host.network.egress.bytes', }; expect(metricToFormat(metric)).toBe(InfraFormatterType.bits); }); diff --git a/x-pack/plugins/infra/server/lib/metrics/lib/__snapshots__/create_metrics_aggregations.test.ts.snap b/x-pack/plugins/infra/server/lib/metrics/lib/__snapshots__/create_metrics_aggregations.test.ts.snap index bbfe7e9cf0f9f..36e456c507f24 100644 --- a/x-pack/plugins/infra/server/lib/metrics/lib/__snapshots__/create_metrics_aggregations.test.ts.snap +++ b/x-pack/plugins/infra/server/lib/metrics/lib/__snapshots__/create_metrics_aggregations.test.ts.snap @@ -16,7 +16,7 @@ Object { }, "metric_1_max": Object { "max": Object { - "field": "system.network.in.bytes", + "field": "test.field.that.is.a.counter", }, }, } diff --git a/x-pack/plugins/infra/server/lib/metrics/lib/create_metrics_aggregations.test.ts b/x-pack/plugins/infra/server/lib/metrics/lib/create_metrics_aggregations.test.ts index 2e2d1736e5925..00b895ec19241 100644 --- a/x-pack/plugins/infra/server/lib/metrics/lib/create_metrics_aggregations.test.ts +++ b/x-pack/plugins/infra/server/lib/metrics/lib/create_metrics_aggregations.test.ts @@ -22,7 +22,7 @@ const options: MetricsAPIRequest = { { id: 'metric_1', aggregations: { - metric_1_max: { max: { field: 'system.network.in.bytes' } }, + metric_1_max: { max: { field: 'test.field.that.is.a.counter' } }, metric_1: { derivative: { buckets_path: 'metric_1_max', gap_policy: 'skip', unit: '1s' } }, }, }, diff --git a/x-pack/plugins/infra/server/lib/metrics/types.ts b/x-pack/plugins/infra/server/lib/metrics/types.ts index 82e174f4f94c1..cb2fefaf9b7e3 100644 --- a/x-pack/plugins/infra/server/lib/metrics/types.ts +++ b/x-pack/plugins/infra/server/lib/metrics/types.ts @@ -35,12 +35,18 @@ export const TopMetricsTypeRT = rt.type({ ), }); +export const MaxPeriodFilterExistsTypeRT = rt.type({ + doc_count: rt.number, + period: BasicMetricValueRT, +}); + export const MetricValueTypeRT = rt.union([ BasicMetricValueRT, NormalizedMetricValueRT, PercentilesTypeRT, PercentilesKeyedTypeRT, TopMetricsTypeRT, + MaxPeriodFilterExistsTypeRT, ]); export type MetricValueType = rt.TypeOf; diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.test.ts b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.test.ts index fbf7abc1c0530..6e391aeb45246 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.test.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.test.ts @@ -34,13 +34,13 @@ describe('convertMetricToMetricsAPIMetric(metric, index)', () => { runTestForBasic('cardinality'); runTest( - { aggregation: 'rate', field: 'system.network.in.bytes' }, + { aggregation: 'rate', field: 'test.field.that.is.a.counter' }, { id: 'metric_1', aggregations: { metric_1_max: { max: { - field: 'system.network.in.bytes', + field: 'test.field.that.is.a.counter', }, }, metric_1_deriv: { diff --git a/x-pack/plugins/infra/server/routes/overview/lib/convert_es_response_to_top_nodes_response.ts b/x-pack/plugins/infra/server/routes/overview/lib/convert_es_response_to_top_nodes_response.ts index c3b4693372db3..cf8227be460af 100644 --- a/x-pack/plugins/infra/server/routes/overview/lib/convert_es_response_to_top_nodes_response.ts +++ b/x-pack/plugins/infra/server/routes/overview/lib/convert_es_response_to_top_nodes_response.ts @@ -27,16 +27,16 @@ export const convertESResponseToTopNodesResponse = ( cpu: bucket.cpu.value, iowait: bucket.iowait.value, load: bucket.load.value, - rx: bucket.rx.value, - tx: bucket.tx.value, + rx: bucket.rx?.value || null, + tx: bucket.tx?.value || null, }; }), cpu: node.cpu.value, iowait: node.iowait.value, load: node.load.value, uptime: node.uptime.value, - rx: node.rx.value, - tx: node.tx.value, + rx: node.rx?.value || null, + tx: node.tx?.value || null, }; }), }; diff --git a/x-pack/plugins/infra/server/routes/overview/lib/create_top_nodes_query.ts b/x-pack/plugins/infra/server/routes/overview/lib/create_top_nodes_query.ts index a915a7882e231..20bf2324c29d1 100644 --- a/x-pack/plugins/infra/server/routes/overview/lib/create_top_nodes_query.ts +++ b/x-pack/plugins/infra/server/routes/overview/lib/create_top_nodes_query.ts @@ -75,14 +75,68 @@ export const createTopNodesQuery = ( field: 'system.load.15', }, }, + rx_avg: { + avg: { + field: 'host.network.ingress.bytes', + }, + }, + rx_period: { + filter: { + exists: { + field: 'host.network.ingress.bytes', + }, + }, + aggs: { + period: { + max: { + field: 'metricset.period', + }, + }, + }, + }, rx: { - sum: { - field: 'host.network.in.bytes', + bucket_script: { + buckets_path: { + value: 'rx_avg', + period: 'rx_period>period', + }, + script: { + source: 'params.value / (params.period / 1000)', + lang: 'painless', + }, + gap_policy: 'skip', + }, + }, + tx_avg: { + avg: { + field: 'host.network.egress.bytes', + }, + }, + tx_period: { + filter: { + exists: { + field: 'host.network.egress.bytes', + }, + }, + aggs: { + period: { + max: { + field: 'metricset.period', + }, + }, }, }, tx: { - sum: { - field: 'host.network.out.bytes', + bucket_script: { + buckets_path: { + value: 'tx_avg', + period: 'tx_period>period', + }, + script: { + source: 'params.value / (params.period / 1000)', + lang: 'painless', + }, + gap_policy: 'skip', }, }, timeseries: { @@ -110,16 +164,70 @@ export const createTopNodesQuery = ( field: 'system.load.15', }, }, - rx: { - rate: { + rx_avg: { + avg: { field: 'host.network.ingress.bytes', }, }, - tx: { - rate: { + rx_period: { + filter: { + exists: { + field: 'host.network.ingress.bytes', + }, + }, + aggs: { + period: { + max: { + field: 'metricset.period', + }, + }, + }, + }, + rx: { + bucket_script: { + buckets_path: { + value: 'rx_avg', + period: 'rx_period>period', + }, + script: { + source: 'params.value / (params.period / 1000)', + lang: 'painless', + }, + gap_policy: 'skip', + }, + }, + tx_avg: { + avg: { field: 'host.network.egress.bytes', }, }, + tx_period: { + filter: { + exists: { + field: 'host.network.egress.bytes', + }, + }, + aggs: { + period: { + max: { + field: 'metricset.period', + }, + }, + }, + }, + tx: { + bucket_script: { + buckets_path: { + value: 'tx_avg', + period: 'tx_period>period', + }, + script: { + source: 'params.value / (params.period / 1000)', + lang: 'painless', + }, + gap_policy: 'skip', + }, + }, }, }, }, diff --git a/x-pack/test/api_integration/apis/metrics_ui/constants.ts b/x-pack/test/api_integration/apis/metrics_ui/constants.ts index 9ef8c5e6b9407..b37b5b1ddd5da 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/constants.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/constants.ts @@ -27,6 +27,9 @@ export const DATES = { min: new Date('2022-01-18T19:57:47.534Z').getTime(), max: new Date('2022-01-18T20:02:50.043Z').getTime(), }, + rx: { + max: new Date('2022-06-21T17:02:00.00Z').getTime(), + }, logs_and_metrics: { min: 1562786660845, max: 1562786716965, diff --git a/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts b/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts index 230ae0e134f43..999a89926cf5c 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts @@ -136,6 +136,7 @@ export default function ({ getService }: FtrProviderContext) { it('should work FOR LAST 1 minute', async () => { const results = await evaluateCondition({ ...baseOptions, + executionTimestamp: new Date(DATES['8.0.0'].rx.max), condition: { ...baseCondition, metric: 'rx', @@ -155,7 +156,7 @@ export default function ({ getService }: FtrProviderContext) { shouldWarn: false, isNoData: false, isError: false, - currentValue: 1666.6666666666667, + currentValue: 79351.95, }, 'host-1': { metric: 'rx', @@ -168,13 +169,14 @@ export default function ({ getService }: FtrProviderContext) { shouldWarn: false, isNoData: false, isError: false, - currentValue: 2000, + currentValue: 10, }, }); }); it('should work with a long threshold', async () => { const results = await evaluateCondition({ ...baseOptions, + executionTimestamp: new Date(DATES['8.0.0'].rx.max), condition: { ...baseCondition, metric: 'rx', @@ -195,7 +197,7 @@ export default function ({ getService }: FtrProviderContext) { shouldWarn: false, isNoData: false, isError: false, - currentValue: 1666.6666666666667, + currentValue: 79351.95, }, 'host-1': { metric: 'rx', @@ -208,13 +210,14 @@ export default function ({ getService }: FtrProviderContext) { shouldWarn: false, isNoData: false, isError: false, - currentValue: 2000, + currentValue: 10, }, }); }); it('should work FOR LAST 5 minute', async () => { const options = { ...baseOptions, + executionTimestamp: new Date(DATES['8.0.0'].rx.max), condition: { ...baseCondition, metric: 'rx' as SnapshotMetricType, @@ -236,7 +239,7 @@ export default function ({ getService }: FtrProviderContext) { shouldWarn: false, isNoData: false, isError: false, - currentValue: 2266.6666666666665, + currentValue: 125658.70833333333, }, 'host-1': { metric: 'rx', @@ -249,7 +252,7 @@ export default function ({ getService }: FtrProviderContext) { shouldWarn: false, isNoData: false, isError: false, - currentValue: 2266.6666666666665, + currentValue: 11.666666666666668, }, }); }); diff --git a/x-pack/test/functional/es_archives/infra/8.0.0/hosts_only/data.json.gz b/x-pack/test/functional/es_archives/infra/8.0.0/hosts_only/data.json.gz index 217442c2cf338f2357d487a50558a2f5e7fab604..78dd0e435db16b0ae42136abf0285f193ba62a60 100644 GIT binary patch literal 6184 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 C8f Date: Wed, 6 Jul 2022 00:44:31 -0400 Subject: [PATCH 17/81] [api-docs] Daily api_docs build (#135769) --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/core.devdocs.json | 269 +----------------- api_docs/core.mdx | 2 +- api_docs/core_application.mdx | 2 +- api_docs/core_chrome.mdx | 2 +- api_docs/core_http.devdocs.json | 263 ++++++++++++++++- api_docs/core_http.mdx | 2 +- api_docs/core_saved_objects.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 2 +- api_docs/deprecations_by_plugin.mdx | 2 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/elastic_apm_synthtrace.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/fleet.devdocs.json | 41 +++ api_docs/fleet.mdx | 4 +- api_docs/global_search.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- api_docs/kbn_alerts.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_bazel_packages.mdx | 2 +- api_docs/kbn_bazel_runner.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- .../kbn_core_injected_metadata_browser.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_internal.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_home_sample_data_cards.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_kibana_json_schema.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_discovery.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_pm.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- .../kbn_scalability_simulation_generator.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_components.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- api_docs/kbn_shared_ux_services.mdx | 2 +- api_docs/kbn_shared_ux_storybook.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_sort_package_json.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_type_summarizer.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 8 +- api_docs/presentation_util.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/shared_u_x.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.devdocs.json | 34 +++ api_docs/triggers_actions_ui.mdx | 4 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 278 files changed, 620 insertions(+), 545 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 0a924b79e2fd5..04f9ca9848255 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github summary: API docs for the actions plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index d59a7ca9a6773..199f5754f28ae 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github summary: API docs for the advancedSettings plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 683238001eb31..93080b2ec47ae 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github summary: API docs for the aiops plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index bae41322adabc..27c34442b17ad 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github summary: API docs for the alerting plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 350d27e94c7e6..b678eed633f6e 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github summary: API docs for the apm plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 49c393c29ecec..2e6ec85089876 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github summary: API docs for the banners plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index c304d33271310..629e6211243fa 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github summary: API docs for the bfetch plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index dc0fb09c91d0e..8bccf44169b1b 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github summary: API docs for the canvas plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 67eb668c7d77c..bf0efc39f586f 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github summary: API docs for the cases plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 25996ac5e773a..2d197fa95403c 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github summary: API docs for the charts plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 549a4295ae5d5..ea204aa889b0c 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github summary: API docs for the cloud plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index e9573b9b887a6..c00155235b520 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github summary: API docs for the cloudSecurityPosture plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/console.mdx b/api_docs/console.mdx index acd0582278c34..c405baf17e096 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github summary: API docs for the console plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 22090e8c1d9a5..6fc30e4b6d501 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github summary: API docs for the controls plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core.devdocs.json b/api_docs/core.devdocs.json index f39f42b2dd3bd..b19e9cda96adb 100644 --- a/api_docs/core.devdocs.json +++ b/api_docs/core.devdocs.json @@ -2670,7 +2670,7 @@ "description": [ "\nA policy describing whether access to an external destination is allowed." ], - "path": "src/core/server/external_url/external_url_config.ts", + "path": "src/core/server/http/external_url/external_url_config.ts", "deprecated": false, "children": [ { @@ -2682,7 +2682,7 @@ "description": [ "\nIndicates if this policy allows or denies access to the described destination." ], - "path": "src/core/server/external_url/external_url_config.ts", + "path": "src/core/server/http/external_url/external_url_config.ts", "deprecated": false }, { @@ -2697,7 +2697,7 @@ "signature": [ "string | undefined" ], - "path": "src/core/server/external_url/external_url_config.ts", + "path": "src/core/server/http/external_url/external_url_config.ts", "deprecated": false }, { @@ -2712,7 +2712,7 @@ "signature": [ "string | undefined" ], - "path": "src/core/server/external_url/external_url_config.ts", + "path": "src/core/server/http/external_url/external_url_config.ts", "deprecated": false } ], @@ -8502,110 +8502,6 @@ }, "server": { "classes": [ - { - "parentPluginId": "core", - "id": "def-server.CspConfig", - "type": "Class", - "tags": [], - "label": "CspConfig", - "description": [ - "\nCSP configuration for use in Kibana." - ], - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.CspConfig", - "text": "CspConfig" - }, - " implements ", - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.ICspConfig", - "text": "ICspConfig" - } - ], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.CspConfig.DEFAULT", - "type": "Object", - "tags": [], - "label": "DEFAULT", - "description": [], - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.CspConfig", - "text": "CspConfig" - } - ], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.directives", - "type": "Object", - "tags": [], - "label": "#directives", - "description": [], - "signature": [ - "CspDirectives" - ], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.strict", - "type": "boolean", - "tags": [], - "label": "strict", - "description": [], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.warnLegacyBrowsers", - "type": "boolean", - "tags": [], - "label": "warnLegacyBrowsers", - "description": [], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.disableEmbedding", - "type": "boolean", - "tags": [], - "label": "disableEmbedding", - "description": [], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.header", - "type": "string", - "tags": [], - "label": "header", - "description": [], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "core", "id": "def-server.ElasticsearchConfig", @@ -15642,69 +15538,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "core", - "id": "def-server.ICspConfig", - "type": "Interface", - "tags": [], - "label": "ICspConfig", - "description": [ - "\nCSP configuration for use in Kibana." - ], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.ICspConfig.strict", - "type": "boolean", - "tags": [], - "label": "strict", - "description": [ - "\nSpecify whether browsers that do not support CSP should be\nable to use Kibana. Use `true` to block and `false` to allow." - ], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.ICspConfig.warnLegacyBrowsers", - "type": "boolean", - "tags": [], - "label": "warnLegacyBrowsers", - "description": [ - "\nSpecify whether users with legacy browsers should be warned\nabout their lack of Kibana security compliance." - ], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.ICspConfig.disableEmbedding", - "type": "boolean", - "tags": [], - "label": "disableEmbedding", - "description": [ - "\nWhether or not embedding (using iframes) should be allowed by the CSP. If embedding is disabled, a restrictive 'frame-ancestors' rule will be added to the default CSP rules." - ], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.ICspConfig.header", - "type": "string", - "tags": [], - "label": "header", - "description": [ - "\nThe CSP rules in a formatted directives string for use\nin a `Content-Security-Policy` header." - ], - "path": "src/core/server/csp/csp_config.ts", - "deprecated": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "core", "id": "def-server.ICustomClusterClient", @@ -15799,100 +15632,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "core", - "id": "def-server.IExternalUrlConfig", - "type": "Interface", - "tags": [], - "label": "IExternalUrlConfig", - "description": [ - "\nExternal Url configuration for use in Kibana." - ], - "path": "src/core/server/external_url/external_url_config.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.IExternalUrlConfig.policy", - "type": "Array", - "tags": [], - "label": "policy", - "description": [ - "\nA set of policies describing which external urls are allowed." - ], - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.IExternalUrlPolicy", - "text": "IExternalUrlPolicy" - }, - "[]" - ], - "path": "src/core/server/external_url/external_url_config.ts", - "deprecated": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "core", - "id": "def-server.IExternalUrlPolicy", - "type": "Interface", - "tags": [], - "label": "IExternalUrlPolicy", - "description": [ - "\nA policy describing whether access to an external destination is allowed." - ], - "path": "src/core/server/external_url/external_url_config.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.IExternalUrlPolicy.allow", - "type": "boolean", - "tags": [], - "label": "allow", - "description": [ - "\nIndicates if this policy allows or denies access to the described destination." - ], - "path": "src/core/server/external_url/external_url_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.IExternalUrlPolicy.host", - "type": "string", - "tags": [], - "label": "host", - "description": [ - "\nOptional host describing the external destination.\nMay be combined with `protocol`.\n" - ], - "signature": [ - "string | undefined" - ], - "path": "src/core/server/external_url/external_url_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.IExternalUrlPolicy.protocol", - "type": "string", - "tags": [], - "label": "protocol", - "description": [ - "\nOptional protocol describing the external destination.\nMay be combined with `host`.\n" - ], - "signature": [ - "string | undefined" - ], - "path": "src/core/server/external_url/external_url_config.ts", - "deprecated": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "core", "id": "def-server.IntervalHistogram", diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 211be1d7b3378..da5ea0d7edabe 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github summary: API docs for the core plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core_application.mdx b/api_docs/core_application.mdx index 1f96f2c27d492..59dba6cd8a38c 100644 --- a/api_docs/core_application.mdx +++ b/api_docs/core_application.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-application title: "core.application" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.application plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.application'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core_chrome.mdx b/api_docs/core_chrome.mdx index 013887c1e6bc9..8b5253145facb 100644 --- a/api_docs/core_chrome.mdx +++ b/api_docs/core_chrome.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-chrome title: "core.chrome" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.chrome plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.chrome'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core_http.devdocs.json b/api_docs/core_http.devdocs.json index fc0ff622cc4aa..4ebe6e418a508 100644 --- a/api_docs/core_http.devdocs.json +++ b/api_docs/core_http.devdocs.json @@ -2247,6 +2247,110 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig", + "type": "Class", + "tags": [], + "label": "CspConfig", + "description": [ + "\nCSP configuration for use in Kibana." + ], + "signature": [ + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.CspConfig", + "text": "CspConfig" + }, + " implements ", + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.ICspConfig", + "text": "ICspConfig" + } + ], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.CspConfig.DEFAULT", + "type": "Object", + "tags": [], + "label": "DEFAULT", + "description": [], + "signature": [ + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.CspConfig", + "text": "CspConfig" + } + ], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.directives", + "type": "Object", + "tags": [], + "label": "#directives", + "description": [], + "signature": [ + "CspDirectives" + ], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.strict", + "type": "boolean", + "tags": [], + "label": "strict", + "description": [], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.warnLegacyBrowsers", + "type": "boolean", + "tags": [], + "label": "warnLegacyBrowsers", + "description": [], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.disableEmbedding", + "type": "boolean", + "tags": [], + "label": "disableEmbedding", + "description": [], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.header", + "type": "string", + "tags": [], + "label": "header", + "description": [], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "core", "id": "def-server.RouteValidationError", @@ -3604,7 +3708,7 @@ { "pluginId": "core", "scope": "server", - "docId": "kibCorePluginApi", + "docId": "kibCoreHttpPluginApi", "section": "def-server.ICspConfig", "text": "ICspConfig" } @@ -3845,6 +3949,163 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "core", + "id": "def-server.ICspConfig", + "type": "Interface", + "tags": [], + "label": "ICspConfig", + "description": [ + "\nCSP configuration for use in Kibana." + ], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.ICspConfig.strict", + "type": "boolean", + "tags": [], + "label": "strict", + "description": [ + "\nSpecify whether browsers that do not support CSP should be\nable to use Kibana. Use `true` to block and `false` to allow." + ], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.ICspConfig.warnLegacyBrowsers", + "type": "boolean", + "tags": [], + "label": "warnLegacyBrowsers", + "description": [ + "\nSpecify whether users with legacy browsers should be warned\nabout their lack of Kibana security compliance." + ], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.ICspConfig.disableEmbedding", + "type": "boolean", + "tags": [], + "label": "disableEmbedding", + "description": [ + "\nWhether or not embedding (using iframes) should be allowed by the CSP. If embedding is disabled, a restrictive 'frame-ancestors' rule will be added to the default CSP rules." + ], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.ICspConfig.header", + "type": "string", + "tags": [], + "label": "header", + "description": [ + "\nThe CSP rules in a formatted directives string for use\nin a `Content-Security-Policy` header." + ], + "path": "src/core/server/http/csp/csp_config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "core", + "id": "def-server.IExternalUrlConfig", + "type": "Interface", + "tags": [], + "label": "IExternalUrlConfig", + "description": [ + "\nExternal Url configuration for use in Kibana." + ], + "path": "src/core/server/http/external_url/external_url_config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.IExternalUrlConfig.policy", + "type": "Array", + "tags": [], + "label": "policy", + "description": [ + "\nA set of policies describing which external urls are allowed." + ], + "signature": [ + { + "pluginId": "core", + "scope": "server", + "docId": "kibCoreHttpPluginApi", + "section": "def-server.IExternalUrlPolicy", + "text": "IExternalUrlPolicy" + }, + "[]" + ], + "path": "src/core/server/http/external_url/external_url_config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "core", + "id": "def-server.IExternalUrlPolicy", + "type": "Interface", + "tags": [], + "label": "IExternalUrlPolicy", + "description": [ + "\nA policy describing whether access to an external destination is allowed." + ], + "path": "src/core/server/http/external_url/external_url_config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.IExternalUrlPolicy.allow", + "type": "boolean", + "tags": [], + "label": "allow", + "description": [ + "\nIndicates if this policy allows or denies access to the described destination." + ], + "path": "src/core/server/http/external_url/external_url_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.IExternalUrlPolicy.host", + "type": "string", + "tags": [], + "label": "host", + "description": [ + "\nOptional host describing the external destination.\nMay be combined with `protocol`.\n" + ], + "signature": [ + "string | undefined" + ], + "path": "src/core/server/http/external_url/external_url_config.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.IExternalUrlPolicy.protocol", + "type": "string", + "tags": [], + "label": "protocol", + "description": [ + "\nOptional protocol describing the external destination.\nMay be combined with `host`.\n" + ], + "signature": [ + "string | undefined" + ], + "path": "src/core/server/http/external_url/external_url_config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "core", "id": "def-server.IKibanaResponse", diff --git a/api_docs/core_http.mdx b/api_docs/core_http.mdx index fa0e5038f9e8d..947cc08e7e47b 100644 --- a/api_docs/core_http.mdx +++ b/api_docs/core_http.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-http title: "core.http" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.http plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.http'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/core_saved_objects.mdx b/api_docs/core_saved_objects.mdx index 48b69e88f01bb..c5cc9e4958475 100644 --- a/api_docs/core_saved_objects.mdx +++ b/api_docs/core_saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-savedObjects title: "core.savedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.savedObjects plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.savedObjects'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 70e8d78a3de87..1aa61bc8552ac 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github summary: API docs for the customIntegrations plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index fbbb35e8c581d..78788da6d10ba 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github summary: API docs for the dashboard plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 0770925dc334f..0c683f0f80417 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the dashboardEnhanced plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 665c772321923..6ee260e779293 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github summary: API docs for the data plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 35e12e5b6fb33..bf4dd1d71c209 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github summary: API docs for the data.query plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index a3c2313510964..e0bf9eef25329 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github summary: API docs for the data.search plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 2e2bd6c6fb2b3..22b8161ff87ce 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewEditor plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 3ebc2d5a5a97a..942eb15ebbadb 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewFieldEditor plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index 75c622ae5abdb..1fa3724cf0471 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewManagement plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index a9007c3295dc1..1bb3924c6e5da 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViews plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 1b4a297a8aca0..6fedfd95d76a4 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataVisualizer plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index d5e64b08332e4..446aaf0f930b0 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -3,7 +3,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API summary: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 0bb265e66bd40..f590bc331147e 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -3,7 +3,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin summary: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 233abd8838f1e..1df23cc4d4b58 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -3,7 +3,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team summary: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 698f790a3a66e..8ce7e65ab6325 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github summary: API docs for the devTools plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 7eed6b5a74359..f90a52f366500 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github summary: API docs for the discover plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 11cd7bdab2f25..61f5521a27e7e 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the discoverEnhanced plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/elastic_apm_synthtrace.mdx b/api_docs/elastic_apm_synthtrace.mdx index 4cf2aea8c4c65..d391636a2bad8 100644 --- a/api_docs/elastic_apm_synthtrace.mdx +++ b/api_docs/elastic_apm_synthtrace.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/elastic-apm-synthtrace title: "@elastic/apm-synthtrace" image: https://source.unsplash.com/400x175/?github summary: API docs for the @elastic/apm-synthtrace plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@elastic/apm-synthtrace'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 88f836dfe2cfa..36b9052aee012 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github summary: API docs for the embeddable plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index aa1690823ca17..5560476a596dc 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the embeddableEnhanced plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 375f8d5fc10eb..34e642535c698 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the encryptedSavedObjects plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 84242c541fba2..bc14ca5e07344 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github summary: API docs for the enterpriseSearch plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 2b6f39a07750f..daadef372bb4e 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github summary: API docs for the esUiShared plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 57cd28af43b70..baae0aec38a74 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github summary: API docs for the eventAnnotation plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 1dc589faadc84..a5c81ba0af217 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github summary: API docs for the eventLog plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index eaf691a042530..a4f843cde4f00 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionError plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index c2f057c4cde16..ba4f9b251af0d 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionGauge plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 794ec314f90f0..365063c480e4f 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionHeatmap plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index b72c6116e61a7..5580fe7c9863d 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionImage plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 76d6c48f79d84..3435762ee052e 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionMetric plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 8ffd404412284..14dbc595db99c 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionMetricVis plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index c98b791b69409..628b9e067b640 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionPartitionVis plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 7043bffddd6c5..8051dff3eb460 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionRepeatImage plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 330c820f403e2..a8ffc816b0dd3 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionRevealImage plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 2bd5b14a359ee..f810684e92c1f 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionShape plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 6b6448d1b0543..9b528815a1b2d 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionTagcloud plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 000a4755237e5..e1bf00bf73f83 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionXY plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index e60a916d90d02..c0ffd62c9a602 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressions plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 5e9fc577a6949..f963ffb3e5d87 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github summary: API docs for the features plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index b0ccf0e0b8184..59c0afd9afa1d 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github summary: API docs for the fieldFormats plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 10a8637b1530e..75c66970bc3b7 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github summary: API docs for the fileUpload plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 6911a3ccadf82..0dd6660ad8283 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -17633,6 +17633,32 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-common.PostBulkUpdateAgentTagsRequest", + "type": "Interface", + "tags": [], + "label": "PostBulkUpdateAgentTagsRequest", + "description": [], + "path": "x-pack/plugins/fleet/common/types/rest_spec/agent.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-common.PostBulkUpdateAgentTagsRequest.body", + "type": "Object", + "tags": [], + "label": "body", + "description": [], + "signature": [ + "{ agents: string | string[]; tagsToAdd?: string[] | undefined; tagsToRemove?: string[] | undefined; }" + ], + "path": "x-pack/plugins/fleet/common/types/rest_spec/agent.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-common.PostDownloadSourceRequest", @@ -23542,6 +23568,21 @@ ], "returnComment": [] }, + { + "parentPluginId": "fleet", + "id": "def-common.agentRouteService.getBulkUpdateTagsPath", + "type": "Function", + "tags": [], + "label": "getBulkUpdateTagsPath", + "description": [], + "signature": [ + "() => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-common.agentRouteService.getUnenrollPath", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index ba7cbd4908772..b192deae3031f 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github summary: API docs for the fleet plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1504 | 8 | 1373 | 10 | +| 1507 | 8 | 1376 | 10 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index bb56934aab8d1..3ddab3812d2db 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github summary: API docs for the globalSearch plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/home.mdx b/api_docs/home.mdx index f78ddd08e73ba..df4c044b05df3 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github summary: API docs for the home plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 31ff9d3cff3be..33616b041586c 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the indexLifecycleManagement plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 17fd7a713acf2..e4ba1df16728b 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the indexManagement plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 6bfe34f47104e..c4ddc3007c1b5 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github summary: API docs for the infra plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index ac939ab560e1b..3d33f589d6ce7 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github summary: API docs for the inspector plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index aa5e4ec412856..40a6094137255 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github summary: API docs for the interactiveSetup plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index cb24c054644a7..7cd9e39ac0437 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ace plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index e5b0089376945..b25f7bdcb84a5 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/aiops-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index ebeee5bd01264..17b50aa0711f0 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/alerts plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index f7b6ceaedf7c9..decd43831cdf9 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 6687f03554de5..211931f3b03a6 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics-client plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 0bfb58c382899..662941ef39760 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index da4ef5d94d81e..c36bebac0f37f 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 5799ad575960c..9f13944078587 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 664bc45c94908..53706eb4724dc 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 33272b97afa21..b20b0a24c7a6a 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/apm-config-loader plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index f48270a33f010..c2a1860b21084 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/apm-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index eb08c111ee69d..d9754c5f9e701 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/axe-config plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_bazel_packages.mdx b/api_docs/kbn_bazel_packages.mdx index cdec0abf52511..98aa3508ce66d 100644 --- a/api_docs/kbn_bazel_packages.mdx +++ b/api_docs/kbn_bazel_packages.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-bazel-packages title: "@kbn/bazel-packages" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/bazel-packages plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bazel-packages'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_bazel_runner.mdx b/api_docs/kbn_bazel_runner.mdx index 0a1c22790a6ad..988c2c46252df 100644 --- a/api_docs/kbn_bazel_runner.mdx +++ b/api_docs/kbn_bazel_runner.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-bazel-runner title: "@kbn/bazel-runner" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/bazel-runner plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bazel-runner'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index e89105feaa576..a8eb97543b062 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ci-stats-core plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index d31507fb2e8a9..d4ed4a0929dc3 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 508cc8f5b5089..c516383cd90e1 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index ee45e492874f6..302ba48109cd3 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/cli-dev-mode plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 911828986be89..b68294b3ee9ef 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/coloring plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index e1e118cef2d25..f24a37234c2c0 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/config plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 8dbcff899bcc9..0fb8ff62f267c 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/config-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 33901667623f1..b5227b1eb6129 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/config-schema plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index e9eb480842904..969b8f79a6f52 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-browser plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 5ce99ef3d822e..97df49033eae2 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 8f0646b7067df..2c8ea1d913ef1 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 718feb6d481a8..51a54e0659af4 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-server plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 81be2b6954c9d..84ca0a89363de 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 572dbecd470e7..56bb0f675ca82 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 784233e669604..2f267b9fdb727 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 9e789297e2f14..ad30b6a95f8d9 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-base-common plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index a16c10cf715ab..9336dc8d8d8c9 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-base-server-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index b12145fbbc5f1..76710bf1f3f50 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 33b7cfb3755c1..91836e415961c 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-config-server-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 7233a10e0d9b0..73ad8060f9599 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index b21b02a30722c..160f43a949c1a 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 2076cf554bd20..3a5d74756aaaf 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-doc-links-server plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 7a4fa2289d87a..7f8fb970a154c 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 63f5e7981b598..b4d9e045aa0fc 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index bd7b5dca84f06..77064390b0217 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 59336f0413474..43ee9e94cc7b6 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 3b54937d8e600..ee7ff4a212f72 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 57ffba13bef8d..d71e18396cba5 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 1feb3263b4fb1..03391226485b4 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-common plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 51b5f3b344ced..979795a6613be 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-server plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index dca45d9a7be1d..cd953e59475b4 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 393d8e474cd15..d95811927b648 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index d9c3d6d69680b..226c12e58c2d5 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 279ce15f26988..44f0b95114045 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index d7b1b1a50c438..55e4bcc4e326f 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-i18n-browser plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 9f1affe365f3f..7a5df7bfffe5f 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index 8ae7f64551bfe..19369bb16a483 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 9e79ca40deb2c..fe22478b9809a 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index c65b6dd74aea4..ec69a22d153f8 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-logging-server plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index f8d76eed39f29..7a456df71b973 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index d23c1744baf94..21db6bf6444bb 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index d121bf530bcea..e61d41464d10d 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-node-server plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 6f61e236c48b4..1ee47b2ccf6bb 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-node-server-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 6a8ca1c3641ac..2b2a55ecf8ce7 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 843a4a5b790b0..6c6c7cc8dc744 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-theme-browser plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 275bf092dae6d..436e4a7c461c7 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 05755e17ea9e5..03501941aae29 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index c0ac3b48435c0..631bf1cc7ef3f 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/crypto plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index d64a233d17d34..944e5ebbb4efa 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/datemath plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 389efa73e7c16..f1609c09345bd 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-cli-errors plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index 9c6705a22836f..475a0376686b6 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-cli-runner plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index eaa943f59a848..c70bc93d9aa6b 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-proc-runner plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index da519febef9a7..35c3b9e57733c 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 96a82bbafe558..7a06065346c5d 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/doc-links plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 9a7ac412650ef..62938d41446fa 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/docs-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index ed96e0abd72b6..3457981b014bd 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/es-archiver plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 4c908787f3277..809e2c147b481 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/es-errors plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index c07adc2d51210..1b7a7cab7c1eb 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/es-query plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 6506b3f4084dc..42ca4fbcf97d2 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 363633710fe2a..f13cc97778342 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/field-types plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 22b35802f36da..8e1ef9fcd033b 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/find-used-node-modules plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 38c4acf6b2786..44179a295e876 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/generate plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index ce37ecba885a6..9c02ce4e41aa3 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/handlebars plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_home_sample_data_cards.mdx b/api_docs/kbn_home_sample_data_cards.mdx index b7627c54ac784..9691209561650 100644 --- a/api_docs/kbn_home_sample_data_cards.mdx +++ b/api_docs/kbn_home_sample_data_cards.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-cards title: "@kbn/home-sample-data-cards" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/home-sample-data-cards plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-cards'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index b6879eb47a17a..b49d301a842af 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/i18n plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 6b42e8d7e28fa..ecab00f2ec793 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/import-resolver plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 87ec6df6e300b..4b8dc90c7dec5 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/interpreter plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index f86f58c63a59e..284e6350bd5df 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/io-ts-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 9bbe9109ba0a0..fc2de0cdb66fb 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/jest-serializers plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_kibana_json_schema.mdx b/api_docs/kbn_kibana_json_schema.mdx index 4550d0e5915ed..81d81d1855d21 100644 --- a/api_docs/kbn_kibana_json_schema.mdx +++ b/api_docs/kbn_kibana_json_schema.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-json-schema title: "@kbn/kibana-json-schema" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/kibana-json-schema plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-json-schema'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 67c2d6bea3653..dbc438c03341e 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/logging plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index 3ab79e27c0c60..b3ed256c7192d 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/logging-mocks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 74ad735224c02..7551c2bd00ee7 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/mapbox-gl plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 3339d2245c640..c1dea751a9dff 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ml-agg-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 6567afd0f21d2..da0e2f46294e8 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 833ccbeadc4ae..56c2e5172f20f 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ml-string-hash plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 71cab510fe3f3..62297303e8a03 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/monaco plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 56fa75eba229b..a73dde4d99eaf 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/optimizer plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index d86a3980763fd..0f91cfa1e510e 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index bff3ae05911b8..7f2224296f1cb 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_plugin_discovery.mdx b/api_docs/kbn_plugin_discovery.mdx index c0a762ecf9b8f..74a30558e3a05 100644 --- a/api_docs/kbn_plugin_discovery.mdx +++ b/api_docs/kbn_plugin_discovery.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-discovery title: "@kbn/plugin-discovery" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/plugin-discovery plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-discovery'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 285a98781a8f3..d5ae5eb1f1285 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/plugin-generator plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index a09ee10759cfd..51b5ac5bc566f 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/plugin-helpers plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_pm.mdx b/api_docs/kbn_pm.mdx index c982ed1d9b9ff..3729e9ea7f833 100644 --- a/api_docs/kbn_pm.mdx +++ b/api_docs/kbn_pm.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-pm title: "@kbn/pm" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/pm plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/pm'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index ab57294d3b379..467d3034887e1 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/react-field plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 4bd73993e5fbf..755a53f297d37 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/rule-data-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_scalability_simulation_generator.mdx b/api_docs/kbn_scalability_simulation_generator.mdx index 42b50c9773685..24e04ac438ecf 100644 --- a/api_docs/kbn_scalability_simulation_generator.mdx +++ b/api_docs/kbn_scalability_simulation_generator.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-scalability-simulation-generator title: "@kbn/scalability-simulation-generator" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/scalability-simulation-generator plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/scalability-simulation-generator'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index fc90e5bcee92c..8484887a31c2b 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 429e83fb9c392..2b9d21d13eba1 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 2eda3fabac37e..14e04dc857d48 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 1764e7cad9bd8..b2a0e88fff7b4 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 204ce7082c48a..6f47890135dd0 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index eca2bcb1b9d4a..8290c28cac588 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 4a279fb95329a..f856e2ea64e27 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 1c54bfbb7f7d8..856716ef398ea 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 0f20c516c4a8d..670f8cb73b577 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index c9fad43c88be7..a4ac0a06b205c 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 0df5bb208a314..f2205153b32eb 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index b5966bcf154b8..2b391df114146 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-rules plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 56884e924d78d..162aa7f25ccba 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index b1bbc46eb4864..18c22236a6d49 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index c97136ba98558..35732273a0c5c 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/server-http-tools plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index 02e9123052c67..f69b178f6c7a6 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/server-route-repository plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 9cf65d1038f50..3bc1baeeab5d6 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 4922f34a73fb5..1f8d06dd7711d 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_components.mdx b/api_docs/kbn_shared_ux_components.mdx index af8e5bca17492..f319a53932165 100644 --- a/api_docs/kbn_shared_ux_components.mdx +++ b/api_docs/kbn_shared_ux_components.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-components title: "@kbn/shared-ux-components" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-components plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-components'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 61d1eb574d2c5..49ac6de5bfd54 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 3cbfbe9930e50..f932782b55544 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 2af348609e793..1e5da8978d010 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_services.mdx b/api_docs/kbn_shared_ux_services.mdx index da467990cec1f..e98fdbe2d4d69 100644 --- a/api_docs/kbn_shared_ux_services.mdx +++ b/api_docs/kbn_shared_ux_services.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-services title: "@kbn/shared-ux-services" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-services plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-services'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_storybook.mdx b/api_docs/kbn_shared_ux_storybook.mdx index c0321d296e3b2..45a24ea0557f6 100644 --- a/api_docs/kbn_shared_ux_storybook.mdx +++ b/api_docs/kbn_shared_ux_storybook.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook title: "@kbn/shared-ux-storybook" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-storybook plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 5bc0e03238416..a6897a35366c2 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-utility plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 77ba686ced3d9..87a32318a54ee 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/sort-package-json plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index e435a855b837a..6fcc96144da31 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/std plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 4ad2206eea1e1..d149288c5732e 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index e7fcb59e4724c..e0adca7a0527b 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/storybook plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 98c8869ae67b1..81f3423c5584b 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/telemetry-tools plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 8aba0f58df7d2..83bd1549b9ba9 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/test plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index f58aec72ec08a..dc478829f98fd 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/test-jest-helpers plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 436e53f0db236..eb0237e803b85 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/tooling-log plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index b00e99fde2a56..634ff34528bfb 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/type-summarizer plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 808fde2273983..7169543f3382f 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/typed-react-router-config plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 67aadc6dc4949..5232b9e07c4f3 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ui-theme plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 6f6d672dbfe6c..8be4156d2f278 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/utility-types plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index dc57ff2d642f9..e7a7ab1c8eaf1 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/utility-types-jest plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index d662d10ef9331..c34a37871a51e 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/utils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 4e05c25956716..aef48f2580bde 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaOverview plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 1786cc7e1b8b9..c4aa59e237fac 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaReact plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index d4efa5c9c12cd..83bd62eec10e6 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaUtils plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index e740547d9ec8d..8ff70feb36159 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github summary: API docs for the kubernetesSecurity plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 90073104e1837..fcde25d9295d0 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github summary: API docs for the lens plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 188fb92655655..4050ddb6ee5bd 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github summary: API docs for the licenseApiGuard plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index d9d715e1dd54e..8a5986a0fdbcf 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the licenseManagement plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 5a06cb5ece3f8..0699001394491 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github summary: API docs for the licensing plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index a0fe3a48add5f..fc51a1a732713 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github summary: API docs for the lists plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 4e5486368b8f8..7238ff68bd718 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github summary: API docs for the management plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index c0eaf26d90d59..e69797822beb9 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github summary: API docs for the maps plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 1b0953f07fd2f..d8e4febe0e6c3 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github summary: API docs for the mapsEms plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index ae1cebce4ed8f..cd25395e3a411 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github summary: API docs for the ml plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index c8e49f240a2db..1f6ac23c046b9 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github summary: API docs for the monitoring plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index 5d839a40cdde2..caa692af3b816 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github summary: API docs for the monitoringCollection plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 98c82a538a92f..599199ffee16d 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github summary: API docs for the navigation plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index c3fa1c1fba316..114f930713ce3 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github summary: API docs for the newsfeed plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index f180f03f5341e..7700cb35cba3a 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github summary: API docs for the observability plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index f923d8259a065..0e7b12ed742cd 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github summary: API docs for the osquery plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index b9cc3c43f28e7..759bc1d69a28d 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -3,7 +3,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory summary: Directory of public APIs available through plugins or packages. -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 26667 | 172 | 19266 | 1279 | +| 26672 | 172 | 19271 | 1280 | ## Plugin Directory @@ -75,7 +75,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 222 | 0 | 95 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 288 | 5 | 249 | 3 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1504 | 8 | 1373 | 10 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1507 | 8 | 1376 | 10 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | globalSearchProviders | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | @@ -141,7 +141,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 452 | 1 | 347 | 35 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [Kibana Localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 388 | 0 | 374 | 36 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 390 | 0 | 376 | 37 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds UI Actions service to Kibana | 130 | 0 | 91 | 11 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 205 | 0 | 142 | 9 | | | [Unified Search](https://github.com/orgs/elastic/teams/kibana-app-services) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 82 | 2 | 78 | 13 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 92bc063049bcf..a20e717666b24 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github summary: API docs for the presentationUtil plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 114eef16826a7..8a20981ae869c 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github summary: API docs for the remoteClusters plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 5bf26cf8c1721..ad6dd87e77a4c 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github summary: API docs for the reporting plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index b6569d479f026..f0bec7cadc63f 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github summary: API docs for the rollup plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 88c351262977d..a51df0188147b 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github summary: API docs for the ruleRegistry plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 6156533b032f8..5af8aa2e89ebe 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github summary: API docs for the runtimeFields plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 05e031e0e731a..791f7d420ab4a 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjects plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 5d61a85adfc4e..f9749154229b0 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsManagement plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 62bec6a292c6c..43bb6e8420ef7 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsTagging plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index bec2ae79a9dcf..e86f5e46f8a10 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsTaggingOss plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 1592f917fca4b..51409cb14cd07 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github summary: API docs for the screenshotMode plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 09ddcae9e441c..c0fa3c2318753 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github summary: API docs for the screenshotting plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 273af482077ce..68ee499aa5c62 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github summary: API docs for the security plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 6c5d5c0f02248..045699a353800 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github summary: API docs for the securitySolution plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 9881dbce1cd89..32339332d72e2 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github summary: API docs for the sessionView plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 51e447f38ed1b..ebd236ff13342 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github summary: API docs for the share plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/shared_u_x.mdx b/api_docs/shared_u_x.mdx index e879fa0cd9a1a..03c0d37014be8 100644 --- a/api_docs/shared_u_x.mdx +++ b/api_docs/shared_u_x.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/sharedUX title: "sharedUX" image: https://source.unsplash.com/400x175/?github summary: API docs for the sharedUX plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sharedUX'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index da01f4c730655..59384932d5578 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github summary: API docs for the snapshotRestore plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 53fa9bf08e176..d2d8a29de4916 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github summary: API docs for the spaces plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 98e301634a2da..8b1976ef26767 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github summary: API docs for the stackAlerts plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 448d0b8cd40c6..23d9e370a3d66 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github summary: API docs for the taskManager plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 6b439649168fd..b5545b6bb27cb 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetry plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 949d390faf840..02eca020f9f5a 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryCollectionManager plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index b57243cec36d5..14a6dede7b59e 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryCollectionXpack plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index c21a6ed5b29c0..bd7a6b96dbc42 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryManagementSection plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 744b2fbcec9af..4b07fec1f04bd 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github summary: API docs for the timelines plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index f34cd424cf0f5..9439fd9d63905 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github summary: API docs for the transform plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index 1da9a4c76258e..725fa33c6265d 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -5615,6 +5615,40 @@ "deprecated": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRuleStatusPanel", + "type": "Function", + "tags": [], + "label": "getRuleStatusPanel", + "description": [], + "signature": [ + "(props: ", + "RuleStatusPanelProps", + ") => React.ReactElement<", + "RuleStatusPanelProps", + ", string | React.JSXElementConstructor>" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRuleStatusPanel.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "RuleStatusPanelProps" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] } ], "lifecycle": "start", diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 2cb9614269fd4..ab9cf78edb449 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github summary: API docs for the triggersActionsUi plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- @@ -18,7 +18,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 388 | 0 | 374 | 36 | +| 390 | 0 | 376 | 37 | ## Client diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index cbec216653b2d..16a04e1b4fda6 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github summary: API docs for the uiActions plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 5c03955fb7367..7569685446d54 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the uiActionsEnhanced plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 9288c722cc259..260eb5dbd4096 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github summary: API docs for the unifiedSearch plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index fee8f8310b836..c49684c380f00 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github summary: API docs for the unifiedSearch.autocomplete plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index f5c0bbb6e3efe..345f8725afc86 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github summary: API docs for the urlForwarding plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 64974d8c08078..d77f8d6cbe79e 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github summary: API docs for the usageCollection plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 1707b405e951e..a701728728d75 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github summary: API docs for the ux plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 554c80deef0ea..297efdf7a9f10 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the visDefaultEditor plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index b5337b23ac2e7..4a9b6435c5b41 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeGauge plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 9e513c3157782..8ecbf22750724 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeHeatmap plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index a13ccefef6faa..763c94b6cf6d6 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypePie plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 4645b7b438437..b879c8a6b32cd 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTable plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 9a8052f329002..d8eee33707c59 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTimelion plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 8e5a1eba4b82a..8ecd0f74a057f 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTimeseries plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 1e381c7034dae..ba53c7b3e33b2 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeVega plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 5d542fb21a302..401d48962d1b7 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeVislib plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 4f465b157ddb8..fb33d35803a9a 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeXy plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 24091ec1ffde2..df8b371f48821 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github summary: API docs for the visualizations plugin -date: 2022-07-05 +date: 2022-07-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- From d2bc9abeb9bacc5ee005404b8db92f1dae5481d1 Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Wed, 6 Jul 2022 07:04:45 +0100 Subject: [PATCH 18/81] [Security Solution][Detections] fixes timeline template selection when templates have same name #135694 ## Summary - addresses https://github.com/elastic/kibana/issues/130366 - instead of checking title and id when changing selection, only id will be checked ### Before Impossible to select timeline template, if previously selected one has the same name https://user-images.githubusercontent.com/92328789/177312907-bdc588c6-2811-430d-855a-6c957a65a8f8.mov ### After Possible to select timeline template, if previously selected one has the same name https://user-images.githubusercontent.com/92328789/177313210-81519771-10c5-4959-bcd2-db46c8d4a41f.mov ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) ### Release note fixes issue when users were not able to select timeline template on rules edit/create page and bulk actions if templates have the same name --- .../components/rules/pick_timeline/index.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/pick_timeline/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/pick_timeline/index.tsx index a047710ff5872..b1d1df13e4a74 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/pick_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/pick_timeline/index.tsx @@ -36,23 +36,21 @@ export const PickTimeline = ({ useEffect(() => { const { id, title } = field.value as FieldValueTimeline; - if (timelineTitle !== title && timelineId !== id) { + if (timelineId !== id) { setTimelineId(id); setTimelineTitle(title); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [field.value]); + }, [field.value, timelineId]); const handleOnTimelineChange = useCallback( (title: string, id: string | null) => { if (id === null) { field.setValue({ id, title: null }); - } else if (timelineTitle !== title && timelineId !== id) { + } else if (timelineId !== id) { field.setValue({ id, title }); } }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [field] + [field, timelineId] ); return ( From aef5c9a0dafb26b1bf8e58acf5f3880b7bae7623 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Wed, 6 Jul 2022 08:45:13 +0200 Subject: [PATCH 19/81] [Security Solution] Adds related integrations test coverage (#135181) Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../fixtures/related_integrations.ndjson | 2 + .../related_integrations.spec.ts | 222 ++++++++++++++++++ .../cypress/screens/alerts_details.ts | 6 + .../cypress/screens/alerts_detection_rules.ts | 4 + .../cypress/screens/integrations.ts | 14 ++ .../cypress/screens/rule_details.ts | 4 + .../cypress/tasks/alerts_details.ts | 5 + .../cypress/tasks/alerts_detection_rules.ts | 5 + .../api_calls/kibana_advanced_settings.ts | 27 +++ .../cypress/tasks/api_calls/rules.ts | 21 ++ .../security_solution/cypress/tasks/common.ts | 42 ++++ .../cypress/tasks/integrations.ts | 23 ++ .../integration_status_badge.tsx | 4 +- 13 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/security_solution/cypress/fixtures/related_integrations.ndjson create mode 100644 x-pack/plugins/security_solution/cypress/integration/detection_rules/related_integrations.spec.ts create mode 100644 x-pack/plugins/security_solution/cypress/screens/integrations.ts create mode 100644 x-pack/plugins/security_solution/cypress/tasks/api_calls/kibana_advanced_settings.ts create mode 100644 x-pack/plugins/security_solution/cypress/tasks/integrations.ts diff --git a/x-pack/plugins/security_solution/cypress/fixtures/related_integrations.ndjson b/x-pack/plugins/security_solution/cypress/fixtures/related_integrations.ndjson new file mode 100644 index 0000000000000..f121d07f4610f --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/fixtures/related_integrations.ndjson @@ -0,0 +1,2 @@ +{"id":"6cc39c80-da3a-11ec-9fce-65c1a0bee904","updated_at":"2022-05-23T01:48:23.422Z","updated_by":"elastic","created_at":"2022-05-23T01:48:20.940Z","created_by":"elastic","name":"Related integrations rule","tags":["Elastic","Endpoint Security"],"interval":"5m","enabled":false,"description":"Generates a detection alert each time an Elastic Endpoint Security alert is received. Enabling this rule allows you to immediately begin investigating your Endpoint alerts.","risk_score":47,"severity":"medium","license":"Elastic License v2","output_index":".siem-signals-default","meta":{"from":"5m"},"rule_name_override":"message","timestamp_override":"event.ingested","author":["Elastic"],"false_positives":[],"from":"now-50000h","rule_id":"2c66bf23-6ae9-4eb2-859e-446bea181ae9","max_signals":10000,"risk_score_mapping":[{"field":"event.risk_score","operator":"equals","value":""}],"severity_mapping":[{"field":"event.severity","operator":"equals","severity":"low","value":"21"},{"field":"event.severity","operator":"equals","severity":"medium","value":"47"},{"field":"event.severity","operator":"equals","severity":"high","value":"73"},{"field":"event.severity","operator":"equals","severity":"critical","value":"99"}],"threat":[],"to":"now","references":[],"version":7,"exceptions_list":[{"id":"endpoint_list","list_id":"endpoint_list","namespace_type":"agnostic","type":"endpoint"}],"immutable":false,"related_integrations":[{"package":"system","version":"1.17.0"},{"package":"aws","integration":"cloudtrail","version":"1.17.0"},{"package":"aws","integration":"cloudfront","version":"1.17.0"},{"package":"aws","integration":"unknown","version":"1.17.0"}],"type":"query","language":"kuery","index":["auditbeat-*"],"query":"*:*","filters":[],"throttle":"no_actions","actions":[]} +{"exported_count":1,"exported_rules_count":1,"missing_rules":[],"missing_rules_count":0,"exported_exception_list_count":0,"exported_exception_list_item_count":0,"missing_exception_list_item_count":0,"missing_exception_list_items":[],"missing_exception_lists":[],"missing_exception_lists_count":0} diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/related_integrations.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/related_integrations.spec.ts new file mode 100644 index 0000000000000..b5c6b5cd341ec --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/related_integrations.spec.ts @@ -0,0 +1,222 @@ +/* + * 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 { + INTEGRATIONS_POPOVER, + INTEGRATIONS_POPOVER_TITLE, + RULE_NAME, +} from '../../screens/alerts_detection_rules'; +import { INTEGRATIONS, INTEGRATIONS_STATUS } from '../../screens/rule_details'; +import { + enableRule, + goToTheRuleDetailsOf, + openIntegrationsPopover, + waitForRuleToChangeStatus, +} from '../../tasks/alerts_detection_rules'; +import { importRule } from '../../tasks/api_calls/rules'; +import { cleanKibana, cleanPackages } from '../../tasks/common'; +import { login, visit } from '../../tasks/login'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { installAwsCloudFrontWithPolicy } from '../../tasks/integrations'; +import { expandFirstAlert } from '../../tasks/alerts'; +import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; +import { filterBy, openTable } from '../../tasks/alerts_details'; +import { FIELD } from '../../screens/alerts_details'; +import { + disableRelatedIntegrations, + enableRelatedIntegrations, +} from '../../tasks/api_calls/kibana_advanced_settings'; + +/* + Note that the rule we are using for testing purposes has the following characteristics, changing that may affect the coverage. + + - Single-integration + - Package: system + - Multi-integration package + - Package: aws + - Integration: cloudtrail + - Integration: cloudfront + - Not existing package: + - Package: unknown + - Not existing integration & existing package: + - Package: aws + - Integration: unknown + */ + +describe('Related integrations', () => { + before(() => { + login(); + cleanKibana(); + importRule('related_integrations.ndjson'); + }); + + context('integrations not installed', () => { + const rule = { + name: 'Related integrations rule', + integrations: ['Aws Cloudfront', 'Aws Cloudtrail', 'Aws Unknown', 'System'], + enabledIntegrations: '0', + }; + + before(() => { + cleanPackages(); + visit(DETECTIONS_RULE_MANAGEMENT_URL); + }); + + it('should display a badge with the installed integrations on the rule management page', () => { + cy.get(INTEGRATIONS_POPOVER).should( + 'have.text', + `${rule.enabledIntegrations}/${rule.integrations.length} integrations` + ); + }); + + it('should display a popover when clicking the badge with the installed integrations on the rule management page', () => { + openIntegrationsPopover(); + + cy.get(INTEGRATIONS_POPOVER_TITLE).should( + 'have.text', + `[${rule.integrations.length}] Related integrations available` + ); + cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); + cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); + + rule.integrations.forEach((integration, index) => { + cy.get(INTEGRATIONS).eq(index).should('contain', integration); + cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', 'Not installed'); + }); + }); + + it('should display the integrations on the definition section', () => { + goToTheRuleDetailsOf(rule.name); + + cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); + cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); + + rule.integrations.forEach((integration, index) => { + cy.get(INTEGRATIONS).eq(index).should('contain', integration); + cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', 'Not installed'); + }); + }); + }); + + context( + 'installed integrations: Amazon CloudFront, AWS CloudTrail, System, enabled integrations: Amazon CloudFront, Aws Cloudfront, System', + () => { + const rule = { + name: 'Related integrations rule', + integrations: [ + { name: 'Amazon CloudFront', installed: true, enabled: true }, + { name: 'AWS CloudTrail', installed: true, enabled: false }, + { name: 'Aws Unknown', installed: false, enabled: false }, + { name: 'System', installed: true, enabled: true }, + ], + enabledIntegrations: '2', + }; + + before(() => { + cleanPackages(); + installAwsCloudFrontWithPolicy(); + visit(DETECTIONS_RULE_MANAGEMENT_URL); + }); + + it('should display a badge with the installed integrations on the rule management page', () => { + cy.get(INTEGRATIONS_POPOVER).should( + 'have.text', + `${rule.enabledIntegrations}/${rule.integrations.length} integrations` + ); + }); + + it('should display a popover when clicking the badge with the installed integrations on the rule management page', () => { + openIntegrationsPopover(); + + cy.get(INTEGRATIONS_POPOVER_TITLE).should( + 'have.text', + `[${rule.integrations.length}] Related integrations available` + ); + cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); + cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); + + rule.integrations.forEach((integration, index) => { + let expectedStatus = integration.installed ? 'Installed' : 'Not installed'; + if (integration.enabled) expectedStatus += ': enabled'; + + cy.get(INTEGRATIONS).eq(index).should('contain', integration.name); + cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', expectedStatus); + }); + }); + + it('should display the integrations on the definition section', () => { + goToTheRuleDetailsOf(rule.name); + + cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); + cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); + + rule.integrations.forEach((integration, index) => { + let expectedStatus = integration.installed ? 'Installed' : 'Not installed'; + if (integration.enabled) expectedStatus += ': enabled'; + + cy.get(INTEGRATIONS).eq(index).should('contain', integration.name); + cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', expectedStatus); + }); + }); + + it('the alerts generated should have a "kibana.alert.rule.parameters.related_integrations" field containing the integrations', () => { + const firstRule = 0; + const relatedIntegrationsField = 'kibana.alert.rule.parameters.related_integrations'; + const expectedRelatedIntegrationsText = + '{"package":"system","version":"1.17.0"}{"package":"aws","integration":"cloudtrail","version":"1.17.0"}{"package":"aws","integration":"cloudfront","version":"1.17.0"}{"package":"aws","integration":"unknown","version":"1.17.0"}'; + + visit(DETECTIONS_RULE_MANAGEMENT_URL); + enableRule(firstRule); + waitForRuleToChangeStatus(); + goToTheRuleDetailsOf(rule.name); + waitForAlertsToPopulate(); + expandFirstAlert(); + openTable(); + filterBy(relatedIntegrationsField); + cy.get(FIELD(relatedIntegrationsField)).should( + 'have.text', + expectedRelatedIntegrationsText + ); + }); + } + ); + + context('related Integrations Advanced Setting is disabled', () => { + const rule = { + name: 'Related integrations rule', + integrations: ['Aws Cloudfront', 'Aws Cloudtrail', 'Aws Unknown', 'System'], + enabledIntegrations: '0', + }; + + before(() => { + cleanPackages(); + disableRelatedIntegrations(); + visit(DETECTIONS_RULE_MANAGEMENT_URL); + }); + + after(() => { + enableRelatedIntegrations(); + }); + + it('should not display a badge with the installed integrations on the rule management page', () => { + cy.get(RULE_NAME).should('have.text', rule.name); + cy.get(INTEGRATIONS).should('not.exist'); + }); + + it('should display the integrations on the definition section', () => { + goToTheRuleDetailsOf(rule.name); + + cy.get(INTEGRATIONS).should('have.length', rule.integrations.length); + cy.get(INTEGRATIONS_STATUS).should('have.length', rule.integrations.length); + + rule.integrations.forEach((integration, index) => { + cy.get(INTEGRATIONS).eq(index).should('contain', integration); + cy.get(INTEGRATIONS_STATUS).eq(index).should('have.text', 'Not installed'); + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts index f035bbf2e3efd..bba46731d4d53 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts @@ -17,6 +17,12 @@ export const ENRICHMENT_QUERY_START_INPUT = '.start-picker'; export const ENRICHMENT_QUERY_END_INPUT = '.end-picker'; +export const FIELD = (value: string) => { + return `[data-test-subj="event-field-${value}"]`; +}; + +export const FILTER_INPUT = '[data-test-subj="eventDetails"] .euiFieldSearch'; + export const INDICATOR_MATCH_ENRICHMENT_SECTION = '[data-test-subj="threat-match-detected"]'; export const INVESTIGATION_TIME_ENRICHMENT_SECTION = diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts index 3556f46ac8534..2e186d95f176c 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts @@ -39,6 +39,10 @@ export const FIRST_RULE = 0; export const FOURTH_RULE = 3; +export const INTEGRATIONS_POPOVER = '[data-test-subj="IntegrationsDisplayPopover"]'; + +export const INTEGRATIONS_POPOVER_TITLE = '[data-test-subj="IntegrationsPopoverTitle"]'; + export const LOAD_PREBUILT_RULES_BTN = '[data-test-subj="load-prebuilt-rules"]'; export const LOAD_PREBUILT_RULES_ON_PAGE_HEADER_BTN = '[data-test-subj="loadPrebuiltRulesBtn"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/integrations.ts b/x-pack/plugins/security_solution/cypress/screens/integrations.ts new file mode 100644 index 0000000000000..a834fdf0fb050 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/screens/integrations.ts @@ -0,0 +1,14 @@ +/* + * 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 ADD_INTEGRATION_BTN = '[data-test-subj="addIntegrationPolicyButton"]'; + +export const INTEGRATION_ADDED_POP_UP = '[data-test-subj="postInstallAddAgentModal"]'; + +export const QUEUE_URL = '.euiFieldText.euiFormControlLayout--1icons'; + +export const SAVE_AND_CONTINUE_BTN = '[data-test-subj="createPackagePolicySaveButton"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts index c7726ac40e83d..d58451f6f1520 100644 --- a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts @@ -47,6 +47,10 @@ export const INDICATOR_INDEX_QUERY = 'Indicator index query'; export const INDICATOR_MAPPING = 'Indicator mapping'; +export const INTEGRATIONS = '[data-test-subj="integrationLink"]'; + +export const INTEGRATIONS_STATUS = '[data-test-subj="statusBadge"]'; + export const INVESTIGATION_NOTES_MARKDOWN = 'test markdown'; export const INVESTIGATION_NOTES_TOGGLE = '[data-test-subj="stepAboutDetailsToggle-notes"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts index 87aa83c3c10ec..d8f1aaf36a01e 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts @@ -11,8 +11,13 @@ import { JSON_VIEW_TAB, OVERVIEW_TAB, TABLE_TAB, + FILTER_INPUT, } from '../screens/alerts_details'; +export const filterBy = (value: string) => { + cy.get(FILTER_INPUT).type(value); +}; + export const openJsonView = () => { cy.get(JSON_VIEW_TAB).click(); }; 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 b5c50d11deb10..80d5bf54ca6c4 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 @@ -46,6 +46,7 @@ import { RULE_IMPORT_OVERWRITE_EXCEPTIONS_CHECKBOX, RULES_TAGS_POPOVER_BTN, RULES_TAGS_POPOVER_WRAPPER, + INTEGRATIONS_POPOVER, SELECTED_RULES_NUMBER_LABEL, } from '../screens/alerts_detection_rules'; import { ALL_ACTIONS } from '../screens/rule_details'; @@ -165,6 +166,10 @@ export const loadPrebuiltDetectionRules = () => { .should('be.disabled'); }; +export const openIntegrationsPopover = () => { + cy.get(INTEGRATIONS_POPOVER).click(); +}; + export const reloadDeletedRules = () => { cy.get(RELOAD_PREBUILT_RULES_BTN).click({ force: true }); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/kibana_advanced_settings.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/kibana_advanced_settings.ts new file mode 100644 index 0000000000000..8b370b8e1168c --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/kibana_advanced_settings.ts @@ -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. + */ + +const kibanaSettings = (body: Cypress.RequestBody) => { + cy.request({ + method: 'POST', + url: 'api/kibana/settings', + body, + headers: { 'kbn-xsrf': 'cypress-creds' }, + }); +}; + +const relatedIntegrationsBody = (status: boolean): Cypress.RequestBody => { + return { changes: { 'securitySolution:showRelatedIntegrations': status } }; +}; + +export const enableRelatedIntegrations = () => { + kibanaSettings(relatedIntegrationsBody(true)); +}; + +export const disableRelatedIntegrations = () => { + kibanaSettings(relatedIntegrationsBody(false)); +}; 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 405c118140395..3f60a8f01bc6e 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 @@ -131,3 +131,24 @@ export const deleteCustomRule = (ruleId = '1') => { failOnStatusCode: false, }); }; + +export const importRule = (ndjsonPath: string) => { + cy.fixture(ndjsonPath) + .then((file) => Cypress.Blob.binaryStringToBlob(file)) + .then((blob) => { + const formdata = new FormData(); + formdata.append('file', blob, ndjsonPath); + + cy.request({ + url: 'api/detection_engine/rules/_import', + method: 'POST', + headers: { + 'kbn-xsrf': 'cypress-creds', + 'content-type': 'multipart/form-data', + }, + body: formdata, + }) + .its('status') + .should('be.equal', 200); + }); +}; diff --git a/x-pack/plugins/security_solution/cypress/tasks/common.ts b/x-pack/plugins/security_solution/cypress/tasks/common.ts index a738019d1fcbf..69b88bca934c5 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/common.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/common.ts @@ -69,6 +69,48 @@ export const cleanKibana = () => { deleteTimelines(); }; +export const cleanPackages = () => { + deletePolicies(); + deletePackages(); +}; + +export const deletePolicies = () => { + cy.request({ + method: 'GET', + url: 'api/fleet/agent_policies', + headers: { 'kbn-xsrf': 'cypress-creds' }, + }).then((response) => { + response.body.items.forEach((item: { id: string }) => { + cy.request({ + method: 'POST', + url: `api/fleet/agent_policies/delete`, + headers: { 'kbn-xsrf': 'cypress-creds' }, + body: { + agentPolicyId: item.id, + }, + }); + }); + }); +}; + +export const deletePackages = () => { + cy.request({ + method: 'GET', + url: 'api/fleet/epm/packages', + headers: { 'kbn-xsrf': 'cypress-creds' }, + }).then((response) => { + response.body.items.forEach((item: { status: string; name: string; version: string }) => { + if (item.status === 'installed') { + cy.request({ + method: 'DELETE', + url: `api/fleet/epm/packages/${item.name}/${item.version}`, + headers: { 'kbn-xsrf': 'cypress-creds' }, + }); + } + }); + }); +}; + export const deleteAlertsAndRules = () => { const kibanaIndexUrl = `${Cypress.env('ELASTICSEARCH_URL')}/.kibana_\*`; diff --git a/x-pack/plugins/security_solution/cypress/tasks/integrations.ts b/x-pack/plugins/security_solution/cypress/tasks/integrations.ts new file mode 100644 index 0000000000000..1da83a591aa12 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/tasks/integrations.ts @@ -0,0 +1,23 @@ +/* + * 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 { + ADD_INTEGRATION_BTN, + INTEGRATION_ADDED_POP_UP, + QUEUE_URL, + SAVE_AND_CONTINUE_BTN, +} from '../screens/integrations'; + +import { visit } from './login'; + +export const installAwsCloudFrontWithPolicy = () => { + visit('app/integrations/detail/aws-1.17.0/overview?integration=cloudfront'); + cy.get(ADD_INTEGRATION_BTN).click(); + cy.get(QUEUE_URL).type('http://www.example.com'); + cy.get(SAVE_AND_CONTINUE_BTN).click(); + cy.get(INTEGRATION_ADDED_POP_UP).should('exist'); +}; diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/integrations_description/integration_status_badge.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/integrations_description/integration_status_badge.tsx index ca17144133dbd..422282e942ddb 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/integrations_description/integration_status_badge.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/related_integrations/integrations_description/integration_status_badge.tsx @@ -49,7 +49,9 @@ const IntegrationStatusBadgeComponent: React.FC = ( return ( - {badgeText} + + {badgeText} + ); }; From 113391618f54db010c50fe74051b569c7732f4c4 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Wed, 6 Jul 2022 09:36:09 +0200 Subject: [PATCH 20/81] Fix Inspect modal header should be in single linear of Host and User risk (#135710) --- .../components/host_risk_score_table/index.tsx | 15 ++++++++++----- .../components/user_risk_score_table/index.tsx | 15 ++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/security_solution/public/hosts/components/host_risk_score_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/host_risk_score_table/index.tsx index bbbda683bb869..59f58d4318482 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/host_risk_score_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/host_risk_score_table/index.tsx @@ -9,6 +9,7 @@ import React, { useMemo, useCallback } from 'react'; import { useDispatch } from 'react-redux'; import { EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; +import styled from 'styled-components'; import { Columns, Criteria, @@ -46,6 +47,10 @@ export const rowItems: ItemsPerRow[] = [ }, ]; +const IconWrapper = styled.span` + margin-left: ${({ theme }) => theme.eui.euiSizeS}; +`; + const tableType = hostsModel.HostsTableType.risk; interface HostRiskScoreTableProps { @@ -150,9 +155,9 @@ const HostRiskScoreTableComponent: React.FC = ({ ); const headerTitle = ( - - {i18nHosts.HOST_RISK_TITLE} - + <> + {i18nHosts.HOST_RISK_TITLE} + = ({ size="l" type="iInCircle" /> - - + + ); const getHostRiskScoreFilterQuerySelector = useMemo( diff --git a/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.tsx b/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.tsx index 121ccae4553fc..0d0eee5848bb5 100644 --- a/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.tsx +++ b/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.tsx @@ -9,6 +9,7 @@ import React, { useMemo, useCallback } from 'react'; import { useDispatch } from 'react-redux'; import { EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; +import styled from 'styled-components'; import { Columns, Criteria, @@ -37,6 +38,10 @@ import { UsersRiskScore, } from '../../../../common/search_strategy'; +const IconWrapper = styled.span` + margin-left: ${({ theme }) => theme.eui.euiSizeS}; +`; + export const rowItems: ItemsPerRow[] = [ { text: i18n.ROWS_5, @@ -154,9 +159,9 @@ const UserRiskScoreTableComponent: React.FC = ({ ); const headerTitle = ( - - {i18nUsers.NAVIGATION_RISK_TITLE} - + <> + {i18nUsers.NAVIGATION_RISK_TITLE} + = ({ size="l" type="iInCircle" /> - - + + ); const getUserRiskScoreFilterQuerySelector = useMemo( From 4d301fdf4d211c43aef42ad4d25f7be95369f74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Wed, 6 Jul 2022 10:01:52 +0200 Subject: [PATCH 21/81] [Usage Collection] Use PIT for collecting UI/Usage Counters & AppUsage (#135689) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fetch_all_saved_objects.ts | 28 +++++++++++++ .../application_usage/rollups/total.ts | 12 ++---- .../telemetry_application_usage_collector.ts | 22 ++++------ .../register_ui_counters_collector.ts | 42 +++++++++---------- .../telemetry_ui_metric_collector.ts | 30 ++++++------- .../register_usage_counters_collector.ts | 28 +++++++------ 6 files changed, 93 insertions(+), 69 deletions(-) create mode 100644 src/plugins/kibana_usage_collection/server/collectors/application_usage/fetch_all_saved_objects.ts diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/fetch_all_saved_objects.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/fetch_all_saved_objects.ts new file mode 100644 index 0000000000000..261b1dc0adb00 --- /dev/null +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/fetch_all_saved_objects.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 type { + ISavedObjectsRepository, + SavedObjectsCreatePointInTimeFinderOptions, + SavedObjectsFindResult, +} from '@kbn/core/server'; + +export async function fetchAllSavedObjects( + soRepository: ISavedObjectsRepository, + findOptions: SavedObjectsCreatePointInTimeFinderOptions +): Promise>> { + const finder = soRepository.createPointInTimeFinder({ ...findOptions, perPage: 1000 }); + + const allSavedObjects: Array> = []; + + for await (const { saved_objects: savedObjects } of finder.find()) { + allSavedObjects.push(...savedObjects); + } + + return allSavedObjects; +} diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/rollups/total.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/rollups/total.ts index 6c55d0f7535af..c8a83deba52e8 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/rollups/total.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/rollups/total.ts @@ -16,6 +16,7 @@ import { SAVED_OBJECTS_TOTAL_TYPE, } from '../saved_objects_types'; import { serializeKey } from './utils'; +import { fetchAllSavedObjects } from '../fetch_all_saved_objects'; /** * Moves all the daily documents into aggregated "total" documents as we don't care about any granularity after 90 days @@ -28,16 +29,11 @@ export async function rollTotals(logger: Logger, savedObjectsClient?: ISavedObje } try { - const [ - { saved_objects: rawApplicationUsageTotals }, - { saved_objects: rawApplicationUsageDaily }, - ] = await Promise.all([ - savedObjectsClient.find({ - perPage: 10000, + const [rawApplicationUsageTotals, rawApplicationUsageDaily] = await Promise.all([ + fetchAllSavedObjects(savedObjectsClient, { type: SAVED_OBJECTS_TOTAL_TYPE, }), - savedObjectsClient.find({ - perPage: 10000, + fetchAllSavedObjects(savedObjectsClient, { type: SAVED_OBJECTS_DAILY_TYPE, filter: `${SAVED_OBJECTS_DAILY_TYPE}.attributes.timestamp < now-90d`, }), diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/telemetry_application_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/telemetry_application_usage_collector.ts index b582cd3ceff64..1d93a05ed9d09 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/telemetry_application_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/telemetry_application_usage_collector.ts @@ -8,12 +8,12 @@ import moment from 'moment'; import { type Observable, takeUntil, timer } from 'rxjs'; -import { ISavedObjectsRepository, Logger, SavedObjectsServiceSetup } from '@kbn/core/server'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import type { ISavedObjectsRepository, Logger, SavedObjectsServiceSetup } from '@kbn/core/server'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { MAIN_APP_DEFAULT_VIEW_ID } from '@kbn/usage-collection-plugin/common/constants'; import { - ApplicationUsageDaily, - ApplicationUsageTotal, + type ApplicationUsageDaily, + type ApplicationUsageTotal, registerMappings, SAVED_OBJECTS_DAILY_TYPE, SAVED_OBJECTS_TOTAL_TYPE, @@ -21,7 +21,8 @@ import { import { applicationUsageSchema } from './schema'; import { rollTotals, serializeKey } from './rollups'; import { ROLL_TOTAL_INDICES_INTERVAL, ROLL_INDICES_START } from './constants'; -import { ApplicationUsageTelemetryReport, ApplicationUsageViews } from './types'; +import type { ApplicationUsageTelemetryReport, ApplicationUsageViews } from './types'; +import { fetchAllSavedObjects } from './fetch_all_saved_objects'; export const transformByApplicationViews = ( report: ApplicationUsageViews @@ -67,17 +68,12 @@ export function registerApplicationUsageCollector( if (typeof savedObjectsClient === 'undefined') { return; } - const [ - { saved_objects: rawApplicationUsageTotals }, - { saved_objects: rawApplicationUsageDaily }, - ] = await Promise.all([ - savedObjectsClient.find({ + const [rawApplicationUsageTotals, rawApplicationUsageDaily] = await Promise.all([ + fetchAllSavedObjects(savedObjectsClient, { type: SAVED_OBJECTS_TOTAL_TYPE, - perPage: 10000, // We only have 44 apps for now. This limit is OK. }), - savedObjectsClient.find({ + fetchAllSavedObjects(savedObjectsClient, { type: SAVED_OBJECTS_DAILY_TYPE, - perPage: 10000, // We can have up to 44 apps * 91 days = 4004 docs. This limit is OK }), ]); diff --git a/src/plugins/kibana_usage_collection/server/collectors/ui_counters/register_ui_counters_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/ui_counters/register_ui_counters_collector.ts index c2e17c24de488..0eb9d291337a7 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ui_counters/register_ui_counters_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ui_counters/register_ui_counters_collector.ts @@ -57,29 +57,29 @@ export function transformRawUsageCounterObject( } export async function fetchUiCounters({ soClient }: CollectorFetchContext) { - const { saved_objects: rawUsageCounters } = - await soClient.find({ - type: USAGE_COUNTERS_SAVED_OBJECT_TYPE, - fields: ['count', 'counterName', 'counterType', 'domainId'], - filter: `${USAGE_COUNTERS_SAVED_OBJECT_TYPE}.attributes.domainId: uiCounter`, - perPage: 10000, - }); + const finder = soClient.createPointInTimeFinder({ + type: USAGE_COUNTERS_SAVED_OBJECT_TYPE, + fields: ['count', 'counterName', 'counterType', 'domainId'], + filter: `${USAGE_COUNTERS_SAVED_OBJECT_TYPE}.attributes.domainId: uiCounter`, + perPage: 1000, + }); - return { - dailyEvents: Object.values( - rawUsageCounters.reduce((acc, raw) => { - try { - const event = transformRawUsageCounterObject(raw); - if (event) { - acc[raw.id] = event; - } - } catch (_) { - // swallow error; allows sending successfully transformed objects. + const dailyEvents: UiCounterEvent[] = []; + + for await (const { saved_objects: rawUsageCounters } of finder.find()) { + rawUsageCounters.forEach((raw) => { + try { + const event = transformRawUsageCounterObject(raw); + if (event) { + dailyEvents.push(event); } - return acc; - }, {} as Record) - ), - }; + } catch (_) { + // swallow error; allows sending successfully transformed objects. + } + }); + } + + return { dailyEvents }; } export function registerUiCountersUsageCollector(usageCollection: UsageCollectionSetup) { diff --git a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts index 3d49bca3bb2a4..833e537b92ddf 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts @@ -52,26 +52,28 @@ export function registerUiMetricUsageCollector( return; } - const { saved_objects: rawUiMetrics } = await savedObjectsClient.find({ + const finder = savedObjectsClient.createPointInTimeFinder({ type: 'ui-metric', fields: ['count'], - perPage: 10000, + perPage: 1000, }); - const uiMetricsByAppName = rawUiMetrics.reduce((accum, rawUiMetric) => { - const { - id, - attributes: { count }, - } = rawUiMetric; + const uiMetricsByAppName: UIMetricUsage = {}; - const [appName, ...metricType] = id.split(':'); + for await (const { saved_objects: rawUiMetrics } of finder.find()) { + rawUiMetrics.forEach((rawUiMetric) => { + const { + id, + attributes: { count }, + } = rawUiMetric; - const pair = { key: metricType.join(':'), value: count }; - return { - ...accum, - [appName]: [...(accum[appName] || []), pair], - }; - }, {} as UIMetricUsage); + const [appName, ...metricType] = id.split(':'); + + const pair = { key: metricType.join(':'), value: count }; + + uiMetricsByAppName[appName] = [...(uiMetricsByAppName[appName] || []), pair]; + }); + } return uiMetricsByAppName; }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/usage_counters/register_usage_counters_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/usage_counters/register_usage_counters_collector.ts index 3899dac73f939..a46782bf8563a 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/usage_counters/register_usage_counters_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/usage_counters/register_usage_counters_collector.ts @@ -86,27 +86,29 @@ export function registerUsageCountersUsageCollector(usageCollection: UsageCollec }, }, fetch: async ({ soClient }: CollectorFetchContext) => { - const { saved_objects: rawUsageCounters } = - await soClient.find({ - type: USAGE_COUNTERS_SAVED_OBJECT_TYPE, - fields: ['count', 'counterName', 'counterType', 'domainId'], - filter: `NOT ${USAGE_COUNTERS_SAVED_OBJECT_TYPE}.attributes.domainId: uiCounter`, - perPage: 10000, - }); + const finder = soClient.createPointInTimeFinder({ + type: USAGE_COUNTERS_SAVED_OBJECT_TYPE, + fields: ['count', 'counterName', 'counterType', 'domainId'], + filter: `NOT ${USAGE_COUNTERS_SAVED_OBJECT_TYPE}.attributes.domainId: uiCounter`, + perPage: 1000, + }); + + const dailyEvents: UsageCounterEvent[] = []; - return { - dailyEvents: rawUsageCounters.reduce((acc, rawUsageCounter) => { + for await (const { saved_objects: rawUsageCounters } of finder.find()) { + rawUsageCounters.forEach((rawUsageCounter) => { try { const event = transformRawCounter(rawUsageCounter); if (event) { - acc.push(event); + dailyEvents.push(event); } } catch (_) { // swallow error; allows sending successfully transformed objects. } - return acc; - }, [] as UsageCounterEvent[]), - }; + }); + } + + return { dailyEvents }; }, isReady: () => true, }); From e88c743f1d0403ed5c866048a119113d5e776359 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Wed, 6 Jul 2022 10:51:11 +0200 Subject: [PATCH 22/81] Decouple RequestHandler from CoreRequestHandlerContext (#135448) * Decouple RequestHandler from CoreRequestHandlerContext * fix service default type * split core context providers * introduce type definition for the sub contexts * ensure the root implementation implements the root interface * adapt SO route definitions * adapt uiSettings route definitions * fix more internal routes * adapt SO route integration tests * adapt SO legacy route integration tests * fix more types * am I getting anywhere? * did it do the trick? * fix test failure * export pre-scoped IRouter for external consumers * fix wrong path import * fix public export of HttpServiceSetup * fix more usages * work around again * fix RequestHandler usage * fix more violations * fix more violations * let's try another approach * fix test file * revert some unecessary changes * revert some unecessary changes bis * cleanup external changes * some tsdoc cleanup * more cleanup * try to fix mock types * export CoreRequestHandlerContext sub-parts * export base types for renamed public types Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/core/server/context/container/context.ts | 10 +- src/core/server/core_app/core_app.ts | 3 +- src/core/server/core_app/internal_types.ts | 28 ++++ src/core/server/core_route_handler_context.ts | 156 +++++------------- .../deprecations_route_handler_context.ts | 43 +++++ src/core/server/deprecations/index.ts | 2 + .../server/deprecations/internal_types.ts | 26 +++ src/core/server/deprecations/routes/get.ts | 7 +- src/core/server/deprecations/routes/index.ts | 3 +- .../elasticsearch_route_handler_context.ts | 39 +++++ src/core/server/elasticsearch/index.ts | 2 + .../integration_tests/tracing.test.ts | 47 +++--- src/core/server/http/http_server.test.ts | 4 +- src/core/server/http/http_service.mock.ts | 13 +- src/core/server/http/http_service.ts | 17 +- .../server/http/router/error_wrapper.test.ts | 5 +- src/core/server/http/router/router.ts | 16 +- src/core/server/http/types.ts | 32 ++-- .../http_resources_service.test.ts | 4 +- .../http_resources/http_resources_service.ts | 5 +- src/core/server/index.ts | 127 ++++++++------ src/core/server/mocks.ts | 5 +- .../preboot_core_route_handler_context.ts | 28 +++- .../bootstrap/register_bootstrap_route.ts | 4 +- src/core/server/rendering/internal_types.ts | 28 ++++ .../server/rendering/rendering_service.tsx | 5 +- src/core/server/saved_objects/index.ts | 2 + .../server/saved_objects/internal_types.ts | 30 ++++ .../saved_objects/routes/bulk_create.ts | 7 +- .../server/saved_objects/routes/bulk_get.ts | 7 +- .../saved_objects/routes/bulk_resolve.ts | 7 +- .../saved_objects/routes/bulk_update.ts | 7 +- .../server/saved_objects/routes/create.ts | 7 +- .../server/saved_objects/routes/delete.ts | 7 +- .../deprecations/delete_unknown_types.ts | 4 +- .../server/saved_objects/routes/export.ts | 5 +- src/core/server/saved_objects/routes/find.ts | 7 +- src/core/server/saved_objects/routes/get.ts | 7 +- .../server/saved_objects/routes/import.ts | 4 +- src/core/server/saved_objects/routes/index.ts | 10 +- .../integration_tests/bulk_create.test.ts | 4 +- .../routes/integration_tests/bulk_get.test.ts | 4 +- .../integration_tests/bulk_resolve.test.ts | 4 +- .../integration_tests/bulk_update.test.ts | 4 +- .../routes/integration_tests/create.test.ts | 4 +- .../routes/integration_tests/delete.test.ts | 4 +- .../delete_unknown_types.test.ts | 5 +- .../routes/integration_tests/export.test.ts | 4 +- .../routes/integration_tests/find.test.ts | 4 +- .../routes/integration_tests/get.test.ts | 14 +- .../routes/integration_tests/import.test.ts | 5 +- .../routes/integration_tests/resolve.test.ts | 14 +- .../resolve_import_errors.test.ts | 4 +- .../routes/integration_tests/update.test.ts | 4 +- .../routes/legacy_import_export/export.ts | 5 +- .../routes/legacy_import_export/import.ts | 6 +- .../integration_tests/export.test.ts | 3 +- .../integration_tests/import.test.ts | 3 +- .../server/saved_objects/routes/migrate.ts | 4 +- .../server/saved_objects/routes/resolve.ts | 7 +- .../routes/resolve_import_errors.ts | 5 +- .../server/saved_objects/routes/test_utils.ts | 11 +- .../server/saved_objects/routes/update.ts | 7 +- .../saved_objects_route_handler_context.ts | 68 ++++++++ src/core/server/server.ts | 21 ++- src/core/server/ui_settings/index.ts | 2 + src/core/server/ui_settings/internal_types.ts | 28 ++++ src/core/server/ui_settings/routes/delete.ts | 4 +- src/core/server/ui_settings/routes/get.ts | 4 +- src/core/server/ui_settings/routes/index.ts | 5 +- src/core/server/ui_settings/routes/set.ts | 4 +- .../server/ui_settings/routes/set_many.ts | 4 +- .../ui_settings_route_handler_context.ts | 40 +++++ .../server/ui_settings/ui_settings_service.ts | 3 +- .../routes/integration_tests/stats.test.ts | 9 +- .../server/services/license.ts | 4 +- .../on_post_auth_interceptor.test.ts | 4 +- .../on_request_interceptor.test.ts | 3 +- 78 files changed, 773 insertions(+), 329 deletions(-) create mode 100644 src/core/server/core_app/internal_types.ts create mode 100644 src/core/server/deprecations/deprecations_route_handler_context.ts create mode 100644 src/core/server/deprecations/internal_types.ts create mode 100644 src/core/server/elasticsearch/elasticsearch_route_handler_context.ts create mode 100644 src/core/server/rendering/internal_types.ts create mode 100644 src/core/server/saved_objects/internal_types.ts create mode 100644 src/core/server/saved_objects/saved_objects_route_handler_context.ts create mode 100644 src/core/server/ui_settings/internal_types.ts create mode 100644 src/core/server/ui_settings/ui_settings_route_handler_context.ts diff --git a/src/core/server/context/container/context.ts b/src/core/server/context/container/context.ts index a2acdf1e5e4cf..6e9670de9925e 100644 --- a/src/core/server/context/container/context.ts +++ b/src/core/server/context/container/context.ts @@ -10,7 +10,7 @@ import { flatten } from 'lodash'; import { ShallowPromise, MaybePromise } from '@kbn/utility-types'; import type { PluginOpaqueId } from '@kbn/core-base-common'; import type { CoreId } from '@kbn/core-base-common-internal'; -import type { RequestHandler, RequestHandlerContext } from '../..'; +import type { RequestHandler, RequestHandlerContextBase } from '../..'; /** * A function that returns a context value for a specific key of given context type. @@ -26,7 +26,7 @@ import type { RequestHandler, RequestHandlerContext } from '../..'; * @public */ export type IContextProvider< - Context extends RequestHandlerContext, + Context extends RequestHandlerContextBase, ContextName extends keyof Context > = ( // context.core will always be available, but plugin contexts are typed as optional @@ -148,7 +148,7 @@ export interface IContextContainer { * @param provider - A {@link IContextProvider} to be called each time a new context is created. * @returns The {@link IContextContainer} for method chaining. */ - registerContext( + registerContext( pluginOpaqueId: PluginOpaqueId, contextName: ContextName, provider: IContextProvider @@ -195,7 +195,7 @@ export class ContextContainer implements IContextContainer { } public registerContext = < - Context extends RequestHandlerContext, + Context extends RequestHandlerContextBase, ContextName extends keyof Context >( source: symbol, @@ -243,7 +243,7 @@ export class ContextContainer implements IContextContainer { const builtContextPromises: Record> = {}; const builtContext = {} as HandlerContextType; - (builtContext as unknown as RequestHandlerContext).resolve = async (keys) => { + (builtContext as unknown as RequestHandlerContextBase).resolve = async (keys) => { const resolved = await Promise.all( keys.map(async (key) => { return [key, await builtContext[key]]; diff --git a/src/core/server/core_app/core_app.ts b/src/core/server/core_app/core_app.ts index b004e1352da9b..78e1e3548fdaa 100644 --- a/src/core/server/core_app/core_app.ts +++ b/src/core/server/core_app/core_app.ts @@ -19,6 +19,7 @@ import { HttpResources, HttpResourcesServiceToolkit } from '../http_resources'; import { InternalCorePreboot, InternalCoreSetup } from '../internal_types'; import { registerBundleRoutes } from './bundle_routes'; import { UiPlugins } from '../plugins'; +import type { InternalCoreAppRequestHandlerContext } from './internal_types'; /** @internal */ interface CommonRoutesParams { @@ -85,7 +86,7 @@ export class CoreApp { private registerDefaultRoutes(coreSetup: InternalCoreSetup, uiPlugins: UiPlugins) { const httpSetup = coreSetup.http; - const router = httpSetup.createRouter(''); + const router = httpSetup.createRouter(''); const resources = coreSetup.httpResources.createRegistrar(router); router.get({ path: '/', validate: false }, async (context, req, res) => { diff --git a/src/core/server/core_app/internal_types.ts b/src/core/server/core_app/internal_types.ts new file mode 100644 index 0000000000000..24b9bd4c709aa --- /dev/null +++ b/src/core/server/core_app/internal_types.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 type { RequestHandlerContextBase } from '..'; +import type { IRouter } from '../http'; +import type { UiSettingsRequestHandlerContext } from '../ui_settings'; + +/** + * Request handler context used by core's coreApp routes. + * @internal + */ +export interface InternalCoreAppRequestHandlerContext extends RequestHandlerContextBase { + core: Promise<{ + uiSettings: UiSettingsRequestHandlerContext; + }>; +} + +/** + * Router bound to the {@link InternalCoreAppRequestHandlerContext}. + * Used by core's coreApp routes. + * @internal + */ +export type InternalCoreAppRouter = IRouter; diff --git a/src/core/server/core_route_handler_context.ts b/src/core/server/core_route_handler_context.ts index 3106053eb6afa..66c7f8c6d98d9 100644 --- a/src/core/server/core_route_handler_context.ts +++ b/src/core/server/core_route_handler_context.ts @@ -6,131 +6,63 @@ * Side Public License, v 1. */ -// eslint-disable-next-line max-classes-per-file -import { InternalCoreStart } from './internal_types'; -import { KibanaRequest } from './http/router'; -import { SavedObjectsClientContract } from './saved_objects/types'; +import type { InternalCoreStart } from './internal_types'; +import type { KibanaRequest } from './http'; import { - InternalSavedObjectsServiceStart, - ISavedObjectTypeRegistry, - SavedObjectsClientProviderOptions, + CoreSavedObjectsRouteHandlerContext, + SavedObjectsRequestHandlerContext, } from './saved_objects'; -import { InternalElasticsearchServiceStart, IScopedClusterClient } from './elasticsearch'; -import { InternalUiSettingsServiceStart, IUiSettingsClient } from './ui_settings'; -import { DeprecationsClient, InternalDeprecationsServiceStart } from './deprecations'; - -class CoreElasticsearchRouteHandlerContext { - #client?: IScopedClusterClient; - - constructor( - private readonly elasticsearchStart: InternalElasticsearchServiceStart, - private readonly request: KibanaRequest - ) {} - - public get client() { - if (this.#client == null) { - this.#client = this.elasticsearchStart.client.asScoped(this.request); - } - return this.#client; - } -} - -class CoreSavedObjectsRouteHandlerContext { - constructor( - private readonly savedObjectsStart: InternalSavedObjectsServiceStart, - private readonly request: KibanaRequest - ) {} - #scopedSavedObjectsClient?: SavedObjectsClientContract; - #typeRegistry?: ISavedObjectTypeRegistry; - - public get client() { - if (this.#scopedSavedObjectsClient == null) { - this.#scopedSavedObjectsClient = this.savedObjectsStart.getScopedClient(this.request); - } - return this.#scopedSavedObjectsClient; - } - - public get typeRegistry() { - if (this.#typeRegistry == null) { - this.#typeRegistry = this.savedObjectsStart.getTypeRegistry(); - } - return this.#typeRegistry; - } - - public getClient = (options?: SavedObjectsClientProviderOptions) => { - if (!options) return this.client; - return this.savedObjectsStart.getScopedClient(this.request, options); - }; - - public getExporter = (client: SavedObjectsClientContract) => { - return this.savedObjectsStart.createExporter(client); - }; - - public getImporter = (client: SavedObjectsClientContract) => { - return this.savedObjectsStart.createImporter(client); - }; -} - -class CoreUiSettingsRouteHandlerContext { - #client?: IUiSettingsClient; - constructor( - private readonly uiSettingsStart: InternalUiSettingsServiceStart, - private readonly savedObjectsRouterHandlerContext: CoreSavedObjectsRouteHandlerContext - ) {} - - public get client() { - if (this.#client == null) { - this.#client = this.uiSettingsStart.asScopedToClient( - this.savedObjectsRouterHandlerContext.client - ); - } - return this.#client; - } -} - -class CoreDeprecationsRouteHandlerContext { - #client?: DeprecationsClient; - constructor( - private readonly deprecationsStart: InternalDeprecationsServiceStart, - private readonly elasticsearchRouterHandlerContext: CoreElasticsearchRouteHandlerContext, - private readonly savedObjectsRouterHandlerContext: CoreSavedObjectsRouteHandlerContext - ) {} - - public get client() { - if (this.#client == null) { - this.#client = this.deprecationsStart.asScopedToClient( - this.elasticsearchRouterHandlerContext.client, - this.savedObjectsRouterHandlerContext.client - ); - } - return this.#client; - } +import { + CoreElasticsearchRouteHandlerContext, + ElasticsearchRequestHandlerContext, +} from './elasticsearch'; +import { CoreUiSettingsRouteHandlerContext, UiSettingsRequestHandlerContext } from './ui_settings'; +import { + CoreDeprecationsRouteHandlerContext, + DeprecationsRequestHandlerContext, +} from './deprecations'; + +/** + * The `core` context provided to route handler. + * + * Provides the following clients and services: + * - {@link SavedObjectsClient | savedObjects.client} - Saved Objects client + * which uses the credentials of the incoming request + * - {@link ISavedObjectTypeRegistry | savedObjects.typeRegistry} - Type registry containing + * all the registered types. + * - {@link IScopedClusterClient | elasticsearch.client} - Elasticsearch + * data client which uses the credentials of the incoming request + * - {@link IUiSettingsClient | uiSettings.client} - uiSettings client + * which uses the credentials of the incoming request + * @public + */ +export interface CoreRequestHandlerContext { + savedObjects: SavedObjectsRequestHandlerContext; + elasticsearch: ElasticsearchRequestHandlerContext; + uiSettings: UiSettingsRequestHandlerContext; + deprecations: DeprecationsRequestHandlerContext; } -export class CoreRouteHandlerContext { +/** + * The concrete implementation for Core's route handler context. + * + * @internal + */ +export class CoreRouteHandlerContext implements CoreRequestHandlerContext { readonly elasticsearch: CoreElasticsearchRouteHandlerContext; readonly savedObjects: CoreSavedObjectsRouteHandlerContext; readonly uiSettings: CoreUiSettingsRouteHandlerContext; readonly deprecations: CoreDeprecationsRouteHandlerContext; - constructor( - private readonly coreStart: InternalCoreStart, - private readonly request: KibanaRequest - ) { - this.elasticsearch = new CoreElasticsearchRouteHandlerContext( - this.coreStart.elasticsearch, - this.request - ); - this.savedObjects = new CoreSavedObjectsRouteHandlerContext( - this.coreStart.savedObjects, - this.request - ); + constructor(coreStart: InternalCoreStart, request: KibanaRequest) { + this.elasticsearch = new CoreElasticsearchRouteHandlerContext(coreStart.elasticsearch, request); + this.savedObjects = new CoreSavedObjectsRouteHandlerContext(coreStart.savedObjects, request); this.uiSettings = new CoreUiSettingsRouteHandlerContext( - this.coreStart.uiSettings, + coreStart.uiSettings, this.savedObjects ); this.deprecations = new CoreDeprecationsRouteHandlerContext( - this.coreStart.deprecations, + coreStart.deprecations, this.elasticsearch, this.savedObjects ); diff --git a/src/core/server/deprecations/deprecations_route_handler_context.ts b/src/core/server/deprecations/deprecations_route_handler_context.ts new file mode 100644 index 0000000000000..76e5d974056d4 --- /dev/null +++ b/src/core/server/deprecations/deprecations_route_handler_context.ts @@ -0,0 +1,43 @@ +/* + * 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 { CoreElasticsearchRouteHandlerContext } from '../elasticsearch'; +import type { CoreSavedObjectsRouteHandlerContext } from '../saved_objects'; +import type { DeprecationsClient, InternalDeprecationsServiceStart } from './deprecations_service'; + +/** + * Core's `deprecations` request handler context. + * @public + */ +export interface DeprecationsRequestHandlerContext { + client: DeprecationsClient; +} + +/** + * The {@link DeprecationsRequestHandlerContext} implementation. + * @internal + */ +export class CoreDeprecationsRouteHandlerContext implements DeprecationsRequestHandlerContext { + #client?: DeprecationsClient; + + constructor( + private readonly deprecationsStart: InternalDeprecationsServiceStart, + private readonly elasticsearchRouterHandlerContext: CoreElasticsearchRouteHandlerContext, + private readonly savedObjectsRouterHandlerContext: CoreSavedObjectsRouteHandlerContext + ) {} + + public get client() { + if (this.#client == null) { + this.#client = this.deprecationsStart.asScopedToClient( + this.elasticsearchRouterHandlerContext.client, + this.savedObjectsRouterHandlerContext.client + ); + } + return this.#client; + } +} diff --git a/src/core/server/deprecations/index.ts b/src/core/server/deprecations/index.ts index d9225750f04a1..9245179d3099a 100644 --- a/src/core/server/deprecations/index.ts +++ b/src/core/server/deprecations/index.ts @@ -25,3 +25,5 @@ export type { export { DeprecationsService } from './deprecations_service'; export { config } from './deprecation_config'; +export { CoreDeprecationsRouteHandlerContext } from './deprecations_route_handler_context'; +export type { DeprecationsRequestHandlerContext } from './deprecations_route_handler_context'; diff --git a/src/core/server/deprecations/internal_types.ts b/src/core/server/deprecations/internal_types.ts new file mode 100644 index 0000000000000..0f23360e94ba9 --- /dev/null +++ b/src/core/server/deprecations/internal_types.ts @@ -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 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 { IRouter } from '../http'; +import type { RequestHandlerContextBase } from '..'; +import type { DeprecationsRequestHandlerContext } from './deprecations_route_handler_context'; + +/** + * Request handler context used by core's deprecations routes. + * @internal + */ +export interface InternalDeprecationRequestHandlerContext extends RequestHandlerContextBase { + core: Promise<{ deprecations: DeprecationsRequestHandlerContext }>; +} + +/** + * Router bound to the {@link InternalDeprecationRequestHandlerContext}. + * Used by core's deprecations routes. + * @internal + */ +export type InternalDeprecationRouter = IRouter; diff --git a/src/core/server/deprecations/routes/get.ts b/src/core/server/deprecations/routes/get.ts index 88965505488f9..a3ea08f04d706 100644 --- a/src/core/server/deprecations/routes/get.ts +++ b/src/core/server/deprecations/routes/get.ts @@ -5,10 +5,11 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { IRouter } from '../../http'; -import { DeprecationsGetResponse } from '../types'; -export const registerGetRoute = (router: IRouter) => { +import type { DeprecationsGetResponse } from '../types'; +import type { InternalDeprecationRouter } from '../internal_types'; + +export const registerGetRoute = (router: InternalDeprecationRouter) => { router.get( { path: '/', diff --git a/src/core/server/deprecations/routes/index.ts b/src/core/server/deprecations/routes/index.ts index 633950be61d12..5c73af882085c 100644 --- a/src/core/server/deprecations/routes/index.ts +++ b/src/core/server/deprecations/routes/index.ts @@ -7,9 +7,10 @@ */ import { InternalHttpServiceSetup } from '../../http'; +import type { InternalDeprecationRequestHandlerContext } from '../internal_types'; import { registerGetRoute } from './get'; export function registerRoutes({ http }: { http: InternalHttpServiceSetup }) { - const router = http.createRouter('/api/deprecations'); + const router = http.createRouter('/api/deprecations'); registerGetRoute(router); } diff --git a/src/core/server/elasticsearch/elasticsearch_route_handler_context.ts b/src/core/server/elasticsearch/elasticsearch_route_handler_context.ts new file mode 100644 index 0000000000000..536ce7f369b6e --- /dev/null +++ b/src/core/server/elasticsearch/elasticsearch_route_handler_context.ts @@ -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 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 { KibanaRequest } from '../http'; +import type { IScopedClusterClient } from './client'; +import type { InternalElasticsearchServiceStart } from './types'; + +/** + * Core's `elasticsearch` request handler context. + * @public + */ +export interface ElasticsearchRequestHandlerContext { + client: IScopedClusterClient; +} + +/** + * The {@link UiSettingsRequestHandlerContext} implementation. + * @internal + */ +export class CoreElasticsearchRouteHandlerContext implements ElasticsearchRequestHandlerContext { + #client?: IScopedClusterClient; + + constructor( + private readonly elasticsearchStart: InternalElasticsearchServiceStart, + private readonly request: KibanaRequest + ) {} + + public get client() { + if (this.#client == null) { + this.#client = this.elasticsearchStart.client.asScoped(this.request); + } + return this.#client; + } +} diff --git a/src/core/server/elasticsearch/index.ts b/src/core/server/elasticsearch/index.ts index f146ba937509e..5b7ef6e1290e9 100644 --- a/src/core/server/elasticsearch/index.ts +++ b/src/core/server/elasticsearch/index.ts @@ -54,3 +54,5 @@ export { isNotFoundFromUnsupportedServer, PRODUCT_RESPONSE_HEADER, } from './supported_server_response_check'; +export { CoreElasticsearchRouteHandlerContext } from './elasticsearch_route_handler_context'; +export type { ElasticsearchRequestHandlerContext } from './elasticsearch_route_handler_context'; diff --git a/src/core/server/execution_context/integration_tests/tracing.test.ts b/src/core/server/execution_context/integration_tests/tracing.test.ts index a733bf796f62e..40dd31e8116df 100644 --- a/src/core/server/execution_context/integration_tests/tracing.test.ts +++ b/src/core/server/execution_context/integration_tests/tracing.test.ts @@ -8,6 +8,7 @@ import { ExecutionContextContainer } from '@kbn/core-execution-context-browser-internal'; import * as kbnTestServer from '../../../test_helpers/kbn_server'; +import { RequestHandlerContext } from '../..'; const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); @@ -63,7 +64,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asInternalUser.ping({}, { meta: true }); @@ -86,7 +87,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asCurrentUser.ping({}, { meta: true }); @@ -109,7 +110,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asInternalUser.ping({}, { meta: true }); @@ -128,7 +129,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asCurrentUser.ping({}, { meta: true }); @@ -147,7 +148,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asInternalUser.ping( @@ -194,7 +195,7 @@ describe('trace', () => { const { http } = await rootExecutionContextDisabled.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asCurrentUser.ping({}, { meta: true }); @@ -217,7 +218,7 @@ describe('trace', () => { const { http, executionContext } = await rootExecutionContextDisabled.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { executionContext.set(parentContext); const esClient = (await context.core).elasticsearch.client; @@ -250,7 +251,7 @@ describe('trace', () => { const { executionContext, http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { executionContext.set(parentContext); return res.ok({ body: executionContext.get() }); @@ -265,7 +266,7 @@ describe('trace', () => { const { executionContext, http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { executionContext.set(parentContext); await delay(100); @@ -281,7 +282,7 @@ describe('trace', () => { const { executionContext, http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); let id = 42; router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { executionContext.set({ ...parentContext, id: String(id++) }); @@ -301,7 +302,7 @@ describe('trace', () => { const { executionContext, http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); let id = 2; router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { executionContext.set({ ...parentContext, id: String(id) }); @@ -329,7 +330,7 @@ describe('trace', () => { const { executionContext, http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); let id = 2; router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { executionContext.set(parentContext); @@ -364,7 +365,7 @@ describe('trace', () => { const { executionContext, http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, (context, req, res) => res.ok({ body: executionContext.get() }) ); @@ -382,7 +383,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asCurrentUser.ping({}, { meta: true }); @@ -416,7 +417,7 @@ describe('trace', () => { registerOnPreResponse, } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { return res.ok({ body: executionContext.get()?.toJSON() }); }); @@ -470,7 +471,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asCurrentUser.ping({}, { meta: true }); @@ -492,7 +493,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asInternalUser.ping({}, { meta: true }); @@ -514,7 +515,7 @@ describe('trace', () => { const { http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { const esClient = (await context.core).elasticsearch.client; const { headers } = await esClient.asCurrentUser.ping({}, { meta: true }); @@ -537,7 +538,7 @@ describe('trace', () => { const { http, executionContext } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { executionContext.set(parentContext); const esClient = (await context.core).elasticsearch.client; @@ -561,7 +562,7 @@ describe('trace', () => { const { http, executionContext } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); const ctx = { type: 'test-type', name: 'test-name', @@ -588,7 +589,7 @@ describe('trace', () => { const { executionContext, http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); router.get({ path: '/execution-context', validate: false }, async (context, req, res) => { return executionContext.withContext(parentContext, () => res.ok({ body: executionContext.get() }) @@ -604,7 +605,7 @@ describe('trace', () => { const { executionContext, http } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); const nestedContext = { type: 'nested-type', name: 'nested-name', @@ -630,7 +631,7 @@ describe('trace', () => { const { http, executionContext } = await root.setup(); const { createRouter } = http; - const router = createRouter(''); + const router = createRouter(''); const newContext = { type: 'new-type', name: 'new-name', diff --git a/src/core/server/http/http_server.test.ts b/src/core/server/http/http_server.test.ts index 5746bd1d6306e..ac2597a0d28ce 100644 --- a/src/core/server/http/http_server.test.ts +++ b/src/core/server/http/http_server.test.ts @@ -25,7 +25,7 @@ import { } from './router'; import { HttpServer } from './http_server'; import { Readable } from 'stream'; -import { RequestHandlerContext } from '..'; +import { RequestHandlerContextBase } from '..'; import { KBN_CERT_PATH, KBN_KEY_PATH } from '@kbn/dev-utils'; import moment from 'moment'; import { of } from 'rxjs'; @@ -466,7 +466,7 @@ test('not inline handler - KibanaRequest', async () => { const router = new Router('/foo', logger, enhanceWithContext); const handler = ( - context: RequestHandlerContext, + context: RequestHandlerContextBase, req: KibanaRequest, res: KibanaResponseFactory ) => { diff --git a/src/core/server/http/http_service.mock.ts b/src/core/server/http/http_service.mock.ts index d3e9fd7fe27f2..c0ddd0ac5b3f4 100644 --- a/src/core/server/http/http_service.mock.ts +++ b/src/core/server/http/http_service.mock.ts @@ -30,6 +30,7 @@ import { OnPreAuthToolkit } from './lifecycle/on_pre_auth'; import { OnPreResponseToolkit } from './lifecycle/on_pre_response'; import { ExternalUrlConfig } from './external_url'; import type { IAuthHeadersStorage } from './auth_headers_storage'; +import type { RequestHandlerContextBase } from '..'; type BasePathMocked = jest.Mocked; type AuthMocked = jest.Mocked; @@ -38,9 +39,9 @@ export type HttpServicePrebootMock = jest.Mocked; export type InternalHttpServicePrebootMock = jest.Mocked< Omit > & { basePath: BasePathMocked }; -export type HttpServiceSetupMock = jest.Mocked< - Omit -> & { +export type HttpServiceSetupMock< + ContextType extends RequestHandlerContextBase = RequestHandlerContextBase +> = jest.Mocked, 'basePath' | 'createRouter'>> & { basePath: BasePathMocked; createRouter: jest.MockedFunction<() => RouterMock>; }; @@ -166,10 +167,12 @@ const createInternalSetupContractMock = () => { return mock; }; -const createSetupContractMock = () => { +const createSetupContractMock = < + ContextType extends RequestHandlerContextBase = RequestHandlerContextBase +>() => { const internalMock = createInternalSetupContractMock(); - const mock: HttpServiceSetupMock = { + const mock: HttpServiceSetupMock = { createCookieSessionStorageFactory: internalMock.createCookieSessionStorageFactory, registerOnPreRouting: internalMock.registerOnPreRouting, registerOnPreAuth: jest.fn(), diff --git a/src/core/server/http/http_service.ts b/src/core/server/http/http_service.ts index f13a0fbaf294d..1014b89e7425e 100644 --- a/src/core/server/http/http_service.ts +++ b/src/core/server/http/http_service.ts @@ -16,11 +16,11 @@ import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; import type { PluginOpaqueId } from '@kbn/core-base-common'; import type { InternalExecutionContextSetup } from '@kbn/core-execution-context-server-internal'; -import type { RequestHandlerContext } from '..'; +import type { RequestHandlerContextBase } from '..'; import { InternalContextSetup, InternalContextPreboot } from '../context'; import { CspConfigType, cspConfig } from './csp'; -import { Router } from './router'; +import { Router, IRouter } from './router'; import { HttpConfig, HttpConfigType, config as httpConfig } from './http_config'; import { HttpServer } from './http_server'; import { HttpsRedirectServer } from './https_redirect_server'; @@ -114,8 +114,13 @@ export class HttpService server: prebootSetup.server, registerRouteHandlerContext: (pluginOpaqueId, contextName, provider) => prebootServerRequestHandlerContext.registerContext(pluginOpaqueId, contextName, provider), - registerRoutes: (path, registerCallback) => { - const router = new Router( + registerRoutes: < + DefaultRequestHandlerType extends RequestHandlerContextBase = RequestHandlerContextBase + >( + path: string, + registerCallback: (router: IRouter) => void + ) => { + const router = new Router( path, this.log, prebootServerRequestHandlerContext.createHandler.bind(null, this.coreContext.coreId) @@ -157,7 +162,7 @@ export class HttpService externalUrl: new ExternalUrlConfig(config.externalUrl), - createRouter: ( + createRouter: ( path: string, pluginId: PluginOpaqueId = this.coreContext.coreId ) => { @@ -168,7 +173,7 @@ export class HttpService }, registerRouteHandlerContext: < - Context extends RequestHandlerContext, + Context extends RequestHandlerContextBase, ContextName extends keyof Context >( pluginOpaqueId: PluginOpaqueId, diff --git a/src/core/server/http/router/error_wrapper.test.ts b/src/core/server/http/router/error_wrapper.test.ts index 948aff8f32fee..48dad17fcf934 100644 --- a/src/core/server/http/router/error_wrapper.test.ts +++ b/src/core/server/http/router/error_wrapper.test.ts @@ -9,7 +9,8 @@ import Boom from '@hapi/boom'; import { KibanaResponse, KibanaResponseFactory, kibanaResponseFactory } from './response'; import { wrapErrors } from './error_wrapper'; -import { KibanaRequest, RequestHandler, RequestHandlerContext } from '../..'; +import { RequestHandlerContextBase } from '../..'; +import { KibanaRequest, RequestHandler } from '..'; const createHandler = (handler: () => any): RequestHandler => @@ -18,7 +19,7 @@ const createHandler = }; describe('wrapErrors', () => { - let context: RequestHandlerContext; + let context: RequestHandlerContextBase; let request: KibanaRequest; let response: KibanaResponseFactory; diff --git a/src/core/server/http/router/router.ts b/src/core/server/http/router/router.ts index 59611e51d9a15..570f4f973dd53 100644 --- a/src/core/server/http/router/router.ts +++ b/src/core/server/http/router/router.ts @@ -24,7 +24,7 @@ import { } from './response'; import { RouteConfig, RouteConfigOptions, RouteMethod, validBodyOutput } from './route'; import { HapiResponseAdapter } from './response_adapter'; -import { RequestHandlerContext } from '../..'; +import { RequestHandlerContextBase } from '../..'; import { wrapErrors } from './error_wrapper'; import { RouteValidator } from './validator'; @@ -46,7 +46,7 @@ export interface RouterRoute { */ export type RouteRegistrar< Method extends RouteMethod, - Context extends RequestHandlerContext = RequestHandlerContext + Context extends RequestHandlerContextBase = RequestHandlerContextBase > = ( route: RouteConfig, handler: RequestHandler @@ -58,7 +58,7 @@ export type RouteRegistrar< * * @public */ -export interface IRouter { +export interface IRouter { /** * Resulted path */ @@ -118,7 +118,7 @@ export type ContextEnhancer< Q, B, Method extends RouteMethod, - Context extends RequestHandlerContext + Context extends RequestHandlerContextBase > = (handler: RequestHandler) => RequestHandlerEnhanced; function getRouteFullPath(routerPath: string, routePath: string) { @@ -202,7 +202,7 @@ function validOptions( /** * @internal */ -export class Router +export class Router implements IRouter { public routes: Array> = []; @@ -307,7 +307,7 @@ type WithoutHeadArgument = T extends (first: any, ...rest: infer Params) => i : never; type RequestHandlerEnhanced = WithoutHeadArgument< - RequestHandler + RequestHandler >; /** @@ -350,7 +350,7 @@ export type RequestHandler< P = unknown, Q = unknown, B = unknown, - Context extends RequestHandlerContext = RequestHandlerContext, + Context extends RequestHandlerContextBase = RequestHandlerContextBase, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory > = ( @@ -376,7 +376,7 @@ export type RequestHandlerWrapper = < P, Q, B, - Context extends RequestHandlerContext = RequestHandlerContext, + Context extends RequestHandlerContextBase = RequestHandlerContextBase, Method extends RouteMethod = any, ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory >( diff --git a/src/core/server/http/types.ts b/src/core/server/http/types.ts index 55bef12fd0f8b..46b74deec2bc2 100644 --- a/src/core/server/http/types.ts +++ b/src/core/server/http/types.ts @@ -21,7 +21,7 @@ import { OnPostAuthHandler } from './lifecycle/on_post_auth'; import { OnPreResponseHandler } from './lifecycle/on_pre_response'; import { IBasePath } from './base_path_service'; import { ExternalUrlConfig } from './external_url'; -import type { PluginOpaqueId, RequestHandlerContext } from '..'; +import type { PluginOpaqueId, RequestHandlerContextBase } from '..'; /** * An object that handles registration of http request context providers. @@ -36,7 +36,7 @@ export type RequestHandlerContextContainer = IContextContainer; * @public */ export type RequestHandlerContextProvider< - Context extends RequestHandlerContext, + Context extends RequestHandlerContextBase, ContextName extends keyof Context > = IContextProvider; @@ -117,7 +117,9 @@ export interface HttpAuth { * ``` * @public */ -export interface HttpServicePreboot { +export interface HttpServicePreboot< + DefaultRequestHandlerType extends RequestHandlerContextBase = RequestHandlerContextBase +> { /** * Provides ability to acquire `preboot` {@link IRouter} instance for a particular top-level path and register handler * functions for any number of nested routes. @@ -135,7 +137,10 @@ export interface HttpServicePreboot { * ``` * @public */ - registerRoutes(path: string, callback: (router: IRouter) => void): void; + registerRoutes( + path: string, + callback: (router: IRouter) => void + ): void; /** * Access or manipulate the Kibana base path @@ -162,7 +167,12 @@ export interface InternalHttpServicePreboot | 'server' | 'getServerInfo' > { - registerRoutes(path: string, callback: (router: IRouter) => void): void; + registerRoutes< + DefaultRequestHandlerType extends RequestHandlerContextBase = RequestHandlerContextBase + >( + path: string, + callback: (router: IRouter) => void + ): void; } /** @@ -237,7 +247,9 @@ export interface InternalHttpServicePreboot * ``` * @public */ -export interface HttpServiceSetup { +export interface HttpServiceSetup< + DefaultRequestHandlerType extends RequestHandlerContextBase = RequestHandlerContextBase +> { /** * Creates cookie based session storage factory {@link SessionStorageFactory} * @param cookieOptions {@link SessionStorageCookieOptions} - options to configure created cookie session storage. @@ -333,7 +345,7 @@ export interface HttpServiceSetup { * @public */ createRouter: < - Context extends RequestHandlerContext = RequestHandlerContext + Context extends DefaultRequestHandlerType = DefaultRequestHandlerType >() => IRouter; /** @@ -365,7 +377,7 @@ export interface HttpServiceSetup { * @public */ registerRouteHandlerContext: < - Context extends RequestHandlerContext, + Context extends DefaultRequestHandlerType, ContextName extends keyof Omit >( contextName: ContextName, @@ -384,7 +396,7 @@ export interface InternalHttpServiceSetup auth: HttpServerSetup['auth']; server: HttpServerSetup['server']; externalUrl: ExternalUrlConfig; - createRouter: ( + createRouter: ( path: string, plugin?: PluginOpaqueId ) => IRouter; @@ -392,7 +404,7 @@ export interface InternalHttpServiceSetup registerStaticDir: (path: string, dirPath: string) => void; authRequestHeaders: IAuthHeadersStorage; registerRouteHandlerContext: < - Context extends RequestHandlerContext, + Context extends RequestHandlerContextBase, ContextName extends keyof Omit >( pluginOpaqueId: PluginOpaqueId, diff --git a/src/core/server/http_resources/http_resources_service.test.ts b/src/core/server/http_resources/http_resources_service.test.ts index 91500737123c7..e626d496c8dec 100644 --- a/src/core/server/http_resources/http_resources_service.test.ts +++ b/src/core/server/http_resources/http_resources_service.test.ts @@ -8,7 +8,7 @@ import { getApmConfigMock } from './http_resources_service.test.mocks'; -import { IRouter, RouteConfig } from '../http'; +import { RouteConfig } from '../http'; import { mockCoreContext } from '@kbn/core-base-server-mocks'; import { coreMock } from '../mocks'; @@ -25,7 +25,7 @@ describe('HttpResources service', () => { let service: HttpResourcesService; let prebootDeps: PrebootDeps; let setupDeps: SetupDeps; - let router: jest.Mocked; + let router: ReturnType; const kibanaRequest = httpServerMock.createKibanaRequest(); const context = coreMock.createCustomRequestHandlerContext({}); const apmConfig = { mockApmConfig: true }; diff --git a/src/core/server/http_resources/http_resources_service.ts b/src/core/server/http_resources/http_resources_service.ts index 978ad8e72621b..2fa90b4346965 100644 --- a/src/core/server/http_resources/http_resources_service.ts +++ b/src/core/server/http_resources/http_resources_service.ts @@ -63,7 +63,10 @@ export class HttpResourcesService implements CoreService + ): HttpResources { return { register: ( route: RouteConfig, diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 25dd89acab6e6..4198fe04789ae 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -46,29 +46,26 @@ import { ElasticsearchServiceSetup, configSchema as elasticsearchConfigSchema, ElasticsearchServiceStart, - IScopedClusterClient, ElasticsearchServicePreboot, } from './elasticsearch'; -import { HttpServicePreboot, HttpServiceSetup, HttpServiceStart } from './http'; +import type { + HttpServicePreboot, + HttpServiceSetup, + HttpServiceStart, + IRouter, + RequestHandler, +} from './http'; import { HttpResources } from './http_resources'; import { PluginsServiceSetup, PluginsServiceStart, PluginOpaqueId } from './plugins'; -import { IUiSettingsClient, UiSettingsServiceSetup, UiSettingsServiceStart } from './ui_settings'; -import { SavedObjectsClientContract } from './saved_objects/types'; -import { - ISavedObjectTypeRegistry, - SavedObjectsServiceSetup, - SavedObjectsServiceStart, - ISavedObjectsExporter, - ISavedObjectsImporter, - SavedObjectsClientProviderOptions, -} from './saved_objects'; +import { UiSettingsServiceSetup, UiSettingsServiceStart } from './ui_settings'; +import { SavedObjectsServiceSetup, SavedObjectsServiceStart } from './saved_objects'; import { CapabilitiesSetup, CapabilitiesStart } from './capabilities'; import { MetricsServiceSetup, MetricsServiceStart } from './metrics'; import { StatusServiceSetup } from './status'; import { CoreUsageDataStart, CoreUsageDataSetup } from './core_usage_data'; import { I18nServiceSetup } from './i18n'; -import { DeprecationsServiceSetup, DeprecationsClient } from './deprecations'; +import { DeprecationsServiceSetup } from './deprecations'; // Because of #79265 we need to explicitly import, then export these types for // scripts/telemetry_check.js to work as expected import { @@ -80,6 +77,9 @@ import { CoreServicesUsageData, } from './core_usage_data'; import { PrebootServicePreboot } from './preboot'; +import type { CoreRequestHandlerContext } from './core_route_handler_context'; +import type { PrebootCoreRequestHandlerContext } from './preboot_core_route_handler_context'; +import { KibanaResponseFactory, RouteMethod } from './http'; export type { PrebootServicePreboot } from './preboot'; @@ -151,6 +151,7 @@ export type { UnauthorizedErrorHandlerResult, UnauthorizedErrorHandlerToolkit, UnauthorizedErrorHandler, + ElasticsearchRequestHandlerContext, } from './elasticsearch'; export type { @@ -176,7 +177,6 @@ export type { HttpResponsePayload, HttpServerInfo, HttpServicePreboot, - HttpServiceSetup, HttpServiceStart, ErrorHttpResponseOptions, IKibanaSocket, @@ -199,7 +199,6 @@ export type { OnPreResponseExtensions, OnPreResponseInfo, RedirectResponseOptions, - RequestHandler, RequestHandlerWrapper, RequestHandlerContextContainer, RequestHandlerContextProvider, @@ -208,7 +207,6 @@ export type { ResponseHeaders, KibanaResponseFactory, RouteConfig, - IRouter, RouteRegistrar, RouteMethod, RouteConfigOptions, @@ -387,6 +385,7 @@ export type { SavedObjectsImportWarning, SavedObjectsValidationMap, SavedObjectsValidationSpec, + SavedObjectsRequestHandlerContext, } from './saved_objects'; export type { @@ -398,6 +397,7 @@ export type { UiSettingsServiceStart, UserProvidedValues, DeprecationSettings, + UiSettingsRequestHandlerContext, } from './ui_settings'; export type { @@ -421,6 +421,7 @@ export type { GetDeprecationsContext, DeprecationsServiceSetup, DeprecationsClient, + DeprecationsRequestHandlerContext, } from './deprecations'; export type { AppCategory } from '../types'; @@ -473,7 +474,12 @@ export type { AnalyticsServiceStart, } from '@kbn/core-analytics-server'; -/** @public **/ +export type { CoreRequestHandlerContext } from './core_route_handler_context'; + +/** + * Base, abstract type for request handler contexts. + * @public + **/ export interface RequestHandlerContextBase { /** * Await all the specified context parts and return them. @@ -491,7 +497,7 @@ export interface RequestHandlerContextBase { } /** - * Base context passed to a route handler. + * Base context passed to a route handler, containing the `core` context part. * * @public */ @@ -499,43 +505,21 @@ export interface RequestHandlerContext extends RequestHandlerContextBase { core: Promise; } -/** @public */ -export type CustomRequestHandlerContext = RequestHandlerContext & { - [Key in keyof T]: T[Key] extends Promise ? T[Key] : Promise; -}; +/** + * @internal + */ +export interface PrebootRequestHandlerContext extends RequestHandlerContextBase { + core: Promise; +} /** - * The `core` context provided to route handler. + * Mixin allowing plugins to define their own request handler contexts. * - * Provides the following clients and services: - * - {@link SavedObjectsClient | savedObjects.client} - Saved Objects client - * which uses the credentials of the incoming request - * - {@link ISavedObjectTypeRegistry | savedObjects.typeRegistry} - Type registry containing - * all the registered types. - * - {@link IScopedClusterClient | elasticsearch.client} - Elasticsearch - * data client which uses the credentials of the incoming request - * - {@link IUiSettingsClient | uiSettings.client} - uiSettings client - * which uses the credentials of the incoming request * @public */ -export interface CoreRequestHandlerContext { - savedObjects: { - client: SavedObjectsClientContract; - typeRegistry: ISavedObjectTypeRegistry; - getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; - getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; - getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; - }; - elasticsearch: { - client: IScopedClusterClient; - }; - uiSettings: { - client: IUiSettingsClient; - }; - deprecations: { - client: DeprecationsClient; - }; -} +export type CustomRequestHandlerContext = RequestHandlerContext & { + [Key in keyof T]: T[Key] extends Promise ? T[Key] : Promise; +}; /** * Context passed to the `setup` method of `preboot` plugins. @@ -547,7 +531,7 @@ export interface CorePreboot { /** {@link ElasticsearchServicePreboot} */ elasticsearch: ElasticsearchServicePreboot; /** {@link HttpServicePreboot} */ - http: HttpServicePreboot; + http: HttpServicePreboot; /** {@link PrebootServicePreboot} */ preboot: PrebootServicePreboot; } @@ -573,7 +557,7 @@ export interface CoreSetup & { /** {@link HttpResources} */ resources: HttpResources; }; @@ -662,3 +646,42 @@ export const config = { appenders: appendersSchema as Type, }, }; + +/** + * Public version of RequestHandler, default-scoped to {@link RequestHandlerContext} + * See [@link RequestHandler} + * @public + */ +type PublicRequestHandler< + P = unknown, + Q = unknown, + B = unknown, + Context extends RequestHandlerContext = RequestHandlerContext, + Method extends RouteMethod = any, + ResponseFactory extends KibanaResponseFactory = KibanaResponseFactory +> = RequestHandler; + +export type { PublicRequestHandler as RequestHandler, RequestHandler as BaseRequestHandler }; + +/** + * Public version of IRouter, default-scoped to {@link RequestHandlerContext} + * See [@link IRouter} + * @public + */ +type PublicRouter = + IRouter; + +export type { PublicRouter as IRouter, IRouter as IBaseRouter }; + +/** + * Public version of RequestHandlerContext, default-scoped to {@link RequestHandlerContext} + * See [@link RequestHandlerContext} + * @public + */ +type PublicHttpServiceSetup = + HttpServiceSetup; + +export type { + PublicHttpServiceSetup as HttpServiceSetup, + HttpServiceSetup as BaseHttpServiceSetup, +}; diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 0382d9f56ca1d..f224ff76418ab 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -23,6 +23,7 @@ import type { CoreStart, StartServicesAccessor, CorePreboot, + RequestHandlerContext, } from '.'; import { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock'; import { httpServiceMock } from './http/http_service.mock'; @@ -139,7 +140,7 @@ function createCorePrebootMock() { const mock: CorePrebootMockType = { analytics: analyticsServiceMock.createAnalyticsServicePreboot(), elasticsearch: elasticsearchServiceMock.createPreboot(), - http: httpServiceMock.createPrebootContract(), + http: httpServiceMock.createPrebootContract() as CorePrebootMockType['http'], preboot: prebootServiceMock.createPrebootContract(), }; @@ -159,7 +160,7 @@ function createCoreSetupMock({ pluginStartContract?: any; } = {}) { const httpMock: jest.Mocked = { - ...httpServiceMock.createSetupContract(), + ...httpServiceMock.createSetupContract(), resources: httpResourcesMock.createRegistrar(), }; diff --git a/src/core/server/preboot_core_route_handler_context.ts b/src/core/server/preboot_core_route_handler_context.ts index 63378046e8050..ba3cc445f6958 100644 --- a/src/core/server/preboot_core_route_handler_context.ts +++ b/src/core/server/preboot_core_route_handler_context.ts @@ -10,12 +10,34 @@ import { InternalCorePreboot } from './internal_types'; import { IUiSettingsClient } from './ui_settings'; -class PrebootCoreUiSettingsRouteHandlerContext { +/** + * @public + */ +export interface PrebootUiSettingsRequestHandlerContext { + client: IUiSettingsClient; +} + +/** + * Implementation of {@link PrebootUiSettingsRequestHandlerContext} + * @internal + */ +class PrebootCoreUiSettingsRouteHandlerContext implements PrebootUiSettingsRequestHandlerContext { constructor(public readonly client: IUiSettingsClient) {} } -export class PrebootCoreRouteHandlerContext { - readonly uiSettings: PrebootCoreUiSettingsRouteHandlerContext; +/** + * @public + */ +export interface PrebootCoreRequestHandlerContext { + uiSettings: PrebootUiSettingsRequestHandlerContext; +} + +/** + * Implementation of {@link PrebootCoreRequestHandlerContext}. + * @internal + */ +export class PrebootCoreRouteHandlerContext implements PrebootCoreRequestHandlerContext { + readonly uiSettings: PrebootUiSettingsRequestHandlerContext; constructor(private readonly corePreboot: InternalCorePreboot) { this.uiSettings = new PrebootCoreUiSettingsRouteHandlerContext( diff --git a/src/core/server/rendering/bootstrap/register_bootstrap_route.ts b/src/core/server/rendering/bootstrap/register_bootstrap_route.ts index 06f4100a01576..c22f7f56d70f2 100644 --- a/src/core/server/rendering/bootstrap/register_bootstrap_route.ts +++ b/src/core/server/rendering/bootstrap/register_bootstrap_route.ts @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import { IRouter } from '../../http'; +import type { InternalRenderingRouter } from '../internal_types'; import type { BootstrapRenderer } from './bootstrap_renderer'; export const registerBootstrapRoute = ({ router, renderer, }: { - router: IRouter; + router: InternalRenderingRouter; renderer: BootstrapRenderer; }) => { router.get( diff --git a/src/core/server/rendering/internal_types.ts b/src/core/server/rendering/internal_types.ts new file mode 100644 index 0000000000000..6ad3fd086f819 --- /dev/null +++ b/src/core/server/rendering/internal_types.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 type { RequestHandlerContextBase } from '..'; +import type { IRouter } from '../http'; +import type { UiSettingsRequestHandlerContext } from '../ui_settings'; + +/** + * Request handler context used by core's rendering routes. + * @internal + */ +export interface InternalRenderingRequestHandlerContext extends RequestHandlerContextBase { + core: Promise<{ + uiSettings: UiSettingsRequestHandlerContext; + }>; +} + +/** + * Router bound to the {@link InternalRenderingRequestHandlerContext}. + * Used by core's rendering routes. + * @internal + */ +export type InternalRenderingRouter = IRouter; diff --git a/src/core/server/rendering/rendering_service.tsx b/src/core/server/rendering/rendering_service.tsx index 2ce22b731b5e5..ac6ff9ee2f2b8 100644 --- a/src/core/server/rendering/rendering_service.tsx +++ b/src/core/server/rendering/rendering_service.tsx @@ -29,6 +29,7 @@ import { getSettingValue, getStylesheetPaths } from './render_utils'; import type { HttpAuth, KibanaRequest } from '../http'; import { IUiSettingsClient } from '../ui_settings'; import { filterUiPlugins } from './filter_ui_plugins'; +import type { InternalRenderingRequestHandlerContext } from './internal_types'; type RenderOptions = | (RenderingPrebootDeps & { status?: never; elasticsearch?: never }) @@ -42,7 +43,7 @@ export class RenderingService { http, uiPlugins, }: RenderingPrebootDeps): Promise { - http.registerRoutes('', (router) => { + http.registerRoutes('', (router) => { registerBootstrapRoute({ router, renderer: bootstrapRendererFactory({ @@ -66,7 +67,7 @@ export class RenderingService { uiPlugins, }: RenderingSetupDeps): Promise { registerBootstrapRoute({ - router: http.createRouter(''), + router: http.createRouter(''), renderer: bootstrapRendererFactory({ uiPlugins, serverBasePath: http.basePath.serverBasePath, diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts index 73a20c0402bbe..434096193ff9f 100644 --- a/src/core/server/saved_objects/index.ts +++ b/src/core/server/saved_objects/index.ts @@ -99,3 +99,5 @@ export type { SavedObjectsValidationMap, SavedObjectsValidationSpec } from './va export { savedObjectsConfig, savedObjectsMigrationConfig } from './saved_objects_config'; export { SavedObjectTypeRegistry } from './saved_objects_type_registry'; export type { ISavedObjectTypeRegistry } from './saved_objects_type_registry'; +export { CoreSavedObjectsRouteHandlerContext } from './saved_objects_route_handler_context'; +export type { SavedObjectsRequestHandlerContext } from './saved_objects_route_handler_context'; diff --git a/src/core/server/saved_objects/internal_types.ts b/src/core/server/saved_objects/internal_types.ts new file mode 100644 index 0000000000000..6d3851fca120b --- /dev/null +++ b/src/core/server/saved_objects/internal_types.ts @@ -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 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 { RequestHandlerContextBase } from '..'; +import type { IRouter } from '../http'; +import type { ElasticsearchRequestHandlerContext } from '../elasticsearch'; +import type { SavedObjectsRequestHandlerContext } from './saved_objects_route_handler_context'; + +/** + * Request handler context used by core's savedObjects routes. + * @internal + */ +export interface InternalSavedObjectsRequestHandlerContext extends RequestHandlerContextBase { + core: Promise<{ + savedObjects: SavedObjectsRequestHandlerContext; + elasticsearch: ElasticsearchRequestHandlerContext; + }>; +} + +/** + * Router bound to the {@link InternalSavedObjectsRequestHandlerContext}. + * Used by core's savedObjects routes. + * @internal + */ +export type InternalSavedObjectRouter = IRouter; diff --git a/src/core/server/saved_objects/routes/bulk_create.ts b/src/core/server/saved_objects/routes/bulk_create.ts index b72cd6715fa10..6a671c830ca69 100644 --- a/src/core/server/saved_objects/routes/bulk_create.ts +++ b/src/core/server/saved_objects/routes/bulk_create.ts @@ -7,15 +7,18 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerBulkCreateRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerBulkCreateRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.post( { path: '/_bulk_create', diff --git a/src/core/server/saved_objects/routes/bulk_get.ts b/src/core/server/saved_objects/routes/bulk_get.ts index 87b6a604ac6c4..ba485c832ca65 100644 --- a/src/core/server/saved_objects/routes/bulk_get.ts +++ b/src/core/server/saved_objects/routes/bulk_get.ts @@ -7,15 +7,18 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerBulkGetRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerBulkGetRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.post( { path: '/_bulk_get', diff --git a/src/core/server/saved_objects/routes/bulk_resolve.ts b/src/core/server/saved_objects/routes/bulk_resolve.ts index 5754ec180541c..e689e243ebc95 100644 --- a/src/core/server/saved_objects/routes/bulk_resolve.ts +++ b/src/core/server/saved_objects/routes/bulk_resolve.ts @@ -7,15 +7,18 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerBulkResolveRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerBulkResolveRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.post( { path: '/_bulk_resolve', diff --git a/src/core/server/saved_objects/routes/bulk_update.ts b/src/core/server/saved_objects/routes/bulk_update.ts index 961b8349d1745..2edfa23ed8786 100644 --- a/src/core/server/saved_objects/routes/bulk_update.ts +++ b/src/core/server/saved_objects/routes/bulk_update.ts @@ -7,15 +7,18 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerBulkUpdateRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerBulkUpdateRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.put( { path: '/_bulk_update', diff --git a/src/core/server/saved_objects/routes/create.ts b/src/core/server/saved_objects/routes/create.ts index eb3938db0a9c7..282cbafc0b2f5 100644 --- a/src/core/server/saved_objects/routes/create.ts +++ b/src/core/server/saved_objects/routes/create.ts @@ -7,15 +7,18 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerCreateRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerCreateRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.post( { path: '/{type}/{id?}', diff --git a/src/core/server/saved_objects/routes/delete.ts b/src/core/server/saved_objects/routes/delete.ts index 5c239a55a6923..7410a237d39f7 100644 --- a/src/core/server/saved_objects/routes/delete.ts +++ b/src/core/server/saved_objects/routes/delete.ts @@ -7,15 +7,18 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerDeleteRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerDeleteRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.delete( { path: '/{type}/{id}', diff --git a/src/core/server/saved_objects/routes/deprecations/delete_unknown_types.ts b/src/core/server/saved_objects/routes/deprecations/delete_unknown_types.ts index a30da9723b916..5d36994928363 100644 --- a/src/core/server/saved_objects/routes/deprecations/delete_unknown_types.ts +++ b/src/core/server/saved_objects/routes/deprecations/delete_unknown_types.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { IRouter } from '../../../http'; import { catchAndReturnBoomErrors } from '../utils'; +import type { InternalSavedObjectRouter } from '../../internal_types'; import { deleteUnknownTypeObjects } from '../../deprecations'; interface RouteDependencies { @@ -16,7 +16,7 @@ interface RouteDependencies { } export const registerDeleteUnknownTypesRoute = ( - router: IRouter, + router: InternalSavedObjectRouter, { kibanaIndex, kibanaVersion }: RouteDependencies ) => { router.post( diff --git a/src/core/server/saved_objects/routes/export.ts b/src/core/server/saved_objects/routes/export.ts index 16547970369c2..e011c71575080 100644 --- a/src/core/server/saved_objects/routes/export.ts +++ b/src/core/server/saved_objects/routes/export.ts @@ -10,7 +10,7 @@ import { schema } from '@kbn/config-schema'; import stringify from 'json-stable-stringify'; import { createPromiseFromStreams, createMapStream, createConcatStream } from '@kbn/utils'; -import { IRouter, KibanaRequest } from '../../http'; +import { KibanaRequest } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; import { SavedObjectConfig } from '../saved_objects_config'; import { @@ -18,6 +18,7 @@ import { SavedObjectsExportByObjectOptions, SavedObjectsExportError, } from '../export'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { validateTypes, validateObjects, catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { @@ -129,7 +130,7 @@ const validateOptions = ( }; export const registerExportRoute = ( - router: IRouter, + router: InternalSavedObjectRouter, { config, coreUsageData }: RouteDependencies ) => { const { maxImportExportSize } = config; diff --git a/src/core/server/saved_objects/routes/find.ts b/src/core/server/saved_objects/routes/find.ts index 01ac9ae9025f4..7ebfef5be7c39 100644 --- a/src/core/server/saved_objects/routes/find.ts +++ b/src/core/server/saved_objects/routes/find.ts @@ -7,15 +7,18 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerFindRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerFindRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { const referenceSchema = schema.object({ type: schema.string(), id: schema.string(), diff --git a/src/core/server/saved_objects/routes/get.ts b/src/core/server/saved_objects/routes/get.ts index 2ea9a13bbce64..e7a2a779c4037 100644 --- a/src/core/server/saved_objects/routes/get.ts +++ b/src/core/server/saved_objects/routes/get.ts @@ -7,15 +7,18 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerGetRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerGetRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.get( { path: '/{type}/{id}', diff --git a/src/core/server/saved_objects/routes/import.ts b/src/core/server/saved_objects/routes/import.ts index 545d01b454741..0c56acf9e2d68 100644 --- a/src/core/server/saved_objects/routes/import.ts +++ b/src/core/server/saved_objects/routes/import.ts @@ -9,10 +9,10 @@ import { Readable } from 'stream'; import { extname } from 'path'; import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; import { SavedObjectConfig } from '../saved_objects_config'; import { SavedObjectsImportError } from '../import'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, createSavedObjectsStreamFromNdJson } from './utils'; interface RouteDependencies { @@ -27,7 +27,7 @@ interface FileStream extends Readable { } export const registerImportRoute = ( - router: IRouter, + router: InternalSavedObjectRouter, { config, coreUsageData }: RouteDependencies ) => { const { maxImportPayloadBytes } = config; diff --git a/src/core/server/saved_objects/routes/index.ts b/src/core/server/saved_objects/routes/index.ts index f76f802928190..34083e0d6ddf8 100644 --- a/src/core/server/saved_objects/routes/index.ts +++ b/src/core/server/saved_objects/routes/index.ts @@ -11,6 +11,7 @@ import { InternalHttpServiceSetup } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; import { SavedObjectConfig } from '../saved_objects_config'; import { IKibanaMigrator } from '../migrations'; +import type { InternalSavedObjectsRequestHandlerContext } from '../internal_types'; import { registerGetRoute } from './get'; import { registerResolveRoute } from './resolve'; import { registerCreateRoute } from './create'; @@ -46,7 +47,8 @@ export function registerRoutes({ kibanaVersion: string; kibanaIndex: string; }) { - const router = http.createRouter('/api/saved_objects/'); + const router = + http.createRouter('/api/saved_objects/'); registerGetRoute(router, { coreUsageData }); registerResolveRoute(router, { coreUsageData }); @@ -62,7 +64,7 @@ export function registerRoutes({ registerImportRoute(router, { config, coreUsageData }); registerResolveImportErrorsRoute(router, { config, coreUsageData }); - const legacyRouter = http.createRouter(''); + const legacyRouter = http.createRouter(''); registerLegacyImportRoute(legacyRouter, { maxImportPayloadBytes: config.maxImportPayloadBytes, coreUsageData, @@ -70,7 +72,9 @@ export function registerRoutes({ }); registerLegacyExportRoute(legacyRouter, { kibanaVersion, coreUsageData, logger }); - const internalRouter = http.createRouter('/internal/saved_objects/'); + const internalRouter = http.createRouter( + '/internal/saved_objects/' + ); registerMigrateRoute(internalRouter, migratorPromise); registerDeleteUnknownTypesRoute(internalRouter, { kibanaIndex, kibanaVersion }); diff --git a/src/core/server/saved_objects/routes/integration_tests/bulk_create.test.ts b/src/core/server/saved_objects/routes/integration_tests/bulk_create.test.ts index eeec6bd6b0be0..c34ea099d0ec8 100644 --- a/src/core/server/saved_objects/routes/integration_tests/bulk_create.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/bulk_create.test.ts @@ -13,6 +13,7 @@ import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -28,7 +29,8 @@ describe('POST /api/saved_objects/_bulk_create', () => { savedObjectsClient = handlerContext.savedObjects.client; savedObjectsClient.bulkCreate.mockResolvedValue({ saved_objects: [] }); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkCreate.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/bulk_get.test.ts b/src/core/server/saved_objects/routes/integration_tests/bulk_get.test.ts index f389307d45c41..a82a5351e9949 100644 --- a/src/core/server/saved_objects/routes/integration_tests/bulk_get.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/bulk_get.test.ts @@ -13,6 +13,7 @@ import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -30,7 +31,8 @@ describe('POST /api/saved_objects/_bulk_get', () => { savedObjectsClient.bulkGet.mockResolvedValue({ saved_objects: [], }); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkGet.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/bulk_resolve.test.ts b/src/core/server/saved_objects/routes/integration_tests/bulk_resolve.test.ts index bb5067a13ba3e..90f06368468be 100644 --- a/src/core/server/saved_objects/routes/integration_tests/bulk_resolve.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/bulk_resolve.test.ts @@ -13,6 +13,7 @@ import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -30,7 +31,8 @@ describe('POST /api/saved_objects/_bulk_resolve', () => { savedObjectsClient.bulkResolve.mockResolvedValue({ resolved_objects: [], }); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkResolve.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/bulk_update.test.ts b/src/core/server/saved_objects/routes/integration_tests/bulk_update.test.ts index 8c55686b2fd0f..d92041bce3c72 100644 --- a/src/core/server/saved_objects/routes/integration_tests/bulk_update.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/bulk_update.test.ts @@ -13,6 +13,7 @@ import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -27,7 +28,8 @@ describe('PUT /api/saved_objects/_bulk_update', () => { ({ server, httpSetup, handlerContext } = await setupServer()); savedObjectsClient = handlerContext.savedObjects.client; - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkUpdate.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/create.test.ts b/src/core/server/saved_objects/routes/integration_tests/create.test.ts index 9d65843271cc0..e4f566c769234 100644 --- a/src/core/server/saved_objects/routes/integration_tests/create.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/create.test.ts @@ -13,6 +13,7 @@ import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -37,7 +38,8 @@ describe('POST /api/saved_objects/{type}', () => { savedObjectsClient = handlerContext.savedObjects.client; savedObjectsClient.create.mockImplementation(() => Promise.resolve(clientResponse)); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsCreate.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts index 84a2db60b587a..849b99b49fbc0 100644 --- a/src/core/server/saved_objects/routes/integration_tests/delete.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/delete.test.ts @@ -13,6 +13,7 @@ import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -28,7 +29,8 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => { savedObjectsClient = handlerContext.savedObjects.getClient(); handlerContext.savedObjects.getClient = jest.fn().mockImplementation(() => savedObjectsClient); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsDelete.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/delete_unknown_types.test.ts b/src/core/server/saved_objects/routes/integration_tests/delete_unknown_types.test.ts index 60d916744babc..87376de206810 100644 --- a/src/core/server/saved_objects/routes/integration_tests/delete_unknown_types.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/delete_unknown_types.test.ts @@ -12,6 +12,7 @@ import { elasticsearchServiceMock } from '../../../elasticsearch/elasticsearch_s import { typeRegistryMock } from '../../saved_objects_type_registry.mock'; import { setupServer } from '../test_utils'; import { SavedObjectsType } from '../../..'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -37,7 +38,9 @@ describe('POST /internal/saved_objects/deprecations/_delete_unknown_types', () = handlerContext.elasticsearch.client.asCurrentUser = elasticsearchClient.asCurrentUser; handlerContext.elasticsearch.client.asInternalUser = elasticsearchClient.asInternalUser; - const router = httpSetup.createRouter('/internal/saved_objects/'); + const router = httpSetup.createRouter( + '/internal/saved_objects/' + ); registerDeleteUnknownTypesRoute(router, { kibanaVersion, kibanaIndex, diff --git a/src/core/server/saved_objects/routes/integration_tests/export.test.ts b/src/core/server/saved_objects/routes/integration_tests/export.test.ts index 1227d2636c555..9bdd6f39abbd0 100644 --- a/src/core/server/saved_objects/routes/integration_tests/export.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/export.test.ts @@ -19,6 +19,7 @@ import { savedObjectsExporterMock } from '../../export/saved_objects_exporter.mo import { SavedObjectConfig } from '../../saved_objects_config'; import { registerExportRoute } from '../export'; import { setupServer, createExportableType } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; const allowedTypes = ['index-pattern', 'search']; @@ -41,7 +42,8 @@ describe('POST /api/saved_objects/_export', () => { ); exporter = handlerContext.savedObjects.getExporter(); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); handlerContext.savedObjects.getExporter = jest .fn() .mockImplementation(() => exporter as ReturnType); diff --git a/src/core/server/saved_objects/routes/integration_tests/find.test.ts b/src/core/server/saved_objects/routes/integration_tests/find.test.ts index c18044f8973b8..8758666bc487d 100644 --- a/src/core/server/saved_objects/routes/integration_tests/find.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/find.test.ts @@ -15,6 +15,7 @@ import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -38,7 +39,8 @@ describe('GET /api/saved_objects/_find', () => { savedObjectsClient.find.mockResolvedValue(clientResponse); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsFind.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/get.test.ts b/src/core/server/saved_objects/routes/integration_tests/get.test.ts index 98d9d9170e5eb..8b34c9f2ef958 100644 --- a/src/core/server/saved_objects/routes/integration_tests/get.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/get.test.ts @@ -17,6 +17,7 @@ import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_da import { HttpService, InternalHttpServiceSetup } from '../../../http'; import { createHttpServer, createCoreContext } from '../../../http/test_utils'; import { contextServiceMock, coreMock } from '../../../mocks'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; const coreId = Symbol('core'); @@ -41,11 +42,16 @@ describe('GET /api/saved_objects/{type}/{id}', () => { handlerContext = coreMock.createRequestHandlerContext(); savedObjectsClient = handlerContext.savedObjects.client; - httpSetup.registerRouteHandlerContext(coreId, 'core', async (ctx, req, res) => { - return handlerContext; - }); + httpSetup.registerRouteHandlerContext( + coreId, + 'core', + (ctx, req, res) => { + return handlerContext; + } + ); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsGet.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/integration_tests/import.test.ts index 2f6f206366766..9e6e52977b2e1 100644 --- a/src/core/server/saved_objects/routes/integration_tests/import.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/import.test.ts @@ -17,6 +17,7 @@ import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_da import { SavedObjectConfig } from '../../saved_objects_config'; import { setupServer, createExportableType } from '../test_utils'; import { SavedObjectsErrorHelpers, SavedObjectsImporter } from '../..'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -69,7 +70,9 @@ describe(`POST ${URL}`, () => { .fn() .mockImplementation(() => importer as jest.Mocked); - const router = httpSetup.createRouter('/internal/saved_objects/'); + const router = httpSetup.createRouter( + '/internal/saved_objects/' + ); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsImport.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/resolve.test.ts b/src/core/server/saved_objects/routes/integration_tests/resolve.test.ts index f551abda188ef..78397ca00cb60 100644 --- a/src/core/server/saved_objects/routes/integration_tests/resolve.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/resolve.test.ts @@ -17,6 +17,7 @@ import { executionContextServiceMock } from '@kbn/core-execution-context-server- import { HttpService, InternalHttpServiceSetup } from '../../../http'; import { createHttpServer, createCoreContext } from '../../../http/test_utils'; import { contextServiceMock, coreMock } from '../../../mocks'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; const coreId = Symbol('core'); @@ -41,11 +42,16 @@ describe('GET /api/saved_objects/resolve/{type}/{id}', () => { handlerContext = coreMock.createRequestHandlerContext(); savedObjectsClient = handlerContext.savedObjects.client; - httpSetup.registerRouteHandlerContext(coreId, 'core', async (ctx, req, res) => { - return handlerContext; - }); + httpSetup.registerRouteHandlerContext( + coreId, + 'core', + (ctx, req, res) => { + return handlerContext; + } + ); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsResolve.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts index dfc69edaff420..101cf05032618 100644 --- a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts @@ -17,6 +17,7 @@ import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_da import { setupServer, createExportableType } from '../test_utils'; import { SavedObjectConfig } from '../../saved_objects_config'; import { SavedObjectsImporter } from '../..'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -76,7 +77,8 @@ describe(`POST ${URL}`, () => { .fn() .mockImplementation(() => importer as jest.Mocked); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsResolveImportErrors.mockRejectedValue( new Error('Oh no!') // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail diff --git a/src/core/server/saved_objects/routes/integration_tests/update.test.ts b/src/core/server/saved_objects/routes/integration_tests/update.test.ts index 78e7b9c1e93d5..1a41d94b0febe 100644 --- a/src/core/server/saved_objects/routes/integration_tests/update.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/update.test.ts @@ -13,6 +13,7 @@ import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer } from '../test_utils'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../internal_types'; type SetupServerReturn = Awaited>; @@ -38,7 +39,8 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => { savedObjectsClient = handlerContext.savedObjects.client; savedObjectsClient.update.mockResolvedValue(clientResponse); - const router = httpSetup.createRouter('/api/saved_objects/'); + const router = + httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsUpdate.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); diff --git a/src/core/server/saved_objects/routes/legacy_import_export/export.ts b/src/core/server/saved_objects/routes/legacy_import_export/export.ts index 7141d74b71904..9073090de8fe7 100644 --- a/src/core/server/saved_objects/routes/legacy_import_export/export.ts +++ b/src/core/server/saved_objects/routes/legacy_import_export/export.ts @@ -8,12 +8,13 @@ import moment from 'moment'; import { schema } from '@kbn/config-schema'; +import type { Logger } from '@kbn/logging'; import { InternalCoreUsageDataSetup } from '../../../core_usage_data'; -import { IRouter, Logger } from '../../..'; +import type { InternalSavedObjectRouter } from '../../internal_types'; import { exportDashboards } from './lib'; export const registerLegacyExportRoute = ( - router: IRouter, + router: InternalSavedObjectRouter, { kibanaVersion, coreUsageData, diff --git a/src/core/server/saved_objects/routes/legacy_import_export/import.ts b/src/core/server/saved_objects/routes/legacy_import_export/import.ts index d98c14f9b620d..d4a13b2973964 100644 --- a/src/core/server/saved_objects/routes/legacy_import_export/import.ts +++ b/src/core/server/saved_objects/routes/legacy_import_export/import.ts @@ -7,12 +7,14 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter, Logger, SavedObject } from '../../..'; +import type { Logger } from '@kbn/logging'; +import type { SavedObject } from '../../..'; import { InternalCoreUsageDataSetup } from '../../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../../internal_types'; import { importDashboards } from './lib'; export const registerLegacyImportRoute = ( - router: IRouter, + router: InternalSavedObjectRouter, { maxImportPayloadBytes, coreUsageData, diff --git a/src/core/server/saved_objects/routes/legacy_import_export/integration_tests/export.test.ts b/src/core/server/saved_objects/routes/legacy_import_export/integration_tests/export.test.ts index 6ae4a74aee014..7d0a8607fb6ed 100644 --- a/src/core/server/saved_objects/routes/legacy_import_export/integration_tests/export.test.ts +++ b/src/core/server/saved_objects/routes/legacy_import_export/integration_tests/export.test.ts @@ -38,6 +38,7 @@ import { coreUsageDataServiceMock } from '../../../../core_usage_data/core_usage import { registerLegacyExportRoute } from '../export'; import { setupServer } from '../../test_utils'; import { loggerMock } from '@kbn/logging-mocks'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../../internal_types'; type SetupServerReturn = Awaited>; let coreUsageStatsClient: jest.Mocked; @@ -49,7 +50,7 @@ describe('POST /api/dashboards/export', () => { beforeEach(async () => { ({ server, httpSetup } = await setupServer()); - const router = httpSetup.createRouter(''); + const router = httpSetup.createRouter(''); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementLegacyDashboardsExport.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail diff --git a/src/core/server/saved_objects/routes/legacy_import_export/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/legacy_import_export/integration_tests/import.test.ts index 13d5638440547..37f82aa47ece5 100644 --- a/src/core/server/saved_objects/routes/legacy_import_export/integration_tests/import.test.ts +++ b/src/core/server/saved_objects/routes/legacy_import_export/integration_tests/import.test.ts @@ -38,6 +38,7 @@ import { coreUsageDataServiceMock } from '../../../../core_usage_data/core_usage import { registerLegacyImportRoute } from '../import'; import { setupServer } from '../../test_utils'; import { loggerMock } from '@kbn/logging-mocks'; +import type { InternalSavedObjectsRequestHandlerContext } from '../../../internal_types'; type SetupServerReturn = Awaited>; let coreUsageStatsClient: jest.Mocked; @@ -49,7 +50,7 @@ describe('POST /api/dashboards/import', () => { beforeEach(async () => { ({ server, httpSetup } = await setupServer()); - const router = httpSetup.createRouter(''); + const router = httpSetup.createRouter(''); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementLegacyDashboardsImport.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail diff --git a/src/core/server/saved_objects/routes/migrate.ts b/src/core/server/saved_objects/routes/migrate.ts index 404074124c92b..05579855cbfc3 100644 --- a/src/core/server/saved_objects/routes/migrate.ts +++ b/src/core/server/saved_objects/routes/migrate.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import { IRouter } from '../../http'; import { IKibanaMigrator } from '../migrations'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; export const registerMigrateRoute = ( - router: IRouter, + router: InternalSavedObjectRouter, migratorPromise: Promise ) => { router.post( diff --git a/src/core/server/saved_objects/routes/resolve.ts b/src/core/server/saved_objects/routes/resolve.ts index ae09f6526baa3..b0a7153e8d226 100644 --- a/src/core/server/saved_objects/routes/resolve.ts +++ b/src/core/server/saved_objects/routes/resolve.ts @@ -7,14 +7,17 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; +import type { InternalSavedObjectRouter } from '../internal_types'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerResolveRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerResolveRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.get( { path: '/resolve/{type}/{id}', diff --git a/src/core/server/saved_objects/routes/resolve_import_errors.ts b/src/core/server/saved_objects/routes/resolve_import_errors.ts index bf536e906d7da..4bedec1715a4f 100644 --- a/src/core/server/saved_objects/routes/resolve_import_errors.ts +++ b/src/core/server/saved_objects/routes/resolve_import_errors.ts @@ -10,11 +10,12 @@ import { extname } from 'path'; import { Readable } from 'stream'; import { schema } from '@kbn/config-schema'; import { chain } from 'lodash'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; import { SavedObjectConfig } from '../saved_objects_config'; import { SavedObjectsImportError } from '../import'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, createSavedObjectsStreamFromNdJson } from './utils'; + interface RouteDependencies { config: SavedObjectConfig; coreUsageData: InternalCoreUsageDataSetup; @@ -27,7 +28,7 @@ interface FileStream extends Readable { } export const registerResolveImportErrorsRoute = ( - router: IRouter, + router: InternalSavedObjectRouter, { config, coreUsageData }: RouteDependencies ) => { const { maxImportPayloadBytes } = config; diff --git a/src/core/server/saved_objects/routes/test_utils.ts b/src/core/server/saved_objects/routes/test_utils.ts index 0d5e7588ad6ce..5783ecb9e5e27 100644 --- a/src/core/server/saved_objects/routes/test_utils.ts +++ b/src/core/server/saved_objects/routes/test_utils.ts @@ -11,6 +11,7 @@ import { ContextService } from '../../context'; import { createHttpServer, createCoreContext } from '../../http/test_utils'; import { contextServiceMock, coreMock } from '../../mocks'; import { SavedObjectsType } from '../types'; +import { InternalSavedObjectsRequestHandlerContext } from '../internal_types'; const defaultCoreId = Symbol('core'); @@ -26,9 +27,13 @@ export const setupServer = async (coreId: symbol = defaultCoreId) => { }); const handlerContext = coreMock.createRequestHandlerContext(); - httpSetup.registerRouteHandlerContext(coreId, 'core', async (ctx, req, res) => { - return handlerContext; - }); + httpSetup.registerRouteHandlerContext( + coreId, + 'core', + (ctx, req, res) => { + return handlerContext; + } + ); return { server, diff --git a/src/core/server/saved_objects/routes/update.ts b/src/core/server/saved_objects/routes/update.ts index 5383ab76a1e4d..3d68c6a698a04 100644 --- a/src/core/server/saved_objects/routes/update.ts +++ b/src/core/server/saved_objects/routes/update.ts @@ -7,16 +7,19 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { InternalCoreUsageDataSetup } from '../../core_usage_data'; import type { SavedObjectsUpdateOptions } from '../service/saved_objects_client'; +import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; } -export const registerUpdateRoute = (router: IRouter, { coreUsageData }: RouteDependencies) => { +export const registerUpdateRoute = ( + router: InternalSavedObjectRouter, + { coreUsageData }: RouteDependencies +) => { router.put( { path: '/{type}/{id}', diff --git a/src/core/server/saved_objects/saved_objects_route_handler_context.ts b/src/core/server/saved_objects/saved_objects_route_handler_context.ts new file mode 100644 index 0000000000000..bda45de389c98 --- /dev/null +++ b/src/core/server/saved_objects/saved_objects_route_handler_context.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 type { KibanaRequest } from '../http'; +import type { InternalSavedObjectsServiceStart } from './saved_objects_service'; +import type { ISavedObjectTypeRegistry } from './saved_objects_type_registry'; +import type { SavedObjectsClientContract } from './types'; +import type { SavedObjectsClientProviderOptions } from './service'; +import type { ISavedObjectsExporter } from './export'; +import type { ISavedObjectsImporter } from './import'; + +/** + * Core's `savedObjects` request handler context. + * @public + */ +export interface SavedObjectsRequestHandlerContext { + client: SavedObjectsClientContract; + typeRegistry: ISavedObjectTypeRegistry; + getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract; + getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; + getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; +} + +/** + * The {@link SavedObjectsRequestHandlerContext} implementation. + * @internal + */ +export class CoreSavedObjectsRouteHandlerContext implements SavedObjectsRequestHandlerContext { + constructor( + private readonly savedObjectsStart: InternalSavedObjectsServiceStart, + private readonly request: KibanaRequest + ) {} + + #scopedSavedObjectsClient?: SavedObjectsClientContract; + #typeRegistry?: ISavedObjectTypeRegistry; + + public get client() { + if (this.#scopedSavedObjectsClient == null) { + this.#scopedSavedObjectsClient = this.savedObjectsStart.getScopedClient(this.request); + } + return this.#scopedSavedObjectsClient; + } + + public get typeRegistry() { + if (this.#typeRegistry == null) { + this.#typeRegistry = this.savedObjectsStart.getTypeRegistry(); + } + return this.#typeRegistry; + } + + public getClient = (options?: SavedObjectsClientProviderOptions) => { + if (!options) return this.client; + return this.savedObjectsStart.getScopedClient(this.request, options); + }; + + public getExporter = (client: SavedObjectsClientContract) => { + return this.savedObjectsStart.createExporter(client); + }; + + public getImporter = (client: SavedObjectsClientContract) => { + return this.savedObjectsStart.createImporter(client); + }; +} diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 23586396bf62b..3f877d31eec3a 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -57,6 +57,7 @@ import { CoreRouteHandlerContext } from './core_route_handler_context'; import { PrebootCoreRouteHandlerContext } from './preboot_core_route_handler_context'; import { PrebootService } from './preboot'; import { DiscoveredPlugins } from './plugins'; +import type { RequestHandlerContext, PrebootRequestHandlerContext } from '.'; const coreId = Symbol('core'); const rootConfigPath = ''; @@ -208,9 +209,13 @@ export class Server { await this.plugins.preboot(corePreboot); - httpPreboot.registerRouteHandlerContext(coreId, 'core', (() => { - return new PrebootCoreRouteHandlerContext(corePreboot); - }) as any); + httpPreboot.registerRouteHandlerContext( + coreId, + 'core', + () => { + return new PrebootCoreRouteHandlerContext(corePreboot); + } + ); this.coreApp.preboot(corePreboot, uiPlugins); @@ -413,9 +418,13 @@ export class Server { } private registerCoreContext(coreSetup: InternalCoreSetup) { - coreSetup.http.registerRouteHandlerContext(coreId, 'core', async (context, req, res) => { - return new CoreRouteHandlerContext(this.coreStart!, req); - }); + coreSetup.http.registerRouteHandlerContext( + coreId, + 'core', + (context, req) => { + return new CoreRouteHandlerContext(this.coreStart!, req); + } + ); } public setupCoreConfig() { diff --git a/src/core/server/ui_settings/index.ts b/src/core/server/ui_settings/index.ts index d83d9c4358621..ee8cd7181fe8d 100644 --- a/src/core/server/ui_settings/index.ts +++ b/src/core/server/ui_settings/index.ts @@ -10,6 +10,8 @@ export type { UiSettingsClient, UiSettingsServiceOptions } from './ui_settings_c export { config } from './ui_settings_config'; export { UiSettingsService } from './ui_settings_service'; +export { CoreUiSettingsRouteHandlerContext } from './ui_settings_route_handler_context'; +export type { UiSettingsRequestHandlerContext } from './ui_settings_route_handler_context'; export type { UiSettingsServiceSetup, diff --git a/src/core/server/ui_settings/internal_types.ts b/src/core/server/ui_settings/internal_types.ts new file mode 100644 index 0000000000000..4292cca94ffbd --- /dev/null +++ b/src/core/server/ui_settings/internal_types.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 type { RequestHandlerContextBase } from '..'; +import type { IRouter } from '../http'; +import type { UiSettingsRequestHandlerContext } from './ui_settings_route_handler_context'; + +/** + * Request handler context used by core's uiSetting routes. + * @internal + */ +export interface InternalUiSettingsRequestHandlerContext extends RequestHandlerContextBase { + core: Promise<{ + uiSettings: UiSettingsRequestHandlerContext; + }>; +} + +/** + * Router bound to the {@link InternalUiSettingsRequestHandlerContext}. + * Used by core's uiSetting routes. + * @internal + */ +export type InternalUiSettingsRouter = IRouter; diff --git a/src/core/server/ui_settings/routes/delete.ts b/src/core/server/ui_settings/routes/delete.ts index 87c6edf386428..705a5319c1cf5 100644 --- a/src/core/server/ui_settings/routes/delete.ts +++ b/src/core/server/ui_settings/routes/delete.ts @@ -8,8 +8,8 @@ import { schema } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { SavedObjectsErrorHelpers } from '../../saved_objects'; +import type { InternalUiSettingsRouter } from '../internal_types'; import { CannotOverrideError } from '../ui_settings_errors'; const validate = { @@ -18,7 +18,7 @@ const validate = { }), }; -export function registerDeleteRoute(router: IRouter) { +export function registerDeleteRoute(router: InternalUiSettingsRouter) { router.delete( { path: '/api/kibana/settings/{key}', validate }, async (context, request, response) => { diff --git a/src/core/server/ui_settings/routes/get.ts b/src/core/server/ui_settings/routes/get.ts index 0929330cf0238..c940c2e1fe71e 100644 --- a/src/core/server/ui_settings/routes/get.ts +++ b/src/core/server/ui_settings/routes/get.ts @@ -6,10 +6,10 @@ * Side Public License, v 1. */ -import { IRouter } from '../../http'; +import type { InternalUiSettingsRouter } from '../internal_types'; import { SavedObjectsErrorHelpers } from '../../saved_objects'; -export function registerGetRoute(router: IRouter) { +export function registerGetRoute(router: InternalUiSettingsRouter) { router.get( { path: '/api/kibana/settings', validate: false }, async (context, request, response) => { diff --git a/src/core/server/ui_settings/routes/index.ts b/src/core/server/ui_settings/routes/index.ts index 0cf7233b8af19..22ca2ae38cde5 100644 --- a/src/core/server/ui_settings/routes/index.ts +++ b/src/core/server/ui_settings/routes/index.ts @@ -6,14 +6,13 @@ * Side Public License, v 1. */ -import { IRouter } from '../..'; - +import type { InternalUiSettingsRouter } from '../internal_types'; import { registerDeleteRoute } from './delete'; import { registerGetRoute } from './get'; import { registerSetManyRoute } from './set_many'; import { registerSetRoute } from './set'; -export function registerRoutes(router: IRouter) { +export function registerRoutes(router: InternalUiSettingsRouter) { registerGetRoute(router); registerDeleteRoute(router); registerSetRoute(router); diff --git a/src/core/server/ui_settings/routes/set.ts b/src/core/server/ui_settings/routes/set.ts index 91518fb6f3476..af62fda0144b6 100644 --- a/src/core/server/ui_settings/routes/set.ts +++ b/src/core/server/ui_settings/routes/set.ts @@ -8,8 +8,8 @@ import { schema, ValidationError } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { SavedObjectsErrorHelpers } from '../../saved_objects'; +import type { InternalUiSettingsRouter } from '../internal_types'; import { CannotOverrideError } from '../ui_settings_errors'; const validate = { @@ -21,7 +21,7 @@ const validate = { }), }; -export function registerSetRoute(router: IRouter) { +export function registerSetRoute(router: InternalUiSettingsRouter) { router.post( { path: '/api/kibana/settings/{key}', validate }, async (context, request, response) => { diff --git a/src/core/server/ui_settings/routes/set_many.ts b/src/core/server/ui_settings/routes/set_many.ts index f4f3f509bf920..fe0ee1a0a721f 100644 --- a/src/core/server/ui_settings/routes/set_many.ts +++ b/src/core/server/ui_settings/routes/set_many.ts @@ -8,8 +8,8 @@ import { schema, ValidationError } from '@kbn/config-schema'; -import { IRouter } from '../../http'; import { SavedObjectsErrorHelpers } from '../../saved_objects'; +import type { InternalUiSettingsRouter } from '../internal_types'; import { CannotOverrideError } from '../ui_settings_errors'; const validate = { @@ -18,7 +18,7 @@ const validate = { }), }; -export function registerSetManyRoute(router: IRouter) { +export function registerSetManyRoute(router: InternalUiSettingsRouter) { router.post({ path: '/api/kibana/settings', validate }, async (context, request, response) => { try { const uiSettingsClient = (await context.core).uiSettings.client; diff --git a/src/core/server/ui_settings/ui_settings_route_handler_context.ts b/src/core/server/ui_settings/ui_settings_route_handler_context.ts new file mode 100644 index 0000000000000..a975f0faad6ef --- /dev/null +++ b/src/core/server/ui_settings/ui_settings_route_handler_context.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 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 { CoreSavedObjectsRouteHandlerContext } from '../saved_objects'; +import type { IUiSettingsClient, InternalUiSettingsServiceStart } from './types'; + +/** + * Core's `uiSettings` request handler context. + * @public + */ +export interface UiSettingsRequestHandlerContext { + client: IUiSettingsClient; +} + +/** + * The {@link UiSettingsRequestHandlerContext} implementation. + * @internal + */ +export class CoreUiSettingsRouteHandlerContext implements UiSettingsRequestHandlerContext { + #client?: IUiSettingsClient; + + constructor( + private readonly uiSettingsStart: InternalUiSettingsServiceStart, + private readonly savedObjectsRouterHandlerContext: CoreSavedObjectsRouteHandlerContext + ) {} + + public get client() { + if (this.#client == null) { + this.#client = this.uiSettingsStart.asScopedToClient( + this.savedObjectsRouterHandlerContext.client + ); + } + return this.#client; + } +} diff --git a/src/core/server/ui_settings/ui_settings_service.ts b/src/core/server/ui_settings/ui_settings_service.ts index d303060d55595..342514660e8d1 100644 --- a/src/core/server/ui_settings/ui_settings_service.ts +++ b/src/core/server/ui_settings/ui_settings_service.ts @@ -26,6 +26,7 @@ import { uiSettingsType } from './saved_objects'; import { registerRoutes } from './routes'; import { getCoreSettings } from './settings'; import { UiSettingsDefaultsClient } from './ui_settings_defaults_client'; +import type { InternalUiSettingsRequestHandlerContext } from './internal_types'; export interface SetupDeps { http: InternalHttpServiceSetup; @@ -70,7 +71,7 @@ export class UiSettingsService this.log.debug('Setting up ui settings service'); savedObjects.registerType(uiSettingsType); - registerRoutes(http.createRouter('')); + registerRoutes(http.createRouter('')); const config = await firstValueFrom(this.config$); this.overrides = config.overrides; diff --git a/src/plugins/usage_collection/server/routes/integration_tests/stats.test.ts b/src/plugins/usage_collection/server/routes/integration_tests/stats.test.ts index 4412eeb78c428..98531c2fec879 100644 --- a/src/plugins/usage_collection/server/routes/integration_tests/stats.test.ts +++ b/src/plugins/usage_collection/server/routes/integration_tests/stats.test.ts @@ -8,7 +8,12 @@ import { BehaviorSubject } from 'rxjs'; -import { MetricsServiceSetup, ServiceStatus, ServiceStatusLevels } from '@kbn/core/server'; +import { + MetricsServiceSetup, + RequestHandlerContext, + ServiceStatus, + ServiceStatusLevels, +} from '@kbn/core/server'; import { contextServiceMock, loggingSystemMock, @@ -42,7 +47,7 @@ describe('/api/stats', () => { }); metrics = metricsServiceMock.createSetupContract(); - const router = httpSetup.createRouter(''); + const router = httpSetup.createRouter(''); registerStatsRoute({ router, collectorSet: new CollectorSet({ diff --git a/x-pack/plugins/index_lifecycle_management/server/services/license.ts b/x-pack/plugins/index_lifecycle_management/server/services/license.ts index e51ecac56327e..4b3b1331ae444 100644 --- a/x-pack/plugins/index_lifecycle_management/server/services/license.ts +++ b/x-pack/plugins/index_lifecycle_management/server/services/license.ts @@ -57,12 +57,12 @@ export class License { }); } - guardApiRoute(handler: RequestHandler) { + guardApiRoute(handler: RequestHandler) { const license = this; return function licenseCheck( ctx: RequestHandlerContext, - request: KibanaRequest, + request: KibanaRequest, response: KibanaResponseFactory ) { const licenseStatus = license.getStatus(); diff --git a/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts b/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts index f780ee704e319..0d40b03f22081 100644 --- a/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts +++ b/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts @@ -8,7 +8,7 @@ import Boom from '@hapi/boom'; // @ts-ignore -import type { CoreSetup, IBasePath, IRouter } from '@kbn/core/server'; +import type { CoreSetup, IBasePath, IRouter, RequestHandlerContext } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import * as kbnTestServer from '@kbn/core/test_helpers/kbn_server'; @@ -153,7 +153,7 @@ describe.skip('onPostAuthInterceptor', () => { getSpacesService: () => spacesServiceStart, }); - const router = http.createRouter('/'); + const router = http.createRouter('/'); initKbnServer(router, http.basePath); diff --git a/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.test.ts b/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.test.ts index 8e3eb5a555212..7dd66381b4be3 100644 --- a/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.test.ts +++ b/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.test.ts @@ -12,6 +12,7 @@ import type { IRouter, KibanaRequest, KibanaResponseFactory, + RequestHandlerContext, } from '@kbn/core/server'; import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import * as kbnTestServer from '@kbn/core/test_helpers/kbn_server'; @@ -89,7 +90,7 @@ describe.skip('onRequestInterceptor', () => { http: http as unknown as CoreSetup['http'], }); - const router = http.createRouter('/'); + const router = http.createRouter('/'); initKbnServer(router, http.basePath); From 4ffb4e0c7ff1466925a2baaf940c55162a1e65c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Wed, 6 Jul 2022 11:07:48 +0200 Subject: [PATCH 23/81] Handle potential undefined values in es_error helpers (#135739) --- .../migrations/actions/es_errors.test.ts | 32 +++++++++++++++++++ .../migrations/actions/es_errors.ts | 23 +++++++------ 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/core/server/saved_objects/migrations/actions/es_errors.test.ts b/src/core/server/saved_objects/migrations/actions/es_errors.test.ts index b34366b7386d2..f0004851b1bf9 100644 --- a/src/core/server/saved_objects/migrations/actions/es_errors.test.ts +++ b/src/core/server/saved_objects/migrations/actions/es_errors.test.ts @@ -9,6 +9,7 @@ import { isClusterShardLimitExceeded, isIncompatibleMappingException, + isIndexNotFoundException, isWriteBlockException, } from './es_errors'; @@ -37,6 +38,9 @@ describe('isWriteBlockError', () => { }) ).toEqual(false); }); + it('returns false undefined', () => { + expect(isWriteBlockException(undefined)).toEqual(false); + }); }); describe('isIncompatibleMappingExceptionError', () => { @@ -57,6 +61,31 @@ describe('isIncompatibleMappingExceptionError', () => { }) ).toEqual(true); }); + it('returns false undefined', () => { + expect(isIncompatibleMappingException(undefined)).toEqual(false); + }); +}); + +describe('isIndexNotFoundException', () => { + it('returns true with index_not_found_exception errors', () => { + expect( + isIndexNotFoundException({ + type: 'index_not_found_exception', + reason: 'idk', + }) + ).toEqual(true); + }); + it('returns false for other errors', () => { + expect( + isIndexNotFoundException({ + type: 'validation_exception', + reason: 'idk', + }) + ).toEqual(false); + }); + it('returns false undefined', () => { + expect(isIndexNotFoundException(undefined)).toEqual(false); + }); }); describe('isClusterShardLimitExceeded', () => { @@ -77,4 +106,7 @@ describe('isClusterShardLimitExceeded', () => { }) ).toEqual(false); }); + it('returns false undefined', () => { + expect(isClusterShardLimitExceeded(undefined)).toEqual(false); + }); }); diff --git a/src/core/server/saved_objects/migrations/actions/es_errors.ts b/src/core/server/saved_objects/migrations/actions/es_errors.ts index 9f571d38ffd85..2bf432de032a6 100644 --- a/src/core/server/saved_objects/migrations/actions/es_errors.ts +++ b/src/core/server/saved_objects/migrations/actions/es_errors.ts @@ -7,25 +7,28 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -export const isWriteBlockException = ({ type, reason }: estypes.ErrorCause): boolean => { +export const isWriteBlockException = (errorCause?: estypes.ErrorCause): boolean => { return ( - type === 'cluster_block_exception' && - reason.match(/index \[.+] blocked by: \[FORBIDDEN\/8\/.+ \(api\)\]/) !== null + errorCause?.type === 'cluster_block_exception' && + errorCause?.reason.match(/index \[.+] blocked by: \[FORBIDDEN\/8\/.+ \(api\)\]/) !== null ); }; -export const isIncompatibleMappingException = ({ type }: estypes.ErrorCause): boolean => { - return type === 'strict_dynamic_mapping_exception' || type === 'mapper_parsing_exception'; +export const isIncompatibleMappingException = (errorCause?: estypes.ErrorCause): boolean => { + return ( + errorCause?.type === 'strict_dynamic_mapping_exception' || + errorCause?.type === 'mapper_parsing_exception' + ); }; -export const isIndexNotFoundException = ({ type }: estypes.ErrorCause): boolean => { - return type === 'index_not_found_exception'; +export const isIndexNotFoundException = (errorCause?: estypes.ErrorCause): boolean => { + return errorCause?.type === 'index_not_found_exception'; }; -export const isClusterShardLimitExceeded = ({ type, reason }: estypes.ErrorCause): boolean => { +export const isClusterShardLimitExceeded = (errorCause?: estypes.ErrorCause): boolean => { return ( - type === 'validation_exception' && - reason.match( + errorCause?.type === 'validation_exception' && + errorCause?.reason.match( /this action would add .* shards, but this cluster currently has .* maximum normal shards open/ ) !== null ); From 08ff6cca3d097bc4d5463d9a98a9d6b12310b2a2 Mon Sep 17 00:00:00 2001 From: Muhammad Ibragimov <53621505+mibragimov@users.noreply.github.com> Date: Wed, 6 Jul 2022 14:30:29 +0500 Subject: [PATCH 24/81] [Console] Render most severe response status code from Console response pane (#134627) * Render most severe response status in status bar * Add unit tests Co-authored-by: Muhammad Ibragimov Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../application/containers/main/main.tsx | 15 +++++++------- src/plugins/console/public/lib/utils/index.ts | 14 +++++++++++++ .../console/public/lib/utils/utils.test.js | 20 +++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/plugins/console/public/application/containers/main/main.tsx b/src/plugins/console/public/application/containers/main/main.tsx index 5895b919f9842..2833bf1fbebc3 100644 --- a/src/plugins/console/public/application/containers/main/main.tsx +++ b/src/plugins/console/public/application/containers/main/main.tsx @@ -26,6 +26,7 @@ import { useDataInit } from '../../hooks'; import { getTopNavConfig } from './get_top_nav'; import type { SenseEditor } from '../../models/sense_editor'; +import { getResponseWithMostSevereStatusCode } from '../../../lib/utils'; export function Main() { const { @@ -62,7 +63,7 @@ export function Main() { ); } - const lastDatum = requestData?.[requestData.length - 1] ?? requestError; + const data = getResponseWithMostSevereStatusCode(requestData) ?? requestError; return (
@@ -95,13 +96,13 @@ export function Main() { { + if (requestData) { + return requestData + .slice() + .sort((a, b) => a.response.statusCode - b.response.statusCode) + .pop(); + } +}; diff --git a/src/plugins/console/public/lib/utils/utils.test.js b/src/plugins/console/public/lib/utils/utils.test.js index 738aa5b9bf5c3..8cdd93c3b6ed8 100644 --- a/src/plugins/console/public/lib/utils/utils.test.js +++ b/src/plugins/console/public/lib/utils/utils.test.js @@ -173,4 +173,24 @@ describe('Utils class', () => { ]); }); }); + + test('get response with most severe status code', () => { + expect( + utils.getResponseWithMostSevereStatusCode([ + { response: { statusCode: 500 } }, + { response: { statusCode: 400 } }, + { response: { statusCode: 200 } }, + ]) + ).toEqual({ response: { statusCode: 500 } }); + + expect( + utils.getResponseWithMostSevereStatusCode([ + { response: { statusCode: 0 } }, + { response: { statusCode: 100 } }, + { response: { statusCode: 201 } }, + ]) + ).toEqual({ response: { statusCode: 201 } }); + + expect(utils.getResponseWithMostSevereStatusCode(undefined)).toBe(undefined); + }); }); From 90c08d38802885094dc315ee8da169c99bae93bb Mon Sep 17 00:00:00 2001 From: Ari Aviran Date: Wed, 6 Jul 2022 12:38:04 +0300 Subject: [PATCH 25/81] [Cloud Posture] Add navigation links to security solution grouped navigation (#135635) --- .github/CODEOWNERS | 1 + .../security_solution/common/constants.ts | 8 ++ .../common/experimental_features.ts | 4 + .../security_solution/public/cases/links.ts | 2 +- .../public/cloud_security_posture/index.ts | 17 ++++ .../public/cloud_security_posture/links.ts | 75 ++++++++++++++++++ .../public/cloud_security_posture/routes.tsx | 60 ++++++++++++++ .../solution_grouped_nav_panel.test.tsx | 24 ++++++ .../solution_grouped_nav_panel.tsx | 4 + .../cloud_security_posture_dashboard_page.png | Bin 0 -> 20262 bytes .../public/common/links/app_links.ts | 3 + .../public/landing_pages/links.ts | 5 +- .../public/lazy_sub_plugins.tsx | 3 + .../public/management/links.ts | 9 ++- .../security_solution/public/plugin.tsx | 2 + .../public/timelines/links.ts | 2 +- .../plugins/security_solution/public/types.ts | 5 +- 17 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/cloud_security_posture/index.ts create mode 100644 x-pack/plugins/security_solution/public/cloud_security_posture/links.ts create mode 100644 x-pack/plugins/security_solution/public/cloud_security_posture/routes.tsx create mode 100644 x-pack/plugins/security_solution/public/common/images/cloud_security_posture_dashboard_page.png diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f62d103124558..9c06ece1290ad 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -595,6 +595,7 @@ x-pack/plugins/security_solution/public/kubernetes @elastic/awp-platform # Cloud Security Posture /x-pack/plugins/cloud_security_posture/ @elastic/kibana-cloud-security-posture +/x-pack/plugins/security_solution/public/cloud_security_posture @elastic/kibana-cloud-security-posture # Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index e4cd5b70ca65e..86793045ad0cd 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -123,6 +123,10 @@ export enum SecurityPageName { exploreLanding = 'explore', dashboardsLanding = 'dashboards', noPage = '', + cloudSecurityPosture = 'cloud_security_posture', + cloudSecurityPostureDashboard = 'cloud_security_posture-dashboard', + cloudSecurityPostureFindings = 'cloud_security_posture-findings', + cloudSecurityPostureBenchmarks = 'cloud_security_posture-benchmarks', } export const EXPLORE_PATH = '/explore' as const; @@ -151,6 +155,10 @@ export const HOST_ISOLATION_EXCEPTIONS_PATH = `${MANAGEMENT_PATH}/host_isolation_exceptions` as const; export const BLOCKLIST_PATH = `${MANAGEMENT_PATH}/blocklist` as const; export const RESPONSE_ACTIONS_PATH = `${MANAGEMENT_PATH}/response_actions` as const; +export const CLOUD_SECURITY_POSTURE_PATH = '/cloud_security_posture' as const; +export const CLOUD_SECURITY_POSTURE_DASHBOARD_PATH = '/cloud_security_posture/dashboard' as const; +export const CLOUD_SECURITY_POSTURE_FINDINGS_PATH = '/cloud_security_posture/findings' as const; +export const CLOUD_SECURITY_POSTURE_BENCHMARKS_PATH = '/cloud_security_posture/benchmarks' as const; export const APP_OVERVIEW_PATH = `${APP_PATH}${OVERVIEW_PATH}` as const; export const APP_LANDING_PATH = `${APP_PATH}${LANDING_PATH}` as const; diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 8ba1a611af2b6..f22a0b4af5170 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -38,6 +38,10 @@ export const allowedExperimentalValues = Object.freeze({ * Enables the Endpoint response actions console in various areas of the app */ responseActionsConsoleEnabled: false, + /** + * Enables the cloud security posture navigation inside the security solution + */ + cloudSecurityPostureNavigation: false, }); type ExperimentalConfigKeys = Array; diff --git a/x-pack/plugins/security_solution/public/cases/links.ts b/x-pack/plugins/security_solution/public/cases/links.ts index bce1b84a23d2f..57e01813c77ed 100644 --- a/x-pack/plugins/security_solution/public/cases/links.ts +++ b/x-pack/plugins/security_solution/public/cases/links.ts @@ -15,7 +15,7 @@ export const getCasesLinkItems = (): LinkItem => { extend: { [SecurityPageName.case]: { globalNavEnabled: true, - globalNavOrder: 4, + globalNavOrder: 5, capabilities: [`${CASES_FEATURE_ID}.read_cases`], }, [SecurityPageName.caseConfigure]: { diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/index.ts b/x-pack/plugins/security_solution/public/cloud_security_posture/index.ts new file mode 100644 index 0000000000000..798658b15cd42 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/index.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 type { SecuritySubPlugin } from '../app/types'; +import { routes } from './routes'; + +export class CloudSecurityPosture { + public setup() {} + + public start(): SecuritySubPlugin { + return { routes }; + } +} diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/links.ts b/x-pack/plugins/security_solution/public/cloud_security_posture/links.ts new file mode 100644 index 0000000000000..f862f86fc7247 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/links.ts @@ -0,0 +1,75 @@ +/* + * 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'; +import { IconExceptionLists } from '../management/icons/exception_lists'; +import { + CLOUD_SECURITY_POSTURE_DASHBOARD_PATH, + CLOUD_SECURITY_POSTURE_FINDINGS_PATH, + CLOUD_SECURITY_POSTURE_BENCHMARKS_PATH, + SecurityPageName, +} from '../../common/constants'; +import type { LinkItem, LinkCategories } from '../common/links/types'; +import cloudSecurityPostureDashboardImage from '../common/images/cloud_security_posture_dashboard_page.png'; + +const commonLinkProperties: Partial = { + skipUrlState: true, + hideTimeline: true, + experimentalKey: 'cloudSecurityPostureNavigation', +}; + +export const rootLinks: LinkItem = { + id: SecurityPageName.cloudSecurityPostureFindings, + title: i18n.translate('xpack.securitySolution.appLinks.findings', { + defaultMessage: 'Findings ', + }), + path: CLOUD_SECURITY_POSTURE_FINDINGS_PATH, + globalNavEnabled: true, + globalNavOrder: 3, + ...commonLinkProperties, +}; + +export const dashboardLinks: LinkItem = { + id: SecurityPageName.cloudSecurityPostureDashboard, + title: i18n.translate('xpack.securitySolution.appLinks.cloudSecurityPostureDashboard', { + defaultMessage: 'Cloud Posture', + }), + path: CLOUD_SECURITY_POSTURE_DASHBOARD_PATH, + description: i18n.translate( + 'xpack.securitySolution.appLinks.cloudSecurityPostureDashboardDescription', + { + defaultMessage: 'An overview of findings across all CSP integrations.', + } + ), + landingImage: cloudSecurityPostureDashboardImage, + ...commonLinkProperties, +}; + +export const manageLinks: LinkItem = { + id: SecurityPageName.cloudSecurityPostureBenchmarks, + title: i18n.translate('xpack.securitySolution.appLinks.cloudSecurityPostureBenchmarks', { + defaultMessage: 'CSP Benchmarks', + }), + path: CLOUD_SECURITY_POSTURE_BENCHMARKS_PATH, + description: i18n.translate( + 'xpack.securitySolution.appLinks.cloudSecurityPostureBenchmarksDescription', + { + defaultMessage: 'View, enable, and or disable benchmark rules.', + } + ), + // TODO: Temporary until we have a CSP icon + landingIcon: IconExceptionLists, + ...commonLinkProperties, +}; + +export const manageCategories: LinkCategories = [ + { + label: i18n.translate('xpack.securitySolution.appLinks.category.cloudSecurityPosture', { + defaultMessage: 'CLOUD SECURITY POSTURE', + }), + linkIds: [SecurityPageName.cloudSecurityPostureBenchmarks], + }, +]; diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/routes.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/routes.tsx new file mode 100644 index 0000000000000..14cc141e30430 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/routes.tsx @@ -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 { EuiTitle } from '@elastic/eui'; +import React from 'react'; +import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; +import { SecuritySolutionPageWrapper } from '../common/components/page_wrapper'; +import { SpyRoute } from '../common/utils/route/spy_routes'; +import { + CLOUD_SECURITY_POSTURE_BENCHMARKS_PATH, + CLOUD_SECURITY_POSTURE_DASHBOARD_PATH, + CLOUD_SECURITY_POSTURE_FINDINGS_PATH, + CLOUD_SECURITY_POSTURE_PATH, + SecurityPageName, +} from '../../common/constants'; +import type { SecuritySubPluginRoutes } from '../app/types'; + +const CloudSecurityPosture = ({ pageName }: { pageName: SecurityPageName }) => { + return ( + + + + +

{'Coming soon'}

+
+
+
+ ); +}; + +// TODO: We'll probably use a single route here, and we'll manage all CSP pages in an internal router in the CSP plugin. +// For now we have multiple routes as we need `SpyRoute` to use a specific `pageName` for highlighting the correct +// navigation bar entry +export const routes: SecuritySubPluginRoutes = [ + { + path: CLOUD_SECURITY_POSTURE_PATH, + render: () => , + exact: true, + }, + { + path: CLOUD_SECURITY_POSTURE_FINDINGS_PATH, + render: () => , + }, + { + path: CLOUD_SECURITY_POSTURE_DASHBOARD_PATH, + render: () => ( + + ), + }, + { + path: CLOUD_SECURITY_POSTURE_BENCHMARKS_PATH, + render: () => ( + + ), + }, +]; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.test.tsx index 3162df787af1c..ab05936ebd36a 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import type { LinkCategories } from '../../../links'; import React from 'react'; import { render, waitFor } from '@testing-library/react'; import { SecurityPageName } from '../../../../app/types'; @@ -37,6 +38,17 @@ const mockItems: DefaultSideNavItem[] = [ }, ]; +const mockCategories: LinkCategories = [ + { + label: 'HOSTS CATEGORY', + linkIds: [SecurityPageName.hosts], + }, + { + label: 'Empty category', + linkIds: [], + }, +]; + const PANEL_TITLE = 'test title'; const mockOnClose = jest.fn(); const mockOnOutsideClick = jest.fn(); @@ -75,6 +87,18 @@ describe('SolutionGroupedNav', () => { }); }); + it('should only render categories with items', () => { + const result = renderNavPanel({ categories: mockCategories }); + + mockCategories.forEach((mockCategory) => { + if (mockCategory.linkIds.length) { + expect(result.getByText(mockCategory.label)).toBeInTheDocument(); + } else { + expect(result.queryByText(mockCategory.label)).not.toBeInTheDocument(); + } + }); + }); + describe('links', () => { it('should contain correct href in links', () => { const result = renderNavPanel(); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.tsx index 4c0ccc6116703..a2773f2223247 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/solution_grouped_nav/solution_grouped_nav_panel.tsx @@ -138,6 +138,10 @@ const SolutionNavPanelCategories: React.FC = ({ return acc; }, []); + if (!links.length) { + return null; + } + return ( diff --git a/x-pack/plugins/security_solution/public/common/images/cloud_security_posture_dashboard_page.png b/x-pack/plugins/security_solution/public/common/images/cloud_security_posture_dashboard_page.png new file mode 100644 index 0000000000000000000000000000000000000000..de64f3be902cb6b4fca25f58b833fc101c1359d2 GIT binary patch literal 20262 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

0u=hb8@)n1fr4ry|b1B3IK%^`pAjio}?4{Fs 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 literal 0 HcmV?d00001 diff --git a/x-pack/plugins/security_solution/public/common/links/app_links.ts b/x-pack/plugins/security_solution/public/common/links/app_links.ts index fe870caa09c37..cd57f94c0407d 100644 --- a/x-pack/plugins/security_solution/public/common/links/app_links.ts +++ b/x-pack/plugins/security_solution/public/common/links/app_links.ts @@ -12,6 +12,7 @@ import { getCasesLinkItems } from '../../cases/links'; import { links as managementLinks, getManagementFilteredLinks } from '../../management/links'; import { dashboardsLandingLinks, threatHuntingLandingLinks } from '../../landing_pages/links'; import { gettingStartedLinks } from '../../overview/links'; +import { rootLinks as cloudSecurityPostureRootLinks } from '../../cloud_security_posture/links'; import { StartPlugins } from '../../types'; const casesLinks = getCasesLinkItems(); @@ -19,6 +20,7 @@ const casesLinks = getCasesLinkItems(); export const links = Object.freeze([ dashboardsLandingLinks, detectionLinks, + cloudSecurityPostureRootLinks, timelinesLinks, casesLinks, threatHuntingLandingLinks, @@ -35,6 +37,7 @@ export const getFilteredLinks = async ( return Object.freeze([ dashboardsLandingLinks, detectionLinks, + cloudSecurityPostureRootLinks, timelinesLinks, casesLinks, threatHuntingLandingLinks, diff --git a/x-pack/plugins/security_solution/public/landing_pages/links.ts b/x-pack/plugins/security_solution/public/landing_pages/links.ts index e840ab7cc8716..0a53aa88208b5 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/links.ts +++ b/x-pack/plugins/security_solution/public/landing_pages/links.ts @@ -19,6 +19,7 @@ import { links as hostsLinks } from '../hosts/links'; import { links as networkLinks } from '../network/links'; import { links as usersLinks } from '../users/links'; import { links as kubernetesLinks } from '../kubernetes/links'; +import { dashboardLinks as cloudSecurityPostureLinks } from '../cloud_security_posture/links'; export const dashboardsLandingLinks: LinkItem = { id: SecurityPageName.dashboardsLanding, @@ -32,7 +33,7 @@ export const dashboardsLandingLinks: LinkItem = { defaultMessage: 'Dashboards', }), ], - links: [overviewLinks, detectionResponseLinks, kubernetesLinks], + links: [overviewLinks, detectionResponseLinks, kubernetesLinks, cloudSecurityPostureLinks], skipUrlState: true, hideTimeline: true, }; @@ -42,7 +43,7 @@ export const threatHuntingLandingLinks: LinkItem = { title: EXPLORE, path: EXPLORE_PATH, globalNavEnabled: true, - globalNavOrder: 5, + globalNavOrder: 6, capabilities: [`${SERVER_APP_ID}.show`], globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.explore', { diff --git a/x-pack/plugins/security_solution/public/lazy_sub_plugins.tsx b/x-pack/plugins/security_solution/public/lazy_sub_plugins.tsx index abced3257c681..88b063dd037be 100644 --- a/x-pack/plugins/security_solution/public/lazy_sub_plugins.tsx +++ b/x-pack/plugins/security_solution/public/lazy_sub_plugins.tsx @@ -25,6 +25,8 @@ import { Timelines } from './timelines'; import { Management } from './management'; import { LandingPages } from './landing_pages'; +import { CloudSecurityPosture } from './cloud_security_posture'; + /** * The classes used to instantiate the sub plugins. These are grouped into a single object for the sake of bundling them in a single dynamic import. */ @@ -42,5 +44,6 @@ const subPluginClasses = { Timelines, Management, LandingPages, + CloudSecurityPosture, }; export { subPluginClasses }; diff --git a/x-pack/plugins/security_solution/public/management/links.ts b/x-pack/plugins/security_solution/public/management/links.ts index cdbdb50e9edd4..cf7e30793ba7f 100644 --- a/x-pack/plugins/security_solution/public/management/links.ts +++ b/x-pack/plugins/security_solution/public/management/links.ts @@ -37,7 +37,10 @@ import { import { licenseService } from '../common/hooks/use_license'; import { LinkItem } from '../common/links/types'; import { StartPlugins } from '../types'; - +import { + manageCategories as cloudSecurityPostureCategories, + manageLinks as cloudSecurityPostureLinks, +} from '../cloud_security_posture/links'; import { IconBlocklist } from './icons/blocklist'; import { IconEndpoints } from './icons/endpoints'; import { IconEndpointPolicies } from './icons/endpoint_policies'; @@ -68,6 +71,7 @@ const categories = [ SecurityPageName.blocklist, ], }, + ...cloudSecurityPostureCategories, ]; export const links: LinkItem = { @@ -77,7 +81,7 @@ export const links: LinkItem = { skipUrlState: true, hideTimeline: true, globalNavEnabled: true, - globalNavOrder: 6, + globalNavOrder: 7, capabilities: [`${SERVER_APP_ID}.show`], globalSearchKeywords: [ i18n.translate('xpack.securitySolution.appLinks.manage', { @@ -197,6 +201,7 @@ export const links: LinkItem = { skipUrlState: true, hideTimeline: true, }, + cloudSecurityPostureLinks, ], }; diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 72ba80e182547..b9633c49849e5 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -323,6 +323,7 @@ export class Plugin implements IPlugin; management: ReturnType; landingPages: ReturnType; + cloudSecurityPosture: ReturnType; } From 57e70cfa9a97fcbe40ffd323c5c3f5f54f9dab46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20Zolt=C3=A1n=20Szab=C3=B3?= Date: Wed, 6 Jul 2022 12:04:54 +0200 Subject: [PATCH 26/81] Shortens helper text for fields in advanced settings for transforms (#135711) --- .../components/step_details/step_details_form.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx index 141eed06e7ef8..b9ea4ea54a7f1 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx @@ -776,7 +776,7 @@ export const StepDetailsForm: FC = React.memo( } helpText={i18n.translate('xpack.transform.stepDetailsForm.frequencyHelpText', { defaultMessage: - 'The interval between checks for changes in the source indices when the transform is running continuously. Also determines the retry interval in the event of transient failures while the transform is searching or indexing. The minimum value is 1s and the maximum is 1h.', + 'The interval to check for changes in source indices when the transformation runs continuously.', })} > = React.memo( 'xpack.transform.stepDetailsForm.maxPageSearchSizeHelpText', { defaultMessage: - 'Defines the initial page size to use for the composite aggregation for each checkpoint.', + 'The initial page size to use for the composite aggregation for each checkpoint.', } )} > From fd50544641ba1512d1ec15a6c27eac1a794a4b91 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 6 Jul 2022 12:06:33 +0200 Subject: [PATCH 27/81] [Lens] Extend readme (#135695) * extend readme * [CI] Auto-commit changed files from 'node scripts/build_plugin_list_docs' * Update x-pack/plugins/lens/readme.md Co-authored-by: Marco Liberati * Update x-pack/plugins/lens/readme.md Co-authored-by: Marco Liberati * Update x-pack/plugins/lens/readme.md Co-authored-by: Marco Liberati Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Marco Liberati --- docs/developer/plugin-list.asciidoc | 2 +- x-pack/plugins/lens/readme.md | 114 +++++++++++++++++++++++++- x-pack/plugins/lens/to_playground.gif | Bin 0 -> 1165393 bytes 3 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/lens/to_playground.gif diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 919727dfe8625..c939ab2dcf690 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -504,7 +504,7 @@ the infrastructure monitoring use-case within Kibana. |{kib-repo}blob/{branch}/x-pack/plugins/lens/readme.md[lens] -|Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. +|Lens is a visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. |{kib-repo}blob/{branch}/x-pack/plugins/license_api_guard/README.md[licenseApiGuard] diff --git a/x-pack/plugins/lens/readme.md b/x-pack/plugins/lens/readme.md index 84cea6feead06..340931efdcd52 100644 --- a/x-pack/plugins/lens/readme.md +++ b/x-pack/plugins/lens/readme.md @@ -1,12 +1,118 @@ -# Lens +Lens is a visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. -Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. - -## Embedding +# Lens Embedding It's possible to embed Lens visualizations in other apps using `EmbeddableComponent` and `navigateToPrefilledEditor` exposed via contract. For more information check out the example in `x-pack/examples/embedded_lens_example`. +### Embedding guidance + +When adding visualizations to a solution page, there are multiple ways to approach this with pros and cons: + +* #### **Use a dashboard** + If the app page you are planning to build strongly resembles a regular dashboard, it might not even be necessary to write code - configuring a dashboard might be a better choice. The Presentation team is currently working on making it possible to embed dashboard into the solution navigation, which allows you to offer visualization and filter functionality without writing custom code. If possible this option should be chosen because of the low maintenance and development effort as well as the high flexibility for a user to clone the preset dashboard and start customizing it in various ways. + + Pros: + * No need to write and maintain custom code + * "Open in Lens" comes for free + * Ability for the user to customize/add/remove dashboard panels comes for free + + Cons: + * Limited data processing/visualization options - if the dashboard doesn't support it, it can't be used +* #### **Use Lens embeddable** + Using the Lens embeddable is an easy way to handle the rendering of charts. It allows you to specify data fetching and presentational properties of the final chart in a declarative way (the "Lens attributes") - everything is handled within the component (including re-fetching data on changing inputs). By using the `navigateToPrefilledEditor` method which takes the same configuration as the embeddable component, adding an "Open in Lens editor" button to your application comes at almost no additional cost. Such a button is always recommended as it allows a user to drill down further and explore the data on their own, using the current chart as a starting point. This approach is already widely deployed and should be the default choice for new visualizations. + + Pros: + * No need to manage searches and rendering logic on your own + * "Open in Lens" comes for free + + Cons: + * Each panel does its own data fetching and rendering (can lead to performance problems for high number of embeddables on a single page, e.g. more than 20) + * Limited data processing options - if the Lens UI doesn't support it, it can't be used + * Limited visualization options - if Lens can't do it, it's not possible +* #### **Using custom data fetching and rendering** + In case the disadvantages of using the Lens embeddable heavily affect your use case, it sometimes makes sense to roll your own data fetching and rendering by using the underlying APIs of search service and `elastic-charts` directly. This allows a high degree of flexibility when it comes to data processing, efficiently querying data for multiple charts in a single query and adjusting small details in how charts are rendered. However, do not choose these option lightly as maintenance as well as initial development effort will most likely be much higher than by using the Lens embeddable directly. In this case, almost always an "Open in Lens" button can still be offered to the user to drill down and further explore the data by generating a Lens configuration which is similar to the displayed visualization given the possibilities of Lens. Keep in mind that for the "Open in Lens" flow, the most important property isn't perfect fidelity of the chart but retaining the mental context of the user when switching so they don't have to start over. It's also possible to mix this approach with Lens embeddables on a single page. **Note**: In this situation, please let the VisEditors team know what features you are missing / why you chose not to use Lens. + + Pros: + * Full flexibility in data fetching optimization and chart rendering + + Cons: + * "Open in Lens" requires additional logic + * High maintenance and development effort + +## Getting started + +The `EmbeddableComponent` react component is exposed on the Lens plugin contract. In order to use it, +* Make sure you have a data view created for the data you plan to work with +* Add `lens` to `requiredPlugins` in your plugins `kibana.json` +* In the mount callback of your app, get `lens.EmbeddableComponent` from the start contract and pass it into your apps react tree +* In the place where you want to render a visualization, add the component to the tree: +```tsx +

+ // my app + +
+``` + +You can see a working example of this in the `x-pack/examples/embedded_lens_example` directory. + +The `attributes` variable contains the configuration for the Lens visualization. The details are explained in the section below. It's difficult to set up this object manually, in order to quickly get to a functioning starting point, start your Kibana server with example plugins via +``` +yarn start --run-examples +``` + +This will add an `Open in Playground` action to the menu bar in the Lens editor. With this option, try to configure the chart configuration directly in the editor, then open it in the playground to see the attributes object to copy. This works for any possible Lens visualization. + +![Go to playground](./to_playground.gif "Go to playground") + +## Lens attributes explained + +The Lens attributes object contains multiple sections concerned with different aspects of the visualizations. + +On a high level there are references, datasource state, visualization state and filters: + +### References + +References (`references`) are regular saved object references forming a graph of saved objects which depend on each other. For the Lens case, these references are always data views (called `type: "index-pattern"`) in code, referencing data views which are used in the current Lens visualization. Often there is just a single data view in use, but it's possible to use multiple data views for multiple layers in a Lens xy chart. The `id` of a reference needs to be the saved object id of the referenced data view (see the "Handling data views" section below). The `name` of the reference is comprised out of multiple parts used to map the data view to the correct layer : `indexpattern-datasource-layer-`. Even if multiple layers are using the same data view, there has to be one reference per layer (all pointing to the same data view id). + +### Datasource state + +The data source state (`state.datasourceStates.indexPattern.layers`) contains the configuration state of the data fetching and processing part of Lens. It's not specific to a certain representation (xy, pie, gauge, ...), but instead it defines a data table per layer made out of columns with various properties. This data table is passed over to the visualization state which maps it to various dimensions of the specific visualization. Layer and columns have unique ids which are shared amongst visualization and datasource - it's important to make sure they are always in sync. The keys of the `state.datasourceStates.indexPattern.layers` object are the layer ids. Lens editor chooses uuids for these, but when programmatically generating Lens attributes, any string can be used for them. The `layers[].columns` object is constructed in a similar way (keys represent the column ids). The `operationType` property defines the type of the column, other properties depend on the specific operation. Types for individual parts of the datasource state are provided (check the `lens/public` export, e.g. there's the `MaxIndexPatternColumn` for a column of operation type `max`) + +### Visualization state + +The visualization state (`state.visualization`) depends on the chosen visualization type (`visualizationType`). Layer ids and accessor properties in this state have to correspond to the layer ids and column ids of the datasource state. Types for individual visualizations are exported as standalone interfaces (e.g. `XYState` or `HeatmapVisualizationState`). + +### Filters + +Filters and query `state.filters`/`state.query` define the visualization-global filters and query applied to all layers of the visualization. The query is rendered in the top level search bar in the editor while filters are rendered as filter pills. Filters and query state defined this way is used for dashboards and Discover in the same way. + +### Callbacks + +The `EmbeddableComponent` also takes a set of callbacks to react to user interactions with the embedded Lens visualization to integrate the visualization with the surrounding app: `onLoad`, `onBrushEnd`, `onFilter`, `onTableRowClick`. A common pattern is to keep state in the solution app which is updated within these callbacks - re-rendering the surrounding application will change the Lens attributes passed to the component which will re-render the visualization (including re-fetching data if necessary). + +## Handling data views + +Currently it's necessary to have a data view saved object to use the Lens embeddable. Use the data view service to find an existing data view for a given index pattern or create a new one if it doesn't exist yet: +```ts +let dataView = (await dataViews.find('my-pattern-*', 1))[0]; +if (!dataView) { + dataView = await dataViews.createAndSave({ + title: 'my-pattern-*', + timeFieldName: '@timestamp' + }); +} +const dataViewIdForLens = dataView.id; +``` + +# Lens Development + +The following sections are concerned with developing the Lens plugin itself. ## Testing Run all tests from the `x-pack` root directory diff --git a/x-pack/plugins/lens/to_playground.gif b/x-pack/plugins/lens/to_playground.gif new file mode 100644 index 0000000000000000000000000000000000000000..56ce6f3975e533385c6f4c309c06388ecee5a02f GIT binary patch literal 1165393 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