From e60a5b0e852d4bdff23d08cbfa77cfcb570ccd1c Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 21 Oct 2019 01:37:55 -0700 Subject: [PATCH 001/191] [ML] Transforms: Fix page layout (#48628) Fixes the overall page layout of the transform plugin to be in line with the rest of the Kibana Elasticsearch management section. --- .../transform/public/app/constants/index.ts | 1 + .../plugins/transform/public/app/index.scss | 1 + .../step_define/step_define_form.tsx | 2 +- .../components/wizard/_index.scss | 1 + .../components/wizard/_wizard.scss | 5 ++ .../components/wizard/wizard.tsx | 2 +- .../create_transform_section.tsx | 41 ++++++--- .../create_transform_button.test.tsx.snap | 3 +- .../create_transform_button.tsx | 3 +- .../refresh_transform_list_button.tsx | 10 ++- .../transform_list/transform_list.tsx | 20 +++++ .../transform_management_section.tsx | 84 ++++++++++--------- .../documentation/documentation_links.ts | 10 +-- .../legacy/plugins/transform/public/plugin.ts | 2 +- 14 files changed, 116 insertions(+), 69 deletions(-) create mode 100644 x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/_index.scss create mode 100644 x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/_wizard.scss diff --git a/x-pack/legacy/plugins/transform/public/app/constants/index.ts b/x-pack/legacy/plugins/transform/public/app/constants/index.ts index 4988ea660b418..85ffc222f59a2 100644 --- a/x-pack/legacy/plugins/transform/public/app/constants/index.ts +++ b/x-pack/legacy/plugins/transform/public/app/constants/index.ts @@ -14,6 +14,7 @@ export enum SECTION_SLUG { export enum TRANSFORM_DOC_PATHS { default = 'docs.html', plugins = 'plugins.html', + transforms = 'transforms.html', } // UI Metric constants diff --git a/x-pack/legacy/plugins/transform/public/app/index.scss b/x-pack/legacy/plugins/transform/public/app/index.scss index 28459d06b5cb1..836929174875e 100644 --- a/x-pack/legacy/plugins/transform/public/app/index.scss +++ b/x-pack/legacy/plugins/transform/public/app/index.scss @@ -12,6 +12,7 @@ @import 'sections/create_transform/components/aggregation_list/index'; @import 'sections/create_transform/components/group_by_list/index'; +@import 'sections/create_transform/components/wizard/index'; @import 'sections/transform_management/components/create_transform_button/index'; @import 'sections/transform_management/components/stats_bar/index'; @import 'sections/transform_management/components/transform_list/index'; diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx index 2e7cf9911555e..49017ac9e3c02 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx @@ -827,7 +827,7 @@ export const StepDefineForm: SFC = React.memo(({ overrides = {}, onChange - + diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/_index.scss b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/_index.scss new file mode 100644 index 0000000000000..957f378640ea6 --- /dev/null +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/_index.scss @@ -0,0 +1 @@ +@import './wizard'; diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/_wizard.scss b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/_wizard.scss new file mode 100644 index 0000000000000..5a3b03f56a141 --- /dev/null +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/_wizard.scss @@ -0,0 +1,5 @@ +.transform__steps { + .euiStep__content { + padding-right: 0px; + } +} diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx index 0ed40f2d6166b..490fd150e1bc1 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx @@ -173,5 +173,5 @@ export const Wizard: SFC = React.memo(() => { }, ]; - return ; + return ; }); diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/create_transform_section.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/create_transform_section.tsx index 8e33b2ebac89a..2214d1f5adfff 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/create_transform_section.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/create_transform_section.tsx @@ -12,17 +12,19 @@ import { i18n } from '@kbn/i18n'; import { EuiBetaBadge, - EuiPage, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiPageContent, EuiPageBody, EuiPageContentBody, - EuiPageContentHeader, - EuiPageContentHeaderSection, EuiSpacer, EuiTitle, } from '@elastic/eui'; import { APP_CREATE_TRANSFORM_CLUSTER_PRIVILEGES } from '../../../../common/constants'; import { breadcrumbService, docTitleService, BREADCRUMB_SECTION } from '../../services/navigation'; +import { documentationLinksService } from '../../services/documentation'; import { PrivilegesWrapper } from '../../lib/authorization'; import { KibanaProvider } from '../../lib/kibana'; @@ -39,11 +41,11 @@ export const CreateTransformSection: FC = ({ match }) => { return ( - - - - - + + + + +

= ({ match }) => { )} />

-
-
-
+ + + + + + + + -
-
+ +
); diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/create_transform_button/__snapshots__/create_transform_button.test.tsx.snap b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/create_transform_button/__snapshots__/create_transform_button.test.tsx.snap index 94841ad026f80..d85f9379159d0 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/create_transform_button/__snapshots__/create_transform_button.test.tsx.snap +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/create_transform_button/__snapshots__/create_transform_button.test.tsx.snap @@ -12,10 +12,9 @@ exports[`Transform: Transform List Minimal initializat fill={true} iconType="plusInCircle" onClick={[MockFunction]} - size="s" > diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/create_transform_button/create_transform_button.tsx b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/create_transform_button/create_transform_button.tsx index c06be15f259d0..25024d9c5cc08 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/create_transform_button/create_transform_button.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/create_transform_button/create_transform_button.tsx @@ -33,12 +33,11 @@ export const CreateTransformButton: FC = ({ onClick fill onClick={onClick} iconType="plusInCircle" - size="s" data-test-subj="transformButtonCreate" > ); diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/refresh_transform_list_button/refresh_transform_list_button.tsx b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/refresh_transform_list_button/refresh_transform_list_button.tsx index e8ebc42ecc180..f8a1f84937326 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/refresh_transform_list_button/refresh_transform_list_button.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/refresh_transform_list_button/refresh_transform_list_button.tsx @@ -6,7 +6,7 @@ import React, { FC } from 'react'; -import { EuiButtonEmpty } from '@elastic/eui'; +import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; interface RefreshTransformListButton { @@ -17,14 +17,16 @@ export const RefreshTransformListButton: FC = ({ onClick, isLoading, }) => ( - - + ); diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx index 1037fdebbed6a..a7e4e49440089 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/transform_list.tsx @@ -14,6 +14,8 @@ import { EuiButtonIcon, EuiCallOut, EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, EuiPopover, EuiTitle, } from '@elastic/eui'; @@ -21,6 +23,7 @@ import { import { OnTableChangeArg, SortDirection, SORT_DIRECTION } from '../../../../../shared_imports'; import { + useRefreshTransformList, TransformId, TransformListRow, TRANSFORM_MODE, @@ -28,6 +31,9 @@ import { TRANSFORM_STATE, } from '../../../../common'; import { AuthorizationContext } from '../../../../lib/authorization'; + +import { CreateTransformButton } from '../create_transform_button'; +import { RefreshTransformListButton } from '../refresh_transform_list_button'; import { getTaskStateBadge } from './columns'; import { DeleteAction } from './action_delete'; import { StartAction } from './action_start'; @@ -78,6 +84,8 @@ export const TransformList: FC = ({ transformsLoading, }) => { const [isLoading, setIsLoading] = useState(false); + const { refresh } = useRefreshTransformList({ isLoading: setIsLoading }); + const [filterActive, setFilterActive] = useState(false); const [filteredTransforms, setFilteredTransforms] = useState([]); @@ -300,8 +308,20 @@ export const TransformList: FC = ({ ]; }; + const renderToolsRight = () => ( + + + + + + + + + ); + const search = { toolsLeft: transformSelection.length > 0 ? renderToolsLeft() : undefined, + toolsRight: renderToolsRight(), onChange: onQueryChange, box: { incremental: true, diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/transform_management_section.tsx b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/transform_management_section.tsx index 2c17446df830b..2e0e930990e6e 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/transform_management_section.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/transform_management_section.tsx @@ -11,17 +11,16 @@ import { i18n } from '@kbn/i18n'; import { EuiBetaBadge, + EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiModal, EuiOverlayMask, - EuiPage, EuiPageBody, + EuiPageContent, EuiPageContentBody, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiPanel, EuiSpacer, + EuiText, EuiTitle, } from '@elastic/eui'; @@ -31,22 +30,19 @@ import { useGetTransforms } from '../../hooks'; import { RedirectToCreateTransform } from '../../common/navigation'; import { PrivilegesWrapper } from '../../lib/authorization'; import { breadcrumbService, docTitleService, BREADCRUMB_SECTION } from '../../services/navigation'; +import { documentationLinksService } from '../../services/documentation'; import { useRefreshInterval } from './components/transform_list/use_refresh_interval'; -import { CreateTransformButton } from './components/create_transform_button'; -import { RefreshTransformListButton } from './components/refresh_transform_list_button'; import { SearchSelection } from './components/search_selection'; import { TransformList } from './components/transform_list'; import { TransformStatsBar } from './components/transform_list/transforms_stats_bar'; export const TransformManagement: FC = () => { - const [isLoading, setIsLoading] = useState(false); const [transformsLoading, setTransformsLoading] = useState(false); const [isInitialized, setIsInitialized] = useState(false); const [blockRefresh, setBlockRefresh] = useState(false); const [transforms, setTransforms] = useState([]); const [errorMessage, setErrorMessage] = useState(undefined); - const { refresh } = useRefreshTransformList({ isLoading: setIsLoading }); const getTransforms = useGetTransforms( setTransforms, @@ -78,12 +74,12 @@ export const TransformManagement: FC = () => { return ( - - - - - -

+ + + + + +

{ )} />

-
- - - - {/* grow={false} fixes IE11 issue with nested flex */} - - - - {/* grow={false} fixes IE11 issue with nested flex */} - - - - - - + + + + + + + + + + + + + + - - - + -
- + + {isSearchSelectionVisible && ( diff --git a/x-pack/legacy/plugins/transform/public/app/services/documentation/documentation_links.ts b/x-pack/legacy/plugins/transform/public/app/services/documentation/documentation_links.ts index ea44d64600d7c..05eb15f2046a1 100644 --- a/x-pack/legacy/plugins/transform/public/app/services/documentation/documentation_links.ts +++ b/x-pack/legacy/plugins/transform/public/app/services/documentation/documentation_links.ts @@ -6,14 +6,14 @@ import { TRANSFORM_DOC_PATHS } from '../../constants'; class DocumentationLinksService { - private esPluginDocBasePath: string = ''; + private esDocBasePath: string = ''; - public init(esPluginDocBasePath: string): void { - this.esPluginDocBasePath = esPluginDocBasePath; + public init(esDocBasePath: string): void { + this.esDocBasePath = esDocBasePath; } - public getTransformPluginDocUrl() { - return `${this.esPluginDocBasePath}${TRANSFORM_DOC_PATHS.plugins}`; + public getTransformsDocUrl() { + return `${this.esDocBasePath}${TRANSFORM_DOC_PATHS.transforms}`; } } diff --git a/x-pack/legacy/plugins/transform/public/plugin.ts b/x-pack/legacy/plugins/transform/public/plugin.ts index 7dfb9daead574..e7cc83d16b3b9 100644 --- a/x-pack/legacy/plugins/transform/public/plugin.ts +++ b/x-pack/legacy/plugins/transform/public/plugin.ts @@ -54,7 +54,7 @@ export class Plugin { textService.init(); breadcrumbService.init(chrome, management.constants.BREADCRUMB); uiMetricService.init(uiMetric.createUiStatsReporter); - documentationLinksService.init(documentation.esPluginDocBasePath); + documentationLinksService.init(documentation.esDocBasePath); docTitleService.init(docTitle.change); const unmountReactApp = (): void => { From 41aea39cc06b391eb142a937e350337799c528ee Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 21 Oct 2019 01:47:43 -0700 Subject: [PATCH 002/191] Adds es-ui team to transform plugin in CODEOWNERS. (#48665) --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 012e49690fd15..5680bd8cbf822 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -81,6 +81,9 @@ /x-pack/legacy/plugins/rollup/ @elastic/es-ui /x-pack/legacy/plugins/searchprofiler/ @elastic/es-ui /x-pack/legacy/plugins/snapshot_restore/ @elastic/es-ui +# ML team owns the transform plugin, ES team added here for visibility +# because the plugin lives in Kibana's Elasticsearch management section. +/x-pack/legacy/plugins/transform/ @elastic/es-ui /x-pack/legacy/plugins/watcher/ @elastic/es-ui # Kibana TSVB external contractors From fade9ae711d7324f5a7c0231f190d7091a1cc0b3 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Mon, 21 Oct 2019 12:19:23 +0200 Subject: [PATCH 003/191] [ML] Fix partitioning field value update (#48655) --- .../timeseriesexplorer/timeseriesexplorer.js | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js index cea2dc37bfad3..44632a2b29928 100644 --- a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js @@ -337,14 +337,22 @@ export class TimeSeriesExplorer extends React.Component { } entityFieldValueChanged = (entity, fieldValue) => { - this.setState(prevState => ({ - entities: prevState.entities.map(stateEntity => { - if (stateEntity.fieldName === entity.fieldName) { - stateEntity.fieldValue = fieldValue; - } - return stateEntity; - }) - }), () => this.saveSeriesPropertiesAndRefresh()); + const { appStateHandler } = this.props; + const { entities } = this.state; + + const resultEntities = { + ...entities.reduce((appStateEntities, appStateEntity) => { + appStateEntities[appStateEntity.fieldName] = appStateEntity.fieldValue; + return appStateEntities; + }, {}), + [entity.fieldName]: fieldValue, + }; + + appStateHandler(APP_STATE_ACTION.SET_ENTITIES, resultEntities); + + this.updateControlsForDetector(() => { + this.refresh(); + }); }; loadAnomaliesTableData = (earliestMs, latestMs) => { @@ -1090,11 +1098,11 @@ export class TimeSeriesExplorer extends React.Component { /> )} - {(jobs.length > 0 && (fullRefresh === false || loading === false) && hasResults === false) && ( + {(jobs.length > 0 && loading === false && hasResults === false) && ( )} - {(jobs.length > 0 && (fullRefresh === false || loading === false) && hasResults === true) && ( + {(jobs.length > 0 && loading === false && hasResults === true) && ( {i18n.translate('xpack.ml.timeSeriesExplorer.singleTimeSeriesAnalysisTitle', { From bb1c3889c5a00b97bb5f29fb4f82efbb14c86afc Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 21 Oct 2019 11:42:54 +0100 Subject: [PATCH 004/191] [ML] Filtering advanced detector's aggs and fields (#48651) * [ML] Filtering advanced detector's aggs and fields * adding comments * fix for EuiComboBox * better words * updating tests --- .../advanced_detector_modal.tsx | 44 +++++++++++++++++-- .../services/new_job_capabilities_service.ts | 13 +++--- .../results/cloudwatch_rollup_job_caps.json | 10 ----- .../__mocks__/results/farequote_job_caps.json | 36 +++++++-------- .../job_service/new_job_caps/aggregations.ts | 23 +++++++--- .../job_service/new_job_caps/field_service.ts | 16 ++----- .../job_service/new_job_caps/new_job_caps.ts | 6 ++- 7 files changed, 88 insertions(+), 60 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx index 97fb8c1d41fc5..159f26475256d 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx @@ -91,11 +91,19 @@ export const AdvancedDetectorModal: FC = ({ const [fieldOptionEnabled, setFieldOptionEnabled] = useState(true); const { descriptionPlaceholder, setDescriptionPlaceholder } = useDetectorPlaceholder(detector); - const aggOptions: EuiComboBoxOptionProps[] = aggs.map(createAggOption); - const fieldOptions: EuiComboBoxOptionProps[] = fields + // list of aggregation combobox options. filtering out any aggs with no fields. + const aggOptions: EuiComboBoxOptionProps[] = aggs + .filter(a => a.fields !== undefined && a.fields.length) + .map(createAggOption); + + // fields available for the selected agg + const { currentFieldOptions, setCurrentFieldOptions } = useCurrentFieldOptions(detector.agg); + + const allFieldOptions: EuiComboBoxOptionProps[] = fields .filter(f => f.id !== EVENT_RATE_FIELD_ID) .map(createFieldOption); - const splitFieldOptions = [...fieldOptions, ...createMlcategoryField(jobCreator)]; + + const splitFieldOptions = [...allFieldOptions, ...createMlcategoryField(jobCreator)]; const eventRateField = fields.find(f => f.id === EVENT_RATE_FIELD_ID); @@ -124,6 +132,8 @@ export const AdvancedDetectorModal: FC = ({ if (agg !== null) { setFieldsEnabled(true); + setCurrentFieldOptions(agg); + if (isFieldlessAgg(agg) && eventRateField !== undefined) { setFieldOption(emptyOption); setFieldOptionEnabled(false); @@ -207,7 +217,7 @@ export const AdvancedDetectorModal: FC = ({ f.id !== EVENT_RATE_FIELD_ID) + .map(createFieldOption); + + // working round EuiComboBox's odd behavior when the options list contains only one item + return options.length === 1 ? [emptyOption, ...options] : options; +} + +// custom hook for storing combobox options based on an aggregation field list +function useCurrentFieldOptions(aggregation: Aggregation | null) { + const [currentFieldOptions, setCurrentFieldOptions] = useState( + createFieldOptionList(aggregation) + ); + + return { + currentFieldOptions, + setCurrentFieldOptions: (agg: Aggregation | null) => + setCurrentFieldOptions(createFieldOptionList(agg)), + }; +} + function createDefaultDescription(dtr: RichDetector) { if (dtr.agg === null || dtr.field === null) { return ''; diff --git a/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts b/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts index f2639029f6377..890683793339a 100644 --- a/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts +++ b/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts @@ -126,17 +126,18 @@ function createObjects(resp: any, indexPatternTitle: string) { if (results !== undefined) { results.aggs.forEach((a: Aggregation) => { - // copy the agg and add a Fields list + // create the aggs list + // only adding a fields list if there is a fieldIds list const agg: Aggregation = { ...a, - fields: [], + ...(a.fieldIds !== undefined ? { fields: [] } : {}), }; aggMap[agg.id] = agg; aggs.push(agg); }); results.fields.forEach((f: Field) => { - // copy the field and add an Aggregations list + // create the fields list const field: Field = { ...f, aggs: [], @@ -188,8 +189,10 @@ function addEventRateField(aggs: Aggregation[], fields: Field[]) { }; aggs.forEach(a => { - if (a.fields !== undefined && eventRateField.aggs !== undefined && a.fields.length === 0) { - a.fields.push(eventRateField); + if (eventRateField.aggs !== undefined && a.fields === undefined) { + // if the agg's field list is undefined, it is a fieldless aggregation and + // so can only be used with the event rate field. + a.fields = [eventRateField]; eventRateField.aggs.push(a); } }); diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/cloudwatch_rollup_job_caps.json b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/cloudwatch_rollup_job_caps.json index bf5228861967b..ae940ffbf4828 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/cloudwatch_rollup_job_caps.json +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/cloudwatch_rollup_job_caps.json @@ -3,7 +3,6 @@ "aggs": [ { "dslName": "count", - "fieldIds": [], "id": "count", "kibanaName": "count", "mlModelPlotAgg": { @@ -15,7 +14,6 @@ }, { "dslName": "count", - "fieldIds": [], "id": "high_count", "kibanaName": "count", "mlModelPlotAgg": { @@ -27,7 +25,6 @@ }, { "dslName": "count", - "fieldIds": [], "id": "low_count", "kibanaName": "count", "mlModelPlotAgg": { @@ -183,7 +180,6 @@ }, { "dslName": null, - "fieldIds": [], "id": "non_zero_count", "kibanaName": null, "mlModelPlotAgg": { @@ -195,7 +191,6 @@ }, { "dslName": null, - "fieldIds": [], "id": "high_non_zero_count", "kibanaName": null, "mlModelPlotAgg": { @@ -207,7 +202,6 @@ }, { "dslName": null, - "fieldIds": [], "id": "low_non_zero_count", "kibanaName": null, "mlModelPlotAgg": { @@ -327,7 +321,6 @@ }, { "dslName": null, - "fieldIds": [], "id": "rare", "kibanaName": null, "mlModelPlotAgg": { @@ -339,7 +332,6 @@ }, { "dslName": null, - "fieldIds": [], "id": "freq_rare", "kibanaName": null, "mlModelPlotAgg": { @@ -387,7 +379,6 @@ }, { "dslName": null, - "fieldIds": [], "id": "time_of_day", "kibanaName": null, "mlModelPlotAgg": { @@ -399,7 +390,6 @@ }, { "dslName": null, - "fieldIds": [], "id": "time_of_week", "kibanaName": null, "mlModelPlotAgg": { diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json index cff91d90e8ffc..99c373eddd107 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/__mocks__/results/farequote_job_caps.json @@ -10,8 +10,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "high_count", @@ -22,8 +21,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "low_count", @@ -34,8 +32,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "mean", @@ -215,8 +212,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "high_non_zero_count", @@ -227,8 +223,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "low_non_zero_count", @@ -239,8 +234,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "high_distinct_count", @@ -253,6 +247,7 @@ "min": "min" }, "fieldIds": [ + "airline", "responsetime" ] }, @@ -267,6 +262,7 @@ "min": "min" }, "fieldIds": [ + "airline", "responsetime" ] }, @@ -377,8 +373,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "freq_rare", @@ -389,8 +384,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "info_content", @@ -443,8 +437,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "time_of_week", @@ -455,8 +448,7 @@ "mlModelPlotAgg": { "max": "max", "min": "min" - }, - "fieldIds": [] + } }, { "id": "lat_long", @@ -487,7 +479,9 @@ "type": "keyword", "aggregatable": true, "aggIds": [ - "distinct_count" + "distinct_count", + "high_distinct_count", + "low_distinct_count" ] }, { diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts index 5a10eb0eed7aa..efe06f8b5ad4a 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/aggregations.ts @@ -11,9 +11,9 @@ import { ES_AGGREGATION, } from '../../../../common/constants/aggregation_types'; -// aggregation object missing id and title and has null for kibana and dsl aggregation names. +// aggregation object missing id, title and fields and has null for kibana and dsl aggregation names. // this is used as the basis for the ML only aggregations -function getBasicMlOnlyAggregation(): Omit { +function getBasicMlOnlyAggregation(): Omit { return { kibanaName: null, dslName: null, @@ -22,10 +22,11 @@ function getBasicMlOnlyAggregation(): Omit { max: KIBANA_AGGREGATION.MAX, min: KIBANA_AGGREGATION.MIN, }, - fields: [], }; } +// list of aggregations only support by ML and which don't have an equivalent ES aggregation +// note, not all aggs have a field list. Some aggs cannot be used with a field. export const mlOnlyAggregations: Aggregation[] = [ { id: ML_JOB_AGGREGATION.NON_ZERO_COUNT, @@ -45,46 +46,55 @@ export const mlOnlyAggregations: Aggregation[] = [ { id: ML_JOB_AGGREGATION.HIGH_DISTINCT_COUNT, title: 'High distinct count', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.LOW_DISTINCT_COUNT, title: 'Low distinct count', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.METRIC, title: 'Metric', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.VARP, title: 'varp', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.HIGH_VARP, title: 'High varp', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.LOW_VARP, title: 'Low varp', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.NON_NULL_SUM, title: 'Non null sum', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.HIGH_NON_NULL_SUM, title: 'High non null sum', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.LOW_NON_NULL_SUM, title: 'Low non null sum', + fields: [], ...getBasicMlOnlyAggregation(), }, { @@ -100,16 +110,19 @@ export const mlOnlyAggregations: Aggregation[] = [ { id: ML_JOB_AGGREGATION.INFO_CONTENT, title: 'Info content', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.HIGH_INFO_CONTENT, title: 'High info content', + fields: [], ...getBasicMlOnlyAggregation(), }, { id: ML_JOB_AGGREGATION.LOW_INFO_CONTENT, title: 'Low info content', + fields: [], ...getBasicMlOnlyAggregation(), }, { @@ -125,6 +138,7 @@ export const mlOnlyAggregations: Aggregation[] = [ { id: ML_JOB_AGGREGATION.LAT_LONG, title: 'Lat long', + fields: [], ...getBasicMlOnlyAggregation(), }, ]; @@ -140,7 +154,6 @@ export const aggregations: Aggregation[] = [ max: KIBANA_AGGREGATION.MAX, min: KIBANA_AGGREGATION.MIN, }, - fields: [], }, { id: ML_JOB_AGGREGATION.HIGH_COUNT, @@ -152,7 +165,6 @@ export const aggregations: Aggregation[] = [ max: KIBANA_AGGREGATION.MAX, min: KIBANA_AGGREGATION.MIN, }, - fields: [], }, { id: ML_JOB_AGGREGATION.LOW_COUNT, @@ -164,7 +176,6 @@ export const aggregations: Aggregation[] = [ max: KIBANA_AGGREGATION.MAX, min: KIBANA_AGGREGATION.MIN, }, - fields: [], }, { id: ML_JOB_AGGREGATION.MEAN, diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts index 7e5ab342c5a08..df4a2c059f1ef 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts @@ -139,21 +139,11 @@ async function combineFieldsAndAggs( const mix = mixFactory(rollupFields); aggs.forEach(a => { - if (a.type === METRIC_AGG_TYPE) { + if (a.type === METRIC_AGG_TYPE && a.fields !== undefined) { switch (a.id) { - case ML_JOB_AGGREGATION.COUNT: - case ML_JOB_AGGREGATION.HIGH_COUNT: - case ML_JOB_AGGREGATION.LOW_COUNT: - case ML_JOB_AGGREGATION.NON_ZERO_COUNT: - case ML_JOB_AGGREGATION.HIGH_NON_ZERO_COUNT: - case ML_JOB_AGGREGATION.LOW_NON_ZERO_COUNT: - case ML_JOB_AGGREGATION.RARE: - case ML_JOB_AGGREGATION.FREQ_RARE: - case ML_JOB_AGGREGATION.TIME_OF_DAY: - case ML_JOB_AGGREGATION.TIME_OF_WEEK: - // functions which do not take any fields, so break here - break; case ML_JOB_AGGREGATION.DISTINCT_COUNT: + case ML_JOB_AGGREGATION.HIGH_DISTINCT_COUNT: + case ML_JOB_AGGREGATION.LOW_DISTINCT_COUNT: // distinct count (i.e. cardinality) takes keywords, ips // as well as numerical fields keywordFields.forEach(f => { diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts index 798790e1d37c3..cbb249be09aa0 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.ts @@ -42,7 +42,11 @@ function convertForStringify(aggs: Aggregation[], fields: Field[]): void { delete f.aggs; }); aggs.forEach(a => { - a.fieldIds = a.fields ? a.fields.map(f => f.id) : []; + if (a.fields !== undefined) { + // if the aggregation supports fields, i.e. it's fields list isn't undefined, + // create a list of field ids + a.fieldIds = a.fields.map(f => f.id); + } delete a.fields; }); } From 4895f16108ff1768340471428a23841b36e3a80c Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 21 Oct 2019 03:52:22 -0700 Subject: [PATCH 005/191] [ML] Fix analytics source index selection. (#48731) Fixes the empty dropdown when only one Kibana index pattern is available. Root cause of the issue: When no index is selected we passed in an selection item with an empty label. Internally EuiComboBox doesn't check if that item matches one of the available options, it just compares the length of selected and available options. So with one empty option selected and one index pattern available the dropdown would say You've selected all available options. This PR fixes it by checking if the current selection is actually part of the available index patterns. If it's an empty string for example, an empty array will be passed to the component instead of an empty with an item with an empty label. --- .../create_analytics_form/create_analytics_form.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx index a32631c707f55..35a0e1c82cf33 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx @@ -239,7 +239,9 @@ export const CreateAnalyticsForm: FC = ({ actions, sta )} singleSelection={{ asPlainText: true }} options={indexPatternTitles.sort().map(d => ({ label: d }))} - selectedOptions={[{ label: sourceIndex }]} + selectedOptions={ + indexPatternTitles.includes(sourceIndex) ? [{ label: sourceIndex }] : [] + } onChange={selectedOptions => setFormState({ sourceIndex: selectedOptions[0].label || '' }) } From e4ecfb105d9d55a46dd2cd80cfab3f48bed7bead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez?= Date: Mon, 21 Oct 2019 13:28:21 +0200 Subject: [PATCH 006/191] Handle empty datafeedState (#48660) --- .../containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts | 1 + .../containers/logs/log_analysis/log_analysis_status_state.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts index 477e75fc3b90c..6171d10b5f1aa 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts @@ -39,6 +39,7 @@ export type FetchJobStatusRequestPayload = rt.TypeOf (jobSummaries: FetchJobStatusResponsePay .filter(jobSummary => jobSummary.id === jobId) .map( (jobSummary): JobStatus => { - if (jobSummary.jobState === 'failed') { + if (jobSummary.jobState === 'failed' || jobSummary.datafeedState === '') { return 'failed'; } else if ( jobSummary.jobState === 'closed' && From 3cfbfaffd59a818d67fe8f197f10e4f6c860e2d3 Mon Sep 17 00:00:00 2001 From: Daniil Suleiman <31325372+sulemanof@users.noreply.github.com> Date: Mon, 21 Oct 2019 15:23:39 +0300 Subject: [PATCH 007/191] Add keys in NewVisHelp render (#48619) --- .../public/visualize/wizard/type_selection/new_vis_help.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx index 7e1a49c088d54..3877c01dcc672 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/type_selection/new_vis_help.tsx @@ -18,7 +18,7 @@ */ import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; +import React, { Fragment } from 'react'; import { EuiText, EuiButton } from '@elastic/eui'; import chrome from 'ui/chrome'; import { VisTypeAliasListEntry } from './type_selection'; @@ -37,7 +37,7 @@ export function NewVisHelp(props: Props) { />

{props.promotedTypes.map(t => ( - <> +

{t.promotion!.description}

@@ -50,7 +50,7 @@ export function NewVisHelp(props: Props) { > {t.promotion!.buttonText} - +
))}
); From 28c374ace558b2d46ce360a098e866e51bf0c851 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 21 Oct 2019 14:07:02 +0100 Subject: [PATCH 008/191] [ML] Fix detector modal combo box selection (#48741) * [ML] Fix detector modal combo box selection * removing old work around --- .../advanced_detector_modal.tsx | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx index 159f26475256d..142de85e97565 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx @@ -218,7 +218,7 @@ export const AdvancedDetectorModal: FC = ({ = ({ = ({ = ({ f.id !== EVENT_RATE_FIELD_ID) .map(createFieldOption); - - // working round EuiComboBox's odd behavior when the options list contains only one item - return options.length === 1 ? [emptyOption, ...options] : options; } // custom hook for storing combobox options based on an aggregation field list @@ -387,3 +384,13 @@ function createDefaultDescription(dtr: RichDetector) { basicDetector.exclude_frequent = dtr.excludeFrequent ? dtr.excludeFrequent : undefined; return detectorToString(basicDetector); } + +// fixes issue with EuiComboBox. +// if the options list only contains one option and nothing has been selected, set +// selectedOptions list to be an empty array +function createSelectedOptions( + option: EuiComboBoxOptionProps, + options: EuiComboBoxOptionProps[] +): EuiComboBoxOptionProps[] { + return options.length === 1 && options[0].label !== option.label ? [] : [option]; +} From 85e5885ccfbf1c145e21230ca8d878ee9aae6533 Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Mon, 21 Oct 2019 06:35:11 -0700 Subject: [PATCH 009/191] No response compression when there is a referer (#47751) * Hacking it in there, this is obviously not where this belongs * Moving implementation to a private method * Adding unit tests, I don't like the way I had to write these * Adding integration tests * Test not relying on implementation details... * No longer using .inject, thanks Mikhail!!! * Adding comment explaining the long body * Fixing nesting of describes for api integration tests --- src/core/server/http/http_server.test.ts | 39 ++++++++++++++++++++ src/core/server/http/http_server.ts | 18 ++++++++++ test/api_integration/apis/core/index.js | 46 ++++++++++++++++++------ test/api_integration/apis/index.js | 1 + 4 files changed, 93 insertions(+), 11 deletions(-) diff --git a/src/core/server/http/http_server.test.ts b/src/core/server/http/http_server.test.ts index acae9d8ff0e70..f61371c5437e6 100644 --- a/src/core/server/http/http_server.test.ts +++ b/src/core/server/http/http_server.test.ts @@ -577,6 +577,45 @@ test('exposes route details of incoming request to a route handler', async () => }); }); +describe('conditional compression', () => { + test('disables compression when there is a referer', async () => { + const { registerRouter, server: innerServer } = await server.setup(config); + + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => + // we need the large body here so that compression would normally be used + res.ok({ body: 'hello'.repeat(500), headers: { 'Content-Type': 'text/html; charset=UTF-8' } }) + ); + registerRouter(router); + + await server.start(); + const response = await supertest(innerServer.listener) + .get('/') + .set('accept-encoding', 'gzip') + .set('referer', 'http://some-other-site/'); + + expect(response.header).not.toHaveProperty('content-encoding'); + }); + + test(`enables compression when there isn't a referer`, async () => { + const { registerRouter, server: innerServer } = await server.setup(config); + + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/', validate: false }, (context, req, res) => + // we need the large body here so that compression will be used + res.ok({ body: 'hello'.repeat(500), headers: { 'Content-Type': 'text/html; charset=UTF-8' } }) + ); + registerRouter(router); + + await server.start(); + const response = await supertest(innerServer.listener) + .get('/') + .set('accept-encoding', 'gzip'); + + expect(response.header).toHaveProperty('content-encoding', 'gzip'); + }); +}); + describe('setup contract', () => { describe('#createSessionStorage', () => { it('creates session storage factory', async () => { diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index 3354324c12407..d6077200d3c75 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -96,6 +96,7 @@ export class HttpServer { const basePathService = new BasePath(config.basePath); this.setupBasePathRewrite(config, basePathService); + this.setupConditionalCompression(); return { registerRouter: this.registerRouter.bind(this), @@ -175,6 +176,23 @@ export class HttpServer { }); } + private setupConditionalCompression() { + if (this.server === undefined) { + throw new Error('Server is not created yet'); + } + + this.server.ext('onRequest', (request, h) => { + // whenever there is a referrer, don't use compression even if the client supports it + if (request.info.referrer !== '') { + this.log.debug( + `Not using compression because there is a referer: ${request.info.referrer}` + ); + request.info.acceptEncoding = ''; + } + return h.continue; + }); + } + private registerOnPostAuth(fn: OnPostAuthHandler) { if (this.server === undefined) { throw new Error('Server is not created yet'); diff --git a/test/api_integration/apis/core/index.js b/test/api_integration/apis/core/index.js index d617b2ad07351..e5da4e4730662 100644 --- a/test/api_integration/apis/core/index.js +++ b/test/api_integration/apis/core/index.js @@ -16,21 +16,45 @@ * specific language governing permissions and limitations * under the License. */ +import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - describe('core request context', () => { - it('provides access to elasticsearch', async () => ( - await supertest - .get('/requestcontext/elasticsearch') - .expect(200, 'Elasticsearch: true') - )); + describe('core', () => { + describe('request context', () => { + it('provides access to elasticsearch', async () => ( + await supertest + .get('/requestcontext/elasticsearch') + .expect(200, 'Elasticsearch: true') + )); - it('provides access to SavedObjects client', async () => ( - await supertest - .get('/requestcontext/savedobjectsclient') - .expect(200, 'SavedObjects client: {"page":1,"per_page":20,"total":0,"saved_objects":[]}') - )); + it('provides access to SavedObjects client', async () => ( + await supertest + .get('/requestcontext/savedobjectsclient') + .expect(200, 'SavedObjects client: {"page":1,"per_page":20,"total":0,"saved_objects":[]}') + )); + }); + + describe('compression', () => { + it(`uses compression when there isn't a referer`, async () => { + await supertest + .get('/app/kibana') + .set('accept-encoding', 'gzip') + .then(response => { + expect(response.headers).to.have.property('content-encoding', 'gzip'); + }); + }); + + it(`doesn't use compression when there is a referer`, async () => { + await supertest + .get('/app/kibana') + .set('accept-encoding', 'gzip') + .set('referer', 'https://www.google.com') + .then(response => { + expect(response.headers).not.to.have.property('content-encoding'); + }); + }); + }); }); } diff --git a/test/api_integration/apis/index.js b/test/api_integration/apis/index.js index 9f2672959390c..de36ee678b10e 100644 --- a/test/api_integration/apis/index.js +++ b/test/api_integration/apis/index.js @@ -34,5 +34,6 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./status')); loadTestFile(require.resolve('./stats')); loadTestFile(require.resolve('./ui_metric')); + loadTestFile(require.resolve('./core')); }); } From 4fe73779eedbc79aab45b46f771d9c740db67600 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 21 Oct 2019 07:05:43 -0700 Subject: [PATCH 010/191] [ML] Fix sidebar links. (#48662) Fixes missing links to the "What is Elasticsearch Machine Learning"-Page as well as an internal Kibana link to Transforms (Transforms were previously part of the ML main menu but are now moved to the Kibana management section so existing users might miss it otherwise). --- .../ml/public/overview/components/sidebar.tsx | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/ml/public/overview/components/sidebar.tsx b/x-pack/legacy/plugins/ml/public/overview/components/sidebar.tsx index 26b67c7774978..5a25f9ad54aa1 100644 --- a/x-pack/legacy/plugins/ml/public/overview/components/sidebar.tsx +++ b/x-pack/legacy/plugins/ml/public/overview/components/sidebar.tsx @@ -7,12 +7,15 @@ import React, { FC } from 'react'; import { EuiFlexItem, EuiLink, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import chrome from 'ui/chrome'; import { metadata } from 'ui/metadata'; const createJobLink = '#/jobs/new_job/step/index_or_search'; // metadata.branch corresponds to the version used in documentation links. const docsLink = `https://www.elastic.co/guide/en/kibana/${metadata.branch}/xpack-ml.html`; const feedbackLink = 'https://www.elastic.co/community/'; +const transformsLink = `${chrome.getBasePath()}/app/kibana#/management/elasticsearch/transform`; +const whatIsMachineLearningLink = 'https://www.elastic.co/what-is/elasticsearch-machine-learning'; export const OverviewSideBar: FC = () => ( @@ -27,7 +30,8 @@ export const OverviewSideBar: FC = () => ( @@ -45,6 +49,22 @@ export const OverviewSideBar: FC = () => ( /> ), + transforms: ( + + + + ), + whatIsMachineLearning: ( + + + + ), }} />

From 931604d8abf28f7c628198f53491a75fa960ebf7 Mon Sep 17 00:00:00 2001 From: Artyom Gospodarsky Date: Mon, 21 Oct 2019 18:14:55 +0300 Subject: [PATCH 011/191] Remove extra Field Format wrappers and move into data plugin (#47948) * Remove extra wrappers * Move Field Format utils into data plugin * Change i18n prefix * Add a new alias to i18n * Fix issues * Make Numeral utils on their own * Enhance Numeral interface * Revert Percent changes * Add common Numeral for Number, Bite, Percent * Fix i18n for some utils * Remove test duplicates * Remove test duplicates * Make a common import public path * Reimport default color * Change paths for server modules * Change default color constant name --- .i18nrc.json | 2 +- .../common/field_formats/types/_numeral.ts | 87 ------- .../common/field_formats/types/boolean.ts | 54 ----- .../common/field_formats/types/color.ts | 75 ------ .../kibana/common/field_formats/types/date.ts | 82 ------- .../common/field_formats/types/date_server.ts | 92 -------- .../common/field_formats/types/source.ts | 83 ------- .../common/field_formats/types/string.ts | 136 ----------- .../kibana/common/field_formats/types/url.ts | 207 ---------------- .../field_formats/__tests__/_boolean.js | 76 ------ .../public/field_formats/__tests__/_color.js | 90 ------- .../public/field_formats/__tests__/_date.js | 71 ------ .../field_formats/__tests__/_duration.js | 62 ----- .../public/field_formats/__tests__/_source.js | 60 ----- .../public/field_formats/__tests__/_string.js | 71 ------ .../field_formats/__tests__/_truncate.js | 52 ----- .../public/field_formats/__tests__/_url.js | 221 ------------------ .../kibana/public/field_formats/register.js | 62 ++--- .../kibana/server/field_formats/register.js | 62 ++--- .../mixin/field_formats_mixin.ts | 8 +- .../mixin/field_formats_service.test.ts | 5 +- .../mixin/field_formats_service.ts | 6 +- .../editors/color/color.js | 4 +- .../editors/color/color.test.js | 4 +- .../lib/__tests__/get_default_format.test.js | 9 +- .../ui/public/registry/field_formats.js | 7 +- .../field_formats/constants}/color_default.ts | 2 +- .../common/field_formats/constants/index.ts} | 13 +- .../field_formats/converters}/boolean.test.ts | 4 +- .../field_formats/converters/boolean.ts | 50 ++++ .../field_formats/converters}/bytes.test.ts | 4 +- .../common/field_formats/converters}/bytes.ts | 13 +- .../field_formats/converters}/color.test.ts | 6 +- .../common/field_formats/converters/color.ts | 69 ++++++ .../field_formats/converters}/date.test.ts | 4 +- .../common/field_formats/converters/date.ts | 76 ++++++ .../converters}/date_nanos.test.ts | 6 +- .../field_formats/converters}/date_nanos.ts | 106 ++++----- .../field_formats/converters/date_server.ts | 88 +++++++ .../converters}/duration.test.ts | 4 +- .../field_formats/converters}/duration.ts | 102 ++++---- .../common/field_formats/converters/index.ts} | 37 ++- .../field_formats/converters}/ip.test.ts | 4 +- .../common/field_formats/converters/ip.ts} | 28 +-- .../field_formats/converters}/number.test.ts | 4 +- .../field_formats/converters}/number.ts | 13 +- .../field_formats/converters/numeral.ts | 74 ++++++ .../field_formats/converters}/percent.test.ts | 4 +- .../field_formats/converters}/percent.ts | 34 +-- .../converters}/relative_date.test.ts | 4 +- .../converters}/relative_date.ts | 48 ++-- .../field_formats/converters/source.test.ts | 45 ++++ .../common/field_formats/converters/source.ts | 76 ++++++ .../converters}/static_lookup.ts | 50 ++-- .../field_formats/converters}/string.test.ts | 4 +- .../common/field_formats/converters/string.ts | 130 +++++++++++ .../converters}/truncate.test.ts | 4 +- .../field_formats/converters}/truncate.ts | 40 ++-- .../field_formats/converters}/url.test.ts | 6 +- .../common/field_formats/converters/url.ts | 202 ++++++++++++++++ .../data/common/field_formats/index.ts | 2 + .../legacy/plugins/apm/typings/numeral.d.ts | 2 + .../csv/server/__tests__/execute_job.js | 4 +- .../server/lib/__tests__/field_format_map.js | 5 +- 64 files changed, 1146 insertions(+), 1909 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/common/field_formats/types/_numeral.ts delete mode 100644 src/legacy/core_plugins/kibana/common/field_formats/types/boolean.ts delete mode 100644 src/legacy/core_plugins/kibana/common/field_formats/types/color.ts delete mode 100644 src/legacy/core_plugins/kibana/common/field_formats/types/date.ts delete mode 100644 src/legacy/core_plugins/kibana/common/field_formats/types/date_server.ts delete mode 100644 src/legacy/core_plugins/kibana/common/field_formats/types/source.ts delete mode 100644 src/legacy/core_plugins/kibana/common/field_formats/types/string.ts delete mode 100644 src/legacy/core_plugins/kibana/common/field_formats/types/url.ts delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_boolean.js delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_color.js delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_date.js delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_duration.js delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_source.js delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_string.js delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_truncate.js delete mode 100644 src/legacy/core_plugins/kibana/public/field_formats/__tests__/_url.js rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/constants}/color_default.ts (95%) rename src/{legacy/core_plugins/kibana/public/field_formats/__tests__/index.js => plugins/data/common/field_formats/constants/index.ts} (76%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/boolean.test.ts (95%) create mode 100644 src/plugins/data/common/field_formats/converters/boolean.ts rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/bytes.test.ts (93%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/bytes.ts (80%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/color.test.ts (96%) create mode 100644 src/plugins/data/common/field_formats/converters/color.ts rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/date.test.ts (96%) create mode 100644 src/plugins/data/common/field_formats/converters/date.ts rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/date_nanos.test.ts (95%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/date_nanos.ts (56%) create mode 100644 src/plugins/data/common/field_formats/converters/date_server.ts rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/duration.test.ts (96%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/duration.ts (50%) rename src/{legacy/core_plugins/kibana/common/field_formats/types/ip.ts => plugins/data/common/field_formats/converters/index.ts} (55%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/ip.test.ts (94%) rename src/{legacy/core_plugins/kibana/public/field_formats/__tests__/_ip.js => plugins/data/common/field_formats/converters/ip.ts} (57%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/number.test.ts (93%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/number.ts (80%) create mode 100644 src/plugins/data/common/field_formats/converters/numeral.ts rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/percent.test.ts (93%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/percent.ts (57%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/relative_date.test.ts (92%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/relative_date.ts (55%) create mode 100644 src/plugins/data/common/field_formats/converters/source.test.ts create mode 100644 src/plugins/data/common/field_formats/converters/source.ts rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/static_lookup.ts (56%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/string.test.ts (96%) create mode 100644 src/plugins/data/common/field_formats/converters/string.ts rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/truncate.test.ts (94%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/truncate.ts (58%) rename src/{legacy/core_plugins/kibana/common/field_formats/types => plugins/data/common/field_formats/converters}/url.test.ts (98%) create mode 100644 src/plugins/data/common/field_formats/converters/url.ts diff --git a/.i18nrc.json b/.i18nrc.json index b8bd8729139c0..0ea51fe8212c4 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -1,7 +1,7 @@ { "paths": { "common.ui": "src/legacy/ui", - "data": "src/legacy/core_plugins/data", + "data": ["src/legacy/core_plugins/data", "src/plugins/data"], "expressions": "src/legacy/core_plugins/expressions", "kibana_react": "src/legacy/core_plugins/kibana_react", "server": "src/legacy/server", diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/_numeral.ts b/src/legacy/core_plugins/kibana/common/field_formats/types/_numeral.ts deleted file mode 100644 index 0d39075a1dec9..0000000000000 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/_numeral.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// @ts-ignore -import numeral from '@elastic/numeral'; -// @ts-ignore -import numeralLanguages from '@elastic/numeral/languages'; -import { assign, has } from 'lodash'; -import { - FieldFormat, - KBN_FIELD_TYPES, - TextContextTypeConvert, -} from '../../../../../../plugins/data/common/'; - -const numeralInst = numeral(); - -numeralLanguages.forEach(function(numeralLanguage: Record) { - numeral.language(numeralLanguage.id, numeralLanguage.lang); -}); - -export function createNumeralFormat(opts: Record) { - class NumeralFormat extends FieldFormat { - static id = opts.id; - static title = opts.title; - static fieldType = KBN_FIELD_TYPES.NUMBER; - - private getConfig: Function; - - constructor(params: Record, getConfig: Function) { - super(params); - this.getConfig = getConfig; - } - - getParamDefaults() { - if (has(opts, 'getParamDefaults')) { - return opts.getParamDefaults(this.getConfig); - } - - return { - pattern: this.getConfig(`format:${opts.id}:defaultPattern`), - }; - } - - textConvert: TextContextTypeConvert = val => { - if (val === -Infinity) return '-∞'; - if (val === +Infinity) return '+∞'; - if (typeof val !== 'number') { - val = parseFloat(val); - } - - if (isNaN(val)) return ''; - - const previousLocale = numeral.language(); - const defaultLocale = - (this.getConfig && this.getConfig('format:number:defaultLocale')) || 'en'; - numeral.language(defaultLocale); - - const formatted = numeralInst.set(val).format(this.param('pattern')); - - numeral.language(previousLocale); - - return opts.afterConvert ? opts.afterConvert.call(this, formatted) : formatted; - }; - } - - if (opts.prototype) { - assign(NumeralFormat.prototype, opts.prototype); - } - - return NumeralFormat; -} diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/boolean.ts b/src/legacy/core_plugins/kibana/common/field_formats/types/boolean.ts deleted file mode 100644 index 840bf20a9af35..0000000000000 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/boolean.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { - FieldFormat, - asPrettyString, - KBN_FIELD_TYPES, - TextContextTypeConvert, -} from '../../../../../../plugins/data/common'; - -export function createBoolFormat() { - return class BoolFormat extends FieldFormat { - static id = 'boolean'; - static title = 'Boolean'; - static fieldType = [KBN_FIELD_TYPES.BOOLEAN, KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.STRING]; - - textConvert: TextContextTypeConvert = value => { - if (typeof value === 'string') { - value = value.trim().toLowerCase(); - } - - switch (value) { - case false: - case 0: - case 'false': - case 'no': - return 'false'; - case true: - case 1: - case 'true': - case 'yes': - return 'true'; - default: - return asPrettyString(value); - } - }; - }; -} diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/color.ts b/src/legacy/core_plugins/kibana/common/field_formats/types/color.ts deleted file mode 100644 index 065918c6bbdf2..0000000000000 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/color.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { findLast, cloneDeep, template, escape } from 'lodash'; -import { - asPrettyString, - FieldFormat, - KBN_FIELD_TYPES, - HtmlContextTypeConvert, -} from '../../../../../../plugins/data/common/'; -import { DEFAULT_COLOR } from './color_default'; - -const convertTemplate = template('<%- val %>'); - -export function createColorFormat() { - class ColorFormat extends FieldFormat { - static id = 'color'; - static title = 'Color'; - static fieldType = [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.STRING]; - - getParamDefaults() { - return { - fieldType: null, // populated by editor, see controller below - colors: [cloneDeep(DEFAULT_COLOR)], - }; - } - - findColorRuleForVal(val: any) { - switch (this.param('fieldType')) { - case 'string': - return findLast(this.param('colors'), (colorParam: typeof DEFAULT_COLOR) => { - return new RegExp(colorParam.regex).test(val); - }); - - case 'number': - return findLast(this.param('colors'), ({ range }) => { - if (!range) return; - const [start, end] = range.split(':'); - return val >= Number(start) && val <= Number(end); - }); - - default: - return null; - } - } - - htmlConvert: HtmlContextTypeConvert = val => { - const color = this.findColorRuleForVal(val) as typeof DEFAULT_COLOR; - if (!color) return escape(asPrettyString(val)); - - let style = ''; - if (color.text) style += `color: ${color.text};`; - if (color.background) style += `background-color: ${color.background};`; - return convertTemplate({ val, style }); - }; - } - - return ColorFormat; -} diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/date.ts b/src/legacy/core_plugins/kibana/common/field_formats/types/date.ts deleted file mode 100644 index b04a1729ee13e..0000000000000 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/date.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { memoize, noop } from 'lodash'; -import moment from 'moment'; -import { - FieldFormat, - KBN_FIELD_TYPES, - TextContextTypeConvert, -} from '../../../../../../plugins/data/common/'; - -export function createDateFormat() { - return class DateFormat extends FieldFormat { - static id = 'date'; - static title = 'Date'; - static fieldType = KBN_FIELD_TYPES.DATE; - - private getConfig: Function; - private memoizedConverter: Function = noop; - private memoizedPattern: string = ''; - private timeZone: string = ''; - - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - } - - getParamDefaults() { - return { - pattern: this.getConfig('dateFormat'), - timezone: this.getConfig('dateFormat:tz'), - }; - } - - textConvert: TextContextTypeConvert = val => { - // don't give away our ref to converter so - // we can hot-swap when config changes - const pattern = this.param('pattern'); - const timezone = this.param('timezone'); - - const timezoneChanged = this.timeZone !== timezone; - const datePatternChanged = this.memoizedPattern !== pattern; - if (timezoneChanged || datePatternChanged) { - this.timeZone = timezone; - this.memoizedPattern = pattern; - - this.memoizedConverter = memoize(function converter(value: any) { - if (value === null || value === undefined) { - return '-'; - } - - const date = moment(value); - - if (date.isValid()) { - return date.format(pattern); - } else { - return value; - } - }); - } - - return this.memoizedConverter(val); - }; - }; -} diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/date_server.ts b/src/legacy/core_plugins/kibana/common/field_formats/types/date_server.ts deleted file mode 100644 index fa6bf8b261479..0000000000000 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/date_server.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { memoize, noop } from 'lodash'; -import moment from 'moment-timezone'; -import { - FieldFormat, - KBN_FIELD_TYPES, - TextContextTypeConvert, -} from '../../../../../../plugins/data/common/'; - -export function createDateOnServerFormat() { - return class DateFormat extends FieldFormat { - static id = 'date'; - static title = 'Date'; - static fieldType = KBN_FIELD_TYPES.DATE; - - private getConfig: Function; - private memoizedConverter: Function = noop; - private memoizedPattern: string = ''; - private timeZone: string = ''; - - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - this.memoizedConverter = memoize((val: any) => { - if (val == null) { - return '-'; - } - - /* On the server, importing moment returns a new instance. Unlike on - * the client side, it doesn't have the dateFormat:tz configuration - * baked in. - * We need to set the timezone manually here. The date is taken in as - * UTC and converted into the desired timezone. */ - let date; - if (this.timeZone === 'Browser') { - // Assume a warning has been logged this can be unpredictable. It - // would be too verbose to log anything here. - date = moment.utc(val); - } else { - date = moment.utc(val).tz(this.timeZone); - } - - if (date.isValid()) { - return date.format(this.memoizedPattern); - } else { - return val; - } - }); - } - - getParamDefaults() { - return { - pattern: this.getConfig('dateFormat'), - timezone: this.getConfig('dateFormat:tz'), - }; - } - - textConvert: TextContextTypeConvert = val => { - // don't give away our ref to converter so we can hot-swap when config changes - const pattern = this.param('pattern'); - const timezone = this.param('timezone'); - - const timezoneChanged = this.timeZone !== timezone; - const datePatternChanged = this.memoizedPattern !== pattern; - if (timezoneChanged || datePatternChanged) { - this.timeZone = timezone; - this.memoizedPattern = pattern; - } - - return this.memoizedConverter(val); - }; - }; -} diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/source.ts b/src/legacy/core_plugins/kibana/common/field_formats/types/source.ts deleted file mode 100644 index 4d73203696bcd..0000000000000 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/source.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { template, escape, keys } from 'lodash'; -// @ts-ignore -import { noWhiteSpace } from '../../utils/no_white_space'; -// @ts-ignore -import { shortenDottedString } from '../../utils/shorten_dotted_string'; -import { - FieldFormat, - KBN_FIELD_TYPES, - TextContextTypeConvert, - HtmlContextTypeConvert, -} from '../../../../../../plugins/data/common/'; - -const templateHtml = ` -
- <% defPairs.forEach(function (def) { %> -
<%- def[0] %>:
-
<%= def[1] %>
- <%= ' ' %> - <% }); %> -
`; -const doTemplate = template(noWhiteSpace(templateHtml)); - -export function createSourceFormat() { - class SourceFormat extends FieldFormat { - static id = '_source'; - static title = '_source'; - static fieldType = KBN_FIELD_TYPES._SOURCE; - - private getConfig: Function; - - constructor(params: Record, getConfig: Function) { - super(params); - - this.getConfig = getConfig; - } - - textConvert: TextContextTypeConvert = value => JSON.stringify(value); - - htmlConvert: HtmlContextTypeConvert = (value, field, hit) => { - if (!field) { - const converter = this.getConverterFor('text') as Function; - - return escape(converter(value)); - } - - const highlights = (hit && hit.highlight) || {}; - const formatted = field.indexPattern.formatHit(hit); - const highlightPairs: any[] = []; - const sourcePairs: any[] = []; - const isShortDots = this.getConfig('shortDots:enable'); - - keys(formatted).forEach(key => { - const pairs = highlights[key] ? highlightPairs : sourcePairs; - const newField = isShortDots ? shortenDottedString(key) : key; - const val = formatted[key]; - pairs.push([newField, val]); - }, []); - - return doTemplate({ defPairs: highlightPairs.concat(sourcePairs) }); - }; - } - - return SourceFormat; -} diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/string.ts b/src/legacy/core_plugins/kibana/common/field_formats/types/string.ts deleted file mode 100644 index c41b94cab7cf7..0000000000000 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/string.ts +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { asPrettyString } from '../../../../../../plugins/data/common/field_formats'; -import { - FieldFormat, - KBN_FIELD_TYPES, - TextContextTypeConvert, -} from '../../../../../../plugins/data/common/'; -// @ts-ignore -import { shortenDottedString } from '../../utils/shorten_dotted_string'; - -const TRANSFORM_OPTIONS = [ - { - kind: false, - text: i18n.translate('kbn.common.fieldFormats.string.transformOptions.none', { - defaultMessage: '- None -', - }), - }, - { - kind: 'lower', - text: i18n.translate('kbn.common.fieldFormats.string.transformOptions.lower', { - defaultMessage: 'Lower Case', - }), - }, - { - kind: 'upper', - text: i18n.translate('kbn.common.fieldFormats.string.transformOptions.upper', { - defaultMessage: 'Upper Case', - }), - }, - { - kind: 'title', - text: i18n.translate('kbn.common.fieldFormats.string.transformOptions.title', { - defaultMessage: 'Title Case', - }), - }, - { - kind: 'short', - text: i18n.translate('kbn.common.fieldFormats.string.transformOptions.short', { - defaultMessage: 'Short Dots', - }), - }, - { - kind: 'base64', - text: i18n.translate('kbn.common.fieldFormats.string.transformOptions.base64', { - defaultMessage: 'Base64 Decode', - }), - }, - { - kind: 'urlparam', - text: i18n.translate('kbn.common.fieldFormats.string.transformOptions.url', { - defaultMessage: 'URL Param Decode', - }), - }, -]; -const DEFAULT_TRANSFORM_OPTION = false; - -export function createStringFormat() { - class StringFormat extends FieldFormat { - static id = 'string'; - static title = 'String'; - static fieldType = [ - KBN_FIELD_TYPES.NUMBER, - KBN_FIELD_TYPES.BOOLEAN, - KBN_FIELD_TYPES.DATE, - KBN_FIELD_TYPES.IP, - KBN_FIELD_TYPES.ATTACHMENT, - KBN_FIELD_TYPES.GEO_POINT, - KBN_FIELD_TYPES.GEO_SHAPE, - KBN_FIELD_TYPES.STRING, - KBN_FIELD_TYPES.MURMUR3, - KBN_FIELD_TYPES.UNKNOWN, - KBN_FIELD_TYPES.CONFLICT, - ]; - static transformOptions = TRANSFORM_OPTIONS; - - getParamDefaults() { - return { - transform: DEFAULT_TRANSFORM_OPTION, - }; - } - - private base64Decode(val: string) { - try { - return Buffer.from(val, 'base64').toString('utf8'); - } catch (e) { - return asPrettyString(val); - } - } - - private toTitleCase(val: string) { - return val.replace(/\w\S*/g, txt => { - return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); - }); - } - - textConvert: TextContextTypeConvert = val => { - switch (this.param('transform')) { - case 'lower': - return String(val).toLowerCase(); - case 'upper': - return String(val).toUpperCase(); - case 'title': - return this.toTitleCase(val); - case 'short': - return shortenDottedString(val); - case 'base64': - return this.base64Decode(val); - case 'urlparam': - return decodeURIComponent(val); - default: - return asPrettyString(val); - } - }; - } - - return StringFormat; -} diff --git a/src/legacy/core_plugins/kibana/common/field_formats/types/url.ts b/src/legacy/core_plugins/kibana/common/field_formats/types/url.ts deleted file mode 100644 index e9eb41513d52d..0000000000000 --- a/src/legacy/core_plugins/kibana/common/field_formats/types/url.ts +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { escape, memoize } from 'lodash'; -import { - getHighlightHtml, - FieldFormat, - KBN_FIELD_TYPES, - TextContextTypeConvert, - HtmlContextTypeConvert, -} from '../../../../../../plugins/data/common/'; - -const templateMatchRE = /{{([\s\S]+?)}}/g; -const whitelistUrlSchemes = ['http://', 'https://']; - -const URL_TYPES = [ - { - kind: 'a', - text: i18n.translate('kbn.common.fieldFormats.url.types.link', { - defaultMessage: 'Link', - }), - }, - { - kind: 'img', - text: i18n.translate('kbn.common.fieldFormats.url.types.img', { - defaultMessage: 'Image', - }), - }, - { - kind: 'audio', - text: i18n.translate('kbn.common.fieldFormats.url.types.audio', { - defaultMessage: 'Audio', - }), - }, -]; -const DEFAULT_URL_TYPE = 'a'; - -export function createUrlFormat() { - class UrlFormat extends FieldFormat { - static id = 'url'; - static title = 'Url'; - static fieldType = [ - KBN_FIELD_TYPES.NUMBER, - KBN_FIELD_TYPES.BOOLEAN, - KBN_FIELD_TYPES.DATE, - KBN_FIELD_TYPES.IP, - KBN_FIELD_TYPES.STRING, - KBN_FIELD_TYPES.MURMUR3, - KBN_FIELD_TYPES.UNKNOWN, - KBN_FIELD_TYPES.CONFLICT, - ]; - static urlTypes = URL_TYPES; - - constructor(params: Record) { - super(params); - this.compileTemplate = memoize(this.compileTemplate); - } - - getParamDefaults() { - return { - type: DEFAULT_URL_TYPE, - urlTemplate: null, - labelTemplate: null, - width: null, - height: null, - }; - } - - private formatLabel(value: string, url?: string): string { - const template = this.param('labelTemplate'); - if (url == null) url = this.formatUrl(value); - if (!template) return url; - - return this.compileTemplate(template)({ - value, - url, - }); - } - - private formatUrl(value: string): string { - const template = this.param('urlTemplate'); - if (!template) return value; - - return this.compileTemplate(template)({ - value: encodeURIComponent(value), - rawValue: value, - }); - } - - private compileTemplate(template: string): Function { - // trim all the odd bits, the variable names - const parts = template.split(templateMatchRE).map((part, i) => (i % 2 ? part.trim() : part)); - - return function(locals: Record): string { - // replace all the odd bits with their local var - let output = ''; - let i = -1; - while (++i < parts.length) { - if (i % 2) { - if (locals.hasOwnProperty(parts[i])) { - const local = locals[parts[i]]; - output += local == null ? '' : local; - } - } else { - output += parts[i]; - } - } - - return output; - }; - } - - private generateImgHtml(url: string, imageLabel: string): string { - const isValidWidth = !isNaN(parseInt(this.param('width'), 10)); - const isValidHeight = !isNaN(parseInt(this.param('height'), 10)); - const maxWidth = isValidWidth ? `${this.param('width')}px` : 'none'; - const maxHeight = isValidHeight ? `${this.param('height')}px` : 'none'; - - return `${imageLabel}`; - } - - textConvert: TextContextTypeConvert = value => this.formatLabel(value); - - htmlConvert: HtmlContextTypeConvert = (rawValue, field, hit, parsedUrl) => { - const url = escape(this.formatUrl(rawValue)); - const label = escape(this.formatLabel(rawValue, url)); - - switch (this.param('type')) { - case 'audio': - return `

} @@ -177,7 +177,7 @@ export const SnapshotList: React.FunctionComponent

From d5a0f371889823a3a5d75074cbb9c62b1886b11b Mon Sep 17 00:00:00 2001 From: Maryia Lapata Date: Wed, 23 Oct 2019 16:30:50 +0300 Subject: [PATCH 076/191] [Visualization] Fix: add vis title to state (#48867) * Add error when there is no histogram agg when using parent pipeline * Update error message * Update message * Add vis title to state * Revert unrelated changes * Update vis title when vis is renamed * Update title in url when renaming --- .../interpreter/public/renderers/visualization.ts | 6 +++++- .../core_plugins/kibana/public/visualize/editor/editor.js | 4 ++++ test/functional/apps/visualize/_shared_item.js | 3 +-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/interpreter/public/renderers/visualization.ts b/src/legacy/core_plugins/interpreter/public/renderers/visualization.ts index 90020f819dbe2..bedba6bfacede 100644 --- a/src/legacy/core_plugins/interpreter/public/renderers/visualization.ts +++ b/src/legacy/core_plugins/interpreter/public/renderers/visualization.ts @@ -38,7 +38,11 @@ export const visualization = () => ({ // special case in visualize, we need to render first (without executing the expression), for maps to work if (visConfig) { $rootScope.$apply(() => { - handlers.vis.setCurrentState({ type: visType, params: visConfig }); + handlers.vis.setCurrentState({ + type: visType, + params: visConfig, + title: handlers.vis.title, + }); }); } } else { diff --git a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js index dac0880e6fec4..b24cf447d21d6 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/editor/editor.js @@ -600,6 +600,10 @@ function VisEditor( } else if (savedVis.id === $route.current.params.id) { docTitle.change(savedVis.lastSavedTitle); chrome.breadcrumbs.set($injector.invoke(getEditBreadcrumbs)); + savedVis.vis.title = savedVis.title; + savedVis.vis.description = savedVis.description; + // it's needed to save the state to update url string + $state.save(); } else { kbnUrl.change(`${VisualizeConstants.EDIT_PATH}/{{id}}`, { id: savedVis.id }); } diff --git a/test/functional/apps/visualize/_shared_item.js b/test/functional/apps/visualize/_shared_item.js index efd534f035093..9fe38be15a741 100644 --- a/test/functional/apps/visualize/_shared_item.js +++ b/test/functional/apps/visualize/_shared_item.js @@ -24,8 +24,7 @@ export default function ({ getService, getPageObjects }) { const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'visualize']); - // https://github.com/elastic/kibana/issues/37130 - describe.skip('data-shared-item', function indexPatternCreation() { + describe('data-shared-item', function indexPatternCreation() { before(async function () { log.debug('navigateToApp visualize'); await PageObjects.common.navigateToApp('visualize'); From 531448e981c2a2c25f8156f91ebd4df0d09bb255 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 23 Oct 2019 07:52:38 -0600 Subject: [PATCH 077/191] [skip-ci][Maps] clean-up documenation references to match UI text updates (#48993) --- docs/maps/geojson-upload.asciidoc | 6 +-- .../indexing-geojson-data-tutorial.asciidoc | 38 +++++++++---------- docs/maps/maps-getting-started.asciidoc | 2 +- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/maps/geojson-upload.asciidoc b/docs/maps/geojson-upload.asciidoc index d9b21f591f625..8c3cb371b6add 100644 --- a/docs/maps/geojson-upload.asciidoc +++ b/docs/maps/geojson-upload.asciidoc @@ -9,7 +9,7 @@ for example, in visualizations and Canvas workpads. [float] === Why GeoJSON? GeoJSON is an open-standard file format for storing geospatial vector data. -Although many vector data formats are available in the GIS community, +Although many vector data formats are available in the GIS community, GeoJSON is the most commonly used and flexible option. [float] @@ -18,14 +18,14 @@ Follow the instructions below to upload a GeoJSON data file, or try the <>. . Open *Elastic Maps*, and then click *Add layer*. -. Click *Upload GeoJSON vector file*. +. Click *Uploaded GeoJSON*. + [role="screenshot"] image::maps/images/fu_gs_select_source_file_upload.png[] . Use the file chooser to select a valid GeoJSON file. The file will load a preview of the data on the map. -. Use the default *Index type* of {ref}/geo-point.html[geo_point] for point data, +. Use the default *Index type* of {ref}/geo-point.html[geo_point] for point data, or override it and select {ref}/geo-shape.html[geo_shape]. All other shapes will default to a type of `geo_shape`. . Leave the default *Index name* and *Index pattern* names (the name of the uploaded diff --git a/docs/maps/indexing-geojson-data-tutorial.asciidoc b/docs/maps/indexing-geojson-data-tutorial.asciidoc index 5645567ec7e79..5284bd9ac2ac5 100644 --- a/docs/maps/indexing-geojson-data-tutorial.asciidoc +++ b/docs/maps/indexing-geojson-data-tutorial.asciidoc @@ -2,7 +2,7 @@ [[indexing-geojson-data-tutorial]] == Indexing GeoJSON data tutorial -In this tutorial, you'll build a customized map that shows the flight path between +In this tutorial, you'll build a customized map that shows the flight path between two airports, and the lightning hot spots on that route. You'll learn to: * Import GeoJSON files into Kibana @@ -15,7 +15,7 @@ two airports, and the lightning hot spots on that route. You'll learn to: This tutorial requires you to download the following GeoJSON sample data files. These files are good examples of the types of vector data that you can upload to Kibana and index in -Elasticsearch for display in *Elastic Maps*. +Elasticsearch for display in *Elastic Maps*. * https://raw.githubusercontent.com/elastic/examples/master/Maps/Getting%20Started%20Examples/geojson_upload_and_styling/logan_international_airport.geojson[Logan International Airport] * https://raw.githubusercontent.com/elastic/examples/master/Maps/Getting%20Started%20Examples/geojson_upload_and_styling/bangor_international_airport.geojson[Bangor International Airport] @@ -23,7 +23,7 @@ Elasticsearch for display in *Elastic Maps*. * https://raw.githubusercontent.com/elastic/examples/master/Maps/Getting%20Started%20Examples/geojson_upload_and_styling/original_flight_path.geojson[Original flight path] * https://raw.githubusercontent.com/elastic/examples/master/Maps/Getting%20Started%20Examples/geojson_upload_and_styling/modified_flight_path.geojson[Modified flight path] -The data represents two real airports, two fictitious flight routes, and +The data represents two real airports, two fictitious flight routes, and fictitious lightning reports. You don't need to use all of these files. Feel free to work with as many files as you'd like, or use valid GeoJSON files of your own. @@ -47,12 +47,12 @@ image::maps/images/fu_gs_new_england_map.png[] For each GeoJSON file you downloaded, complete the following steps: . Below the map legend, click *Add layer*. -. From the list of layer types, click *Upload GeoJSON vector file*. +. From the list of layer types, click *Uploaded GeoJSON*. . Using the File Picker, upload the GeoJSON file. + -Depending on the geometry type of your features, this will +Depending on the geometry type of your features, this will auto-populate *Index type* with either {ref}/geo-point.html[geo_point] or - {ref}/geo-shape.html[geo_shape] and *Index name* with + {ref}/geo-shape.html[geo_shape] and *Index name* with ``. . Click *Import file* in the lower right. @@ -60,7 +60,7 @@ auto-populate *Index type* with either {ref}/geo-point.html[geo_point] or You'll see activity as the GeoJSON Upload utility creates a new index and index pattern for the data set. When the process is complete, you should receive messages that the creation of the new index and index pattern -were successful. +were successful. . Click *Add layer* in the bottom right. @@ -69,7 +69,7 @@ were successful. . Once you've added all of the sample files, <>. + -At this point, you could consider the map complete, +At this point, you could consider the map complete, but there are a few additions and tweaks that you can make to tell a better story with your data. + @@ -80,18 +80,18 @@ image::maps/images/fu_gs_flight_paths.png[] === Add a heatmap aggregation layer Looking at the `Lightning detected` layer, it's clear where lightning has -struck. What's less clear, is if there have been more lightning -strikes in some areas than others, in other words, where the lightning +struck. What's less clear, is if there have been more lightning +strikes in some areas than others, in other words, where the lightning hot spots are. An advantage of having indexed -{ref}/geo-point.html[geo_point] data for the -lightning strikes is that you can perform aggregations on the data. +{ref}/geo-point.html[geo_point] data for the +lightning strikes is that you can perform aggregations on the data. . Below the map legend, click *Add layer*. . From the list of layer types, click *Grid aggregation*. + -Because you indexed `lightning_detected.geojson` using the index name and +Because you indexed `lightning_detected.geojson` using the index name and pattern `lightning_detected`, that data is available as a {ref}/geo-point.html[geo_point] -aggregation. +aggregation. . Select `lightning_detected`. . Click *Show as* and select `heat map`. @@ -99,15 +99,15 @@ aggregation. "Lightning intensity". + The remaining default settings are good, but there are a couple of -settings that you might want to change. +settings that you might want to change. -. Under *Source settings* > *Grid resolution*, select from the different heat map resolutions. +. Under *Source settings* > *Grid resolution*, select from the different heat map resolutions. + The default "Coarse" looks good, but feel free to select a different resolution. . Play around with the *Layer Style* > -*Color range* setting. +*Color range* setting. + Again the default looks good, but feel free to choose a different color range. @@ -125,14 +125,14 @@ image::maps/images/fu_gs_lightning_intensity.png[] === Organize the layers Consider ways you might improve the appearance of the final map. -Small changes in how and when layers are shown can help tell a +Small changes in how and when layers are shown can help tell a better story with your data. Here are a few final tweaks you might make: * Update layer names * Adjust styles for each layer * Adjust the layer order -* Decide which layers to show at different zoom levels +* Decide which layers to show at different zoom levels When you've finished, again be sure to <>. diff --git a/docs/maps/maps-getting-started.asciidoc b/docs/maps/maps-getting-started.asciidoc index f6db2f0fff219..88ad6a26d3697 100644 --- a/docs/maps/maps-getting-started.asciidoc +++ b/docs/maps/maps-getting-started.asciidoc @@ -65,7 +65,7 @@ and lighter shades symbolize countries with less traffic. ==== Add a vector layer from the Elastic Maps Service source . In the map legend, click *Add layer*. -. Click the *Vector shapes* data source. +. Click the *EMS Boundaries* data source. . From the *Layer* dropdown menu, select *World Countries*. . Click the *Add layer* button. . Set *Layer name* to `Total Requests by Country`. From 7ba1d0b4f86bb85021eaf2d152ec7430027f311d Mon Sep 17 00:00:00 2001 From: Josh Dover Date: Wed, 23 Oct 2019 09:05:27 -0500 Subject: [PATCH 078/191] Use custom deep merging strategy on createCluster (#48836) --- .../elasticsearch_service.test.ts | 44 ++++++++++ .../elasticsearch/elasticsearch_service.ts | 3 +- src/core/utils/index.ts | 1 + src/core/utils/merge.test.ts | 64 ++++++++++++++ src/core/utils/merge.ts | 85 +++++++++++++++++++ 5 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 src/core/utils/merge.test.ts create mode 100644 src/core/utils/merge.ts diff --git a/src/core/server/elasticsearch/elasticsearch_service.test.ts b/src/core/server/elasticsearch/elasticsearch_service.test.ts index 58fe2b52727ef..6c4a1f263bc71 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.test.ts @@ -174,11 +174,55 @@ Object { undefined, ], "ssl": Object { + "certificateAuthorities": undefined, "verificationMode": "none", }, } `); }); + + it('does not merge elasticsearch hosts if custom config overrides', async () => { + configService.atPath.mockReturnValueOnce( + new BehaviorSubject({ + hosts: ['http://1.2.3.4', 'http://9.8.7.6'], + healthCheck: { + delay: 2000, + }, + ssl: { + verificationMode: 'none', + }, + } as any) + ); + elasticsearchService = new ElasticsearchService(coreContext); + const setupContract = await elasticsearchService.setup(deps); + // reset all mocks called during setup phase + MockClusterClient.mockClear(); + + const customConfig = { + hosts: ['http://8.8.8.8'], + logQueries: true, + ssl: { certificate: 'certificate-value' }, + }; + setupContract.createClient('some-custom-type', customConfig); + + const config = MockClusterClient.mock.calls[0][0]; + expect(config).toMatchInlineSnapshot(` + Object { + "healthCheckDelay": 2000, + "hosts": Array [ + "http://8.8.8.8", + ], + "logQueries": true, + "requestHeadersWhitelist": Array [ + undefined, + ], + "ssl": Object { + "certificate": "certificate-value", + "verificationMode": "none", + }, + } + `); + }); }); }); diff --git a/src/core/server/elasticsearch/elasticsearch_service.ts b/src/core/server/elasticsearch/elasticsearch_service.ts index ed1f2a276ebc8..1f062412edaf2 100644 --- a/src/core/server/elasticsearch/elasticsearch_service.ts +++ b/src/core/server/elasticsearch/elasticsearch_service.ts @@ -19,8 +19,9 @@ import { ConnectableObservable, Observable, Subscription } from 'rxjs'; import { filter, first, map, publishReplay, switchMap } from 'rxjs/operators'; -import { merge } from 'lodash'; + import { CoreService } from '../../types'; +import { merge } from '../../utils'; import { CoreContext } from '../core_context'; import { Logger } from '../logging'; import { ClusterClient } from './cluster_client'; diff --git a/src/core/utils/index.ts b/src/core/utils/index.ts index b6ffb57db975c..98f0800feae79 100644 --- a/src/core/utils/index.ts +++ b/src/core/utils/index.ts @@ -22,5 +22,6 @@ export * from './context'; export * from './deep_freeze'; export * from './get'; export * from './map_to_object'; +export * from './merge'; export * from './pick'; export * from './url'; diff --git a/src/core/utils/merge.test.ts b/src/core/utils/merge.test.ts new file mode 100644 index 0000000000000..aa98f51067411 --- /dev/null +++ b/src/core/utils/merge.test.ts @@ -0,0 +1,64 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { merge } from './merge'; + +describe('merge', () => { + test('empty objects', () => expect(merge({}, {})).toEqual({})); + + test('basic', () => { + expect(merge({}, { a: 1 })).toEqual({ a: 1 }); + expect(merge({ a: 0 }, {})).toEqual({ a: 0 }); + expect(merge({ a: 0 }, { a: 1 })).toEqual({ a: 1 }); + }); + + test('undefined', () => { + expect(merge({ a: undefined }, { a: 1 })).toEqual({ a: 1 }); + expect(merge({ a: 0 }, { a: undefined })).toEqual({ a: 0 }); + expect(merge({ a: undefined }, { a: undefined })).toEqual({}); + expect(merge({ a: void 0 }, { a: void 0 })).toEqual({}); + }); + + test('null', () => { + expect(merge({ a: null }, { a: 1 })).toEqual({ a: 1 }); + expect(merge({ a: 0 }, { a: null })).toEqual({ a: null }); + expect(merge({ a: null }, { a: null })).toEqual({ a: null }); + }); + + test('arrays', () => { + expect(merge({ b: [0] }, { b: [2] })).toEqual({ b: [2] }); + expect(merge({ b: [0, 1] }, { b: [2] })).toEqual({ b: [2] }); + expect(merge({ b: [0] }, { b: [2, 3] })).toEqual({ b: [2, 3] }); + expect(merge({ b: [] }, { b: [2] })).toEqual({ b: [2] }); + expect(merge({ b: [0] }, { b: [] })).toEqual({ b: [] }); + }); + + test('nested objects', () => { + expect(merge({ top: { a: 0, b: 0 } }, { top: { a: 1, c: 1 } })).toEqual({ + top: { a: 1, b: 0, c: 1 }, + }); + expect(merge({ top: { a: 0, b: 0 } }, { top: [0, 1] })).toEqual({ top: [0, 1] }); + }); + + test('multiple objects', () => { + expect(merge({}, { a: 1 }, { a: 2 })).toEqual({ a: 2 }); + expect(merge({ a: 0 }, {}, {})).toEqual({ a: 0 }); + expect(merge({ a: 0 }, { a: 1 }, {})).toEqual({ a: 1 }); + }); +}); diff --git a/src/core/utils/merge.ts b/src/core/utils/merge.ts new file mode 100644 index 0000000000000..aead3f35ba841 --- /dev/null +++ b/src/core/utils/merge.ts @@ -0,0 +1,85 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Deeply merges two objects, omitting undefined values, and not deeply merging Arrays. + * + * @remarks + * Should behave identically to lodash.merge, however it will not merge Array values like lodash does. + * Any properties with `undefined` values on both objects will be ommitted from the returned object. + */ +export function merge, TSource1 extends Record>( + baseObj: TBase, + source1: TSource1 +): TBase & TSource1; +export function merge< + TBase extends Record, + TSource1 extends Record, + TSource2 extends Record +>(baseObj: TBase, overrideObj: TSource1, overrideObj2: TSource2): TBase & TSource1 & TSource2; +export function merge< + TBase extends Record, + TSource1 extends Record, + TSource2 extends Record, + TSource3 extends Record +>( + baseObj: TBase, + overrideObj: TSource1, + overrideObj2: TSource2 +): TBase & TSource1 & TSource2 & TSource3; +export function merge>( + baseObj: Record, + ...sources: Array> +): TReturn { + const firstSource = sources[0]; + if (firstSource === undefined) { + return baseObj as TReturn; + } + + return sources + .slice(1) + .reduce( + (merged, nextSource) => mergeObjects(merged, nextSource), + mergeObjects(baseObj, firstSource) + ) as TReturn; +} + +const isMergable = (obj: any) => typeof obj === 'object' && obj !== null && !Array.isArray(obj); + +const mergeObjects = , U extends Record>( + baseObj: T, + overrideObj: U +): T & U => + [...new Set([...Object.keys(baseObj), ...Object.keys(overrideObj)])].reduce( + (merged, key) => { + const baseVal = baseObj[key]; + const overrideVal = overrideObj[key]; + + if (isMergable(baseVal) && isMergable(overrideVal)) { + merged[key] = mergeObjects(baseVal, overrideVal); + } else if (overrideVal !== undefined) { + merged[key] = overrideVal; + } else if (baseVal !== undefined) { + merged[key] = baseVal; + } + + return merged; + }, + {} as any + ); From 206ab222de1589c4a646f9b5f66f5bd401105647 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Wed, 23 Oct 2019 16:10:51 +0200 Subject: [PATCH 079/191] [ML] Force metric selection for Single Metric Viewer (#48235) * [ML] force metric selection * [ML] disable forecast if no metric selected * [ML] check all controls * [ML] fix for no partitioning fields * [ML] warning message condition * [ML] force metric selection * [ML] disable forecast if no metric selected * [ML] check all controls * [ML] fix for no partitioning fields * [ML] warning message condition * [ML] fix criteria fields * [ML] remove condition rendering for the tooltip * [ML] fix tooltip location --- .../_timeseriesexplorer.scss | 4 + .../entity_control/entity_control.js | 58 +++++--- .../timeseriesexplorer/timeseriesexplorer.js | 135 ++++++++++++++---- 3 files changed, 151 insertions(+), 46 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/_timeseriesexplorer.scss b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/_timeseriesexplorer.scss index aa172cf000d5f..0dd32ceabdb05 100644 --- a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/_timeseriesexplorer.scss +++ b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/_timeseriesexplorer.scss @@ -26,6 +26,10 @@ } } + .single-metric-request-callout { + margin: 0 $euiSize; + } + .results-container { padding: $euiSize; diff --git a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/components/entity_control/entity_control.js b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/components/entity_control/entity_control.js index 0e82002904d51..7fb741096e32b 100644 --- a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/components/entity_control/entity_control.js +++ b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/components/entity_control/entity_control.js @@ -6,12 +6,13 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { injectI18n } from '@kbn/i18n/react'; +import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; import { EuiComboBox, EuiFlexItem, EuiFormRow, + EuiToolTip, } from '@elastic/eui'; function getEntityControlOptions(entity) { @@ -29,6 +30,7 @@ export const EntityControl = injectI18n( static propTypes = { entity: PropTypes.object.isRequired, entityFieldValueChanged: PropTypes.func.isRequired, + forceSelection: PropTypes.bool.isRequired, }; state = { @@ -40,7 +42,7 @@ export const EntityControl = injectI18n( } componentDidUpdate() { - const { entity } = this.props; + const { entity, forceSelection } = this.props; const { selectedOptions } = this.state; const fieldValue = entity.fieldValue; @@ -57,6 +59,10 @@ export const EntityControl = injectI18n( selectedOptions: undefined }); } + + if (forceSelection && this.inputRef) { + this.inputRef.focus(); + } } onChange = (selectedOptions) => { @@ -70,25 +76,45 @@ export const EntityControl = injectI18n( }; render() { - const { entity, intl } = this.props; + const { entity, intl, forceSelection } = this.props; const { selectedOptions } = this.state; const options = getEntityControlOptions(entity); + const control = ( { + if (input) { + this.inputRef = input; + } + }} + style={{ minWidth: '300px' }} + placeholder={intl.formatMessage({ + id: 'xpack.ml.timeSeriesExplorer.enterValuePlaceholder', + defaultMessage: 'Enter value' + })} + singleSelection={{ asPlainText: true }} + options={options} + selectedOptions={selectedOptions} + onChange={this.onChange} + isClearable={false} + />); + + const selectMessage = (); + return ( - - + + {control} + ); diff --git a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js index d335baa3a56d8..802772e55078c 100644 --- a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js @@ -16,6 +16,7 @@ import PropTypes from 'prop-types'; import React, { createRef, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiCheckbox, @@ -26,6 +27,7 @@ import { EuiSelect, EuiSpacer, EuiText, + EuiCallOut, } from '@elastic/eui'; import chrome from 'ui/chrome'; @@ -161,6 +163,8 @@ export class TimeSeriesExplorer extends React.Component { subscriptions = new Subscription(); + _criteriaFields = null; + constructor(props) { super(props); const { jobSelectService, unsubscribeFromGlobalState } = jobSelectServiceFactory(props.globalState); @@ -216,17 +220,36 @@ export class TimeSeriesExplorer extends React.Component { tableFilter = (field, value, operator) => { const { entities } = this.state; + const entity = entities.find(({ fieldName }) => fieldName === field); - const entity = find(entities, { fieldName: field }); - if (entity !== undefined) { - if (operator === '+' && entity.fieldValue !== value) { - entity.fieldValue = value; - this.saveSeriesPropertiesAndRefresh(); - } else if (operator === '-' && entity.fieldValue === value) { - entity.fieldValue = ''; - this.saveSeriesPropertiesAndRefresh(); - } + if (entity === undefined) { + return; + } + + const { appStateHandler } = this.props; + + let resultValue = ''; + if (operator === '+' && entity.fieldValue !== value) { + resultValue = value; + } else if (operator === '-' && entity.fieldValue === value) { + resultValue = ''; + } else { + return; } + + const resultEntities = { + ...entities.reduce((appStateEntities, appStateEntity) => { + appStateEntities[appStateEntity.fieldName] = appStateEntity.fieldValue; + return appStateEntities; + }, {}), + [entity.fieldName]: resultValue, + }; + + appStateHandler(APP_STATE_ACTION.SET_ENTITIES, resultEntities); + + this.updateControlsForDetector(() => { + this.refresh(); + }); } contextChartSelectedInitCallDone = false; @@ -296,7 +319,6 @@ export class TimeSeriesExplorer extends React.Component { const searchBounds = getBoundsRoundedToInterval(bounds, focusAggregationInterval, false); const { - criteriaFields, detectorId, entities, modelPlotEnabled, @@ -310,7 +332,7 @@ export class TimeSeriesExplorer extends React.Component { }); getFocusData( - criteriaFields, + this._criteriaFields, +detectorId, focusAggregationInterval, appStateHandler(APP_STATE_ACTION.GET_FORECAST_ID), @@ -357,11 +379,11 @@ export class TimeSeriesExplorer extends React.Component { loadAnomaliesTableData = (earliestMs, latestMs) => { const { dateFormatTz } = this.props; - const { criteriaFields, selectedJob } = this.state; + const { selectedJob } = this.state; ml.results.getAnomaliesTableData( [selectedJob.job_id], - criteriaFields, + this._criteriaFields, [], interval$.getValue().val, severity$.getValue().val, @@ -430,16 +452,17 @@ export class TimeSeriesExplorer extends React.Component { this.setState({ entities: entities.map((entity) => { - if (firstRec.partition_field_name === entity.fieldName) { - entity.fieldValues = chain(resp.records).pluck('partition_field_value').uniq().value(); + const newEntity = { ...entity }; + if (firstRec.partition_field_name === newEntity.fieldName) { + newEntity.fieldValues = chain(resp.records).pluck('partition_field_value').uniq().value(); } - if (firstRec.over_field_name === entity.fieldName) { - entity.fieldValues = chain(resp.records).pluck('over_field_value').uniq().value(); + if (firstRec.over_field_name === newEntity.fieldName) { + newEntity.fieldValues = chain(resp.records).pluck('over_field_value').uniq().value(); } - if (firstRec.by_field_name === entity.fieldName) { - entity.fieldValues = chain(resp.records).pluck('by_field_value').uniq().value(); + if (firstRec.by_field_name === newEntity.fieldName) { + newEntity.fieldValues = chain(resp.records).pluck('by_field_value').uniq().value(); } - return entity; + return newEntity; }) }, callback); } @@ -582,12 +605,7 @@ export class TimeSeriesExplorer extends React.Component { } }; - // Only filter on the entity if the field has a value. const nonBlankEntities = filter(currentEntities, (entity) => { return entity.fieldValue.length > 0; }); - stateUpdate.criteriaFields = [{ - 'fieldName': 'detector_index', - 'fieldValue': +currentDetectorId } - ].concat(nonBlankEntities); if (modelPlotEnabled === false && isSourceDataChartableForDetector(selectedJob, detectorIndex) === false && @@ -641,7 +659,7 @@ export class TimeSeriesExplorer extends React.Component { // across full time range for use in the swimlane. mlResultsService.getRecordMaxScoreByTime( selectedJob.job_id, - stateUpdate.criteriaFields, + this._criteriaFields, searchBounds.min.valueOf(), searchBounds.max.valueOf(), stateUpdate.contextAggregationInterval.expression @@ -698,6 +716,10 @@ export class TimeSeriesExplorer extends React.Component { }); } + /** + * Updates local state of detector related controls from the global state. + * @param callback to invoke after a state update. + */ updateControlsForDetector = (callback = () => {}) => { const { appStateHandler } = this.props; const { detectorId, selectedJob } = this.state; @@ -729,7 +751,26 @@ export class TimeSeriesExplorer extends React.Component { entities.push({ fieldName: byFieldName, fieldValue: byFieldValue }); } + this.updateCriteriaFields(detectorIndex, entities); + this.setState({ entities }, callback); + }; + + /** + * Updates criteria fields for API calls, e.g. getAnomaliesTableData + * @param detectorIndex + * @param entities + */ + updateCriteriaFields(detectorIndex, entities) { + // Only filter on the entity if the field has a value. + const nonBlankEntities = filter(entities, (entity) => { return entity.fieldValue.length > 0; }); + this._criteriaFields = [ + { + fieldName: 'detector_index', + fieldValue: detectorIndex + }, + ...nonBlankEntities + ]; } loadForJobId(jobId, jobs) { @@ -988,6 +1029,11 @@ export class TimeSeriesExplorer extends React.Component { zoomToFocusLoaded, } = this.state; + const fieldNamesWithEmptyValues = entities + .filter(({ fieldValue }) => !fieldValue) + .map(({ fieldName }) => fieldName); + const arePartitioningFieldsProvided = fieldNamesWithEmptyValues.length === 0; + const chartProps = { modelPlotEnabled, contextChartData, @@ -1050,9 +1096,32 @@ export class TimeSeriesExplorer extends React.Component { this.previousShowForecast = showForecast; this.previousShowModelBounds = showModelBounds; + /** + * Indicates if any of the previous controls is empty. + * @type {boolean} + */ + let hasEmptyFieldValues = false; + return ( - + + {fieldNamesWithEmptyValues.length > 0 && } + color="warning" + iconType="help" + size="s" + />} +

@@ -1070,14 +1139,18 @@ export class TimeSeriesExplorer extends React.Component { {entities.map((entity) => { const entityKey = `${entity.fieldName}`; + const forceSelection = !hasEmptyFieldValues && !entity.fieldValue; + hasEmptyFieldValues = !hasEmptyFieldValues && forceSelection; return ( ); })} + {arePartitioningFieldsProvided && - + }
@@ -1100,12 +1173,14 @@ export class TimeSeriesExplorer extends React.Component { /> )} - {(jobs.length > 0 && loading === false && hasResults === false) && ( + {(arePartitioningFieldsProvided && jobs.length > 0 && loading === false && hasResults === false) && ( )} - {(jobs.length > 0 && loading === false && hasResults === true) && ( + {(arePartitioningFieldsProvided && jobs.length > 0 && loading === false && hasResults === true) && ( + + {i18n.translate('xpack.ml.timeSeriesExplorer.singleTimeSeriesAnalysisTitle', { defaultMessage: 'Single time series analysis of {functionLabel}', From 8dcde8b26a3ee151794a5c4e3031afed8667e151 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Wed, 23 Oct 2019 07:17:17 -0700 Subject: [PATCH 080/191] sort by bytes in on destination n flow tables (#48979) --- .../legacy/plugins/siem/public/store/network/reducer.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/store/network/reducer.ts b/x-pack/legacy/plugins/siem/public/store/network/reducer.ts index b2192a92fdf1c..88adc118d51dc 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/reducer.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/reducer.ts @@ -45,7 +45,7 @@ export const initialNetworkState: NetworkState = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: NetworkTopTablesFields.bytes_out, + field: NetworkTopTablesFields.bytes_in, direction: Direction.desc, }, }, @@ -78,7 +78,7 @@ export const initialNetworkState: NetworkState = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: NetworkTopTablesFields.bytes_out, + field: NetworkTopTablesFields.bytes_in, direction: Direction.desc, }, }, @@ -98,7 +98,7 @@ export const initialNetworkState: NetworkState = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: NetworkTopTablesFields.bytes_out, + field: NetworkTopTablesFields.bytes_in, direction: Direction.desc, }, }, @@ -114,7 +114,7 @@ export const initialNetworkState: NetworkState = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: NetworkTopTablesFields.bytes_out, + field: NetworkTopTablesFields.bytes_in, direction: Direction.desc, }, }, From 3a6d0d0db55b17cbd5f2a77130f7a54f096066a6 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Wed, 23 Oct 2019 15:31:33 +0100 Subject: [PATCH 081/191] Use full time interval for x-axis domain (#48754) --- .../public/pages/logs/analysis/sections/anomalies/chart.tsx | 1 + .../public/pages/logs/analysis/sections/log_rate/bar_chart.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/chart.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/chart.tsx index 73adcd13e2441..e4100c6d774b1 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/chart.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/chart.tsx @@ -94,6 +94,7 @@ export const AnomaliesChart: React.FunctionComponent<{ onBrushEnd={handleBrushEnd} tooltip={tooltipProps} baseTheme={isDarkMode ? DARK_THEME : LIGHT_THEME} + xDomain={{ min: timeRange.startTime, max: timeRange.endTime }} /> diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/bar_chart.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/bar_chart.tsx index de856bee90513..5055e3fc08239 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/bar_chart.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/bar_chart.tsx @@ -90,6 +90,7 @@ export const LogEntryRateBarChart: React.FunctionComponent<{ theme={isDarkMode ? DARK_THEME : LIGHT_THEME} showLegend legendPosition="right" + xDomain={{ min: timeRange.startTime, max: timeRange.endTime }} /> From 3d17dd35a315fe01a9f29d293c2a6f6e027e82b6 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Wed, 23 Oct 2019 07:33:47 -0700 Subject: [PATCH 082/191] [ML] Transform: Fix permissions. Fix error messages. (#49025) - Updated internal permissions docs. - Fixes regression to change data_frame to transform for privileges. - Fixes error messages for wizard source table. An error triggered by Elasticsearch would not properly be passed through, just a generic JS error would be reported. Now the error for both source table and pivot preview get passed through. - Fixes correctly reporting an error if the wizard fails to create the transform, previously a success toast would show in any case. - The screenshot below also shows the fix for #46434: A snipped of the full error message is now shown within the toast. --- .../plugins/transform/common/constants.ts | 62 ++++++++++++------- .../toast_notification_text.test.tsx | 4 +- .../components/toast_notification_text.tsx | 7 ++- .../components/authorization_provider.tsx | 16 ++--- .../source_index_preview.tsx | 7 ++- .../use_source_index_data.ts | 25 +++++++- .../step_create/step_create_form.tsx | 11 +++- .../components/step_define/pivot_preview.tsx | 25 ++------ .../step_define/use_pivot_preview_data.ts | 3 +- ...transform_management_section.test.tsx.snap | 4 +- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 12 files changed, 103 insertions(+), 63 deletions(-) diff --git a/x-pack/legacy/plugins/transform/common/constants.ts b/x-pack/legacy/plugins/transform/common/constants.ts index 3c6224c96d6f2..c85408d3c5ce6 100644 --- a/x-pack/legacy/plugins/transform/common/constants.ts +++ b/x-pack/legacy/plugins/transform/common/constants.ts @@ -24,40 +24,54 @@ export const PLUGIN = { export const API_BASE_PATH = '/api/transform/'; -// Current df_admin permission requirements: -// 1. `read` on source index -// 2. `all` on source index to create and start transform -// 3. `all` on dest index (could be less tbd) -// 3. `monitor` cluster privilege -// 4. builtin `data_frame_transforms_admin` -// 5. builtin `kibana_user` -// 6. builtin `data_frame_transforms_user` (although this is probably included in the admin) +// In order to create a transform, the API requires the following privileges: +// - transform_admin (builtin) +// - cluster privileges: manage_transform +// - index privileges: +// - indices: .transform-notifications-*, .data-frame-notifications-*, .transform-notifications-read +// - privileges: view_index_metadata, read +// - transform_user (builtin) +// - cluster privileges: monitor_transform +// - index privileges: +// - indices: .transform-notifications-*, .data-frame-notifications-*, .transform-notifications-read +// - privileges: view_index_metadata, read +// - source index: read, view_index_metadata (can be applied to a pattern e.g. farequote-*) +// - dest index: index, create_index (can be applied to a pattern e.g. df-*) +// +// In the UI additional privileges are required: +// - kibana_user (builtin) +// - dest index: monitor (applied to df-*) +// - cluster: monitor +// +// Note that users with kibana_user can see all Kibana index patterns and saved searches +// in the source selection modal when creating a transform, but the wizard will trigger +// error callouts when there are no sufficient privileges to read the actual source indices. export const APP_CLUSTER_PRIVILEGES = [ - 'cluster:monitor/data_frame/get', - 'cluster:monitor/data_frame/stats/get', - 'cluster:admin/data_frame/delete', - 'cluster:admin/data_frame/preview', - 'cluster:admin/data_frame/put', - 'cluster:admin/data_frame/start', - 'cluster:admin/data_frame/start_task', - 'cluster:admin/data_frame/stop', + 'cluster:monitor/transform/get', + 'cluster:monitor/transform/stats/get', + 'cluster:admin/transform/delete', + 'cluster:admin/transform/preview', + 'cluster:admin/transform/put', + 'cluster:admin/transform/start', + 'cluster:admin/transform/start_task', + 'cluster:admin/transform/stop', ]; // Equivalent of capabilities.canGetTransform export const APP_GET_TRANSFORM_CLUSTER_PRIVILEGES = [ - 'cluster.cluster:monitor/data_frame/get', - 'cluster.cluster:monitor/data_frame/stats/get', + 'cluster.cluster:monitor/transform/get', + 'cluster.cluster:monitor/transform/stats/get', ]; // Equivalent of capabilities.canGetTransform export const APP_CREATE_TRANSFORM_CLUSTER_PRIVILEGES = [ - 'cluster.cluster:monitor/data_frame/get', - 'cluster.cluster:monitor/data_frame/stats/get', - 'cluster.cluster:admin/data_frame/preview', - 'cluster.cluster:admin/data_frame/put', - 'cluster.cluster:admin/data_frame/start', - 'cluster.cluster:admin/data_frame/start_task', + 'cluster.cluster:monitor/transform/get', + 'cluster.cluster:monitor/transform/stats/get', + 'cluster.cluster:admin/transform/preview', + 'cluster.cluster:admin/transform/put', + 'cluster.cluster:admin/transform/start', + 'cluster.cluster:admin/transform/start_task', ]; export const APP_INDEX_PRIVILEGES = ['monitor']; diff --git a/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.test.tsx b/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.test.tsx index ffdb79a9d410b..2a0ce8ca08bec 100644 --- a/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.test.tsx +++ b/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.test.tsx @@ -25,6 +25,8 @@ describe('ToastNotificationText', () => { 'a text message that is longer than 140 characters. a text message that is longer than 140 characters. a text message that is longer than 140 characters. ', }; const { container } = render(); - expect(container.textContent).toBe('View details'); + expect(container.textContent).toBe( + 'a text message that is longer than 140 characters. a text message that is longer than 140 characters. a text message that is longer than 140 ...View details' + ); }); }); diff --git a/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.tsx b/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.tsx index 15cb23415bb3a..28bb9b2687913 100644 --- a/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.tsx +++ b/x-pack/legacy/plugins/transform/public/app/components/toast_notification_text.tsx @@ -35,7 +35,11 @@ export const ToastNotificationText: FC<{ text: any }> = ({ text }) => { return text.message; } - const formattedText = text.message ? text.message : JSON.stringify(text, null, 2); + const unformattedText = text.message ? text.message : text; + const formattedText = typeof unformattedText === 'object' ? JSON.stringify(text, null, 2) : text; + const previewText = `${formattedText.substring(0, 140)}${ + formattedText.length > 140 ? ' ...' : '' + }`; const openModal = () => { const modal = npStart.core.overlays.openModal( @@ -65,6 +69,7 @@ export const ToastNotificationText: FC<{ text: any }> = ({ text }) => { return ( <> +
{previewText}
{i18n.translate('xpack.transform.toastText.openModalButtonText', { defaultMessage: 'View details', diff --git a/x-pack/legacy/plugins/transform/public/app/lib/authorization/components/authorization_provider.tsx b/x-pack/legacy/plugins/transform/public/app/lib/authorization/components/authorization_provider.tsx index 84c7d616c19b8..8060659c78b80 100644 --- a/x-pack/legacy/plugins/transform/public/app/lib/authorization/components/authorization_provider.tsx +++ b/x-pack/legacy/plugins/transform/public/app/lib/authorization/components/authorization_provider.tsx @@ -64,25 +64,25 @@ export const AuthorizationProvider = ({ privilegesEndpoint, children }: Props) = const hasPrivilege = hasPrivilegeFactory(value.privileges); value.capabilities.canGetTransform = - hasPrivilege(['cluster', 'cluster:monitor/data_frame/get']) && - hasPrivilege(['cluster', 'cluster:monitor/data_frame/stats/get']); + hasPrivilege(['cluster', 'cluster:monitor/transform/get']) && + hasPrivilege(['cluster', 'cluster:monitor/transform/stats/get']); - value.capabilities.canCreateTransform = hasPrivilege(['cluster', 'cluster:admin/data_frame/put']); + value.capabilities.canCreateTransform = hasPrivilege(['cluster', 'cluster:admin/transform/put']); value.capabilities.canDeleteTransform = hasPrivilege([ 'cluster', - 'cluster:admin/data_frame/delete', + 'cluster:admin/transform/delete', ]); value.capabilities.canPreviewTransform = hasPrivilege([ 'cluster', - 'cluster:admin/data_frame/preview', + 'cluster:admin/transform/preview', ]); value.capabilities.canStartStopTransform = - hasPrivilege(['cluster', 'cluster:admin/data_frame/start']) && - hasPrivilege(['cluster', 'cluster:admin/data_frame/start_task']) && - hasPrivilege(['cluster', 'cluster:admin/data_frame/stop']); + hasPrivilege(['cluster', 'cluster:admin/transform/start']) && + hasPrivilege(['cluster', 'cluster:admin/transform/start_task']) && + hasPrivilege(['cluster', 'cluster:admin/transform/stop']); return ( {children} diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.tsx index 27234af868fbd..504156b8b89ba 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/source_index_preview.tsx @@ -15,6 +15,7 @@ import { EuiButtonIcon, EuiCallOut, EuiCheckbox, + EuiCodeBlock, EuiCopy, EuiFlexGroup, EuiFlexItem, @@ -142,7 +143,9 @@ export const SourceIndexPreview: React.SFC = React.memo(({ cellClick, que color="danger" iconType="cross" > -

{errorMessage}

+ + {errorMessage} + ); @@ -164,7 +167,7 @@ export const SourceIndexPreview: React.SFC = React.memo(({ cellClick, que

{i18n.translate('xpack.transform.sourceIndexPreview.SourceIndexNoDataCalloutBody', { defaultMessage: - 'The query for the source index returned no results. Please make sure the index contains documents and your query is not too restrictive.', + 'The query for the source index returned no results. Please make sure you have sufficient permissions, the index contains documents and your query is not too restrictive.', })}

diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/use_source_index_data.ts b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/use_source_index_data.ts index 9d60e3550fd75..1f8f25d33e807 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/use_source_index_data.ts +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/source_index_preview/use_source_index_data.ts @@ -32,6 +32,23 @@ export enum SOURCE_INDEX_STATUS { ERROR, } +interface ErrorResponse { + error: { + body: string; + msg: string; + path: string; + query: any; + response: string; + statusCode: number; + }; +} + +const isErrorResponse = (arg: any): arg is ErrorResponse => { + return arg.error !== undefined; +}; + +type SourceIndexSearchResponse = ErrorResponse | SearchResponse; + export interface UseSourceIndexDataReturnType { errorMessage: string; status: SOURCE_INDEX_STATUS; @@ -54,13 +71,17 @@ export const useSourceIndexData = ( setStatus(SOURCE_INDEX_STATUS.LOADING); try { - const resp: SearchResponse = await api.esSearch({ + const resp: SourceIndexSearchResponse = await api.esSearch({ index: indexPattern.title, size: SEARCH_SIZE, // Instead of using the default query (`*`), fall back to a more efficient `match_all` query. body: { query: isDefaultQuery(query) ? { match_all: {} } : query }, }); + if (isErrorResponse(resp)) { + throw resp.error; + } + const docs = resp.hits.hits; if (docs.length === 0) { @@ -101,7 +122,7 @@ export const useSourceIndexData = ( if (e.message !== undefined) { setErrorMessage(e.message); } else { - setErrorMessage(JSON.stringify(e)); + setErrorMessage(JSON.stringify(e, null, 2)); } setTableItems([]); setStatus(SOURCE_INDEX_STATUS.ERROR); diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx index 3f5ddc6238faa..47ce0f19f8f69 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx @@ -88,7 +88,16 @@ export const StepCreateForm: SFC = React.memo( setCreated(true); try { - await api.createTransform(transformId, transformConfig); + const resp = await api.createTransform(transformId, transformConfig); + + if (resp.errors !== undefined) { + if (Array.isArray(resp.errors) && resp.errors.length === 1) { + throw resp.errors[0]; + } + + throw resp.errors; + } + toastNotifications.addSuccess( i18n.translate('xpack.transform.stepCreateForm.createTransformSuccessMessage', { defaultMessage: 'Request to create transform {transformId} acknowledged.', diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.tsx index 3ac87f61d4c89..bbfc6b11d3619 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/pivot_preview.tsx @@ -12,12 +12,12 @@ import { i18n } from '@kbn/i18n'; import { EuiButtonIcon, EuiCallOut, + EuiCodeBlock, EuiCopy, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiProgress, - EuiText, EuiTitle, } from '@elastic/eui'; @@ -102,24 +102,11 @@ interface ErrorMessageProps { message: string; } -const ErrorMessage: SFC = ({ message }) => { - const error = JSON.parse(message); - - const statusCodeLabel = i18n.translate('xpack.transform.pivotPreview.statusCodeLabel', { - defaultMessage: 'Status code', - }); - - return ( - -
-        {(error.message &&
-          error.statusCode &&
-          `${statusCodeLabel}: ${error.statusCode}\n${error.message}`) ||
-          message}
-      
-
- ); -}; +const ErrorMessage: SFC = ({ message }) => ( + + {message} + +); interface PivotPreviewProps { aggs: PivotAggsConfigDict; diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/use_pivot_preview_data.ts b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/use_pivot_preview_data.ts index 7f7d06a7d18e6..17deb4db31990 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/use_pivot_preview_data.ts +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_define/use_pivot_preview_data.ts @@ -82,7 +82,7 @@ export const usePivotPreviewData = ( setPreviewMappings(resp.mappings); setStatus(PIVOT_PREVIEW_STATUS.LOADED); } catch (e) { - setErrorMessage(JSON.stringify(e)); + setErrorMessage(JSON.stringify(e, null, 2)); setPreviewData([]); setPreviewMappings({ properties: {} }); setStatus(PIVOT_PREVIEW_STATUS.ERROR); @@ -97,5 +97,6 @@ export const usePivotPreviewData = ( JSON.stringify(groupByArr), JSON.stringify(query), ]); + return { errorMessage, status, previewData, previewMappings, previewRequest }; }; diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/__snapshots__/transform_management_section.test.tsx.snap b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/__snapshots__/transform_management_section.test.tsx.snap index df8002cb7145d..8348f93b32140 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/__snapshots__/transform_management_section.test.tsx.snap +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/__snapshots__/transform_management_section.test.tsx.snap @@ -4,8 +4,8 @@ exports[`Transform: Minimal initialization 1`] = diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 40a3592440031..4ff1459637889 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6990,7 +6990,6 @@ "xpack.transform.transformList.stopActionName": "停止", "xpack.transform.transformList.stopTransformSuccessMessage": "データフレームジョブ {transformId} が停止しました", "xpack.transform.pivotPreview.copyClipboardTooltip": "ピボットプレビューの開発コンソールステートメントをクリップボードにコピーします。", - "xpack.transform.pivotPreview.statusCodeLabel": "ステータスコード", "xpack.transform.progress": "進捗", "xpack.transform.sourceIndex": "ソースインデックス", "xpack.transform.sourceIndexPreview.copyClipboardTooltip": "ソースインデックスプレビューの開発コンソールステートメントをクリップボードにコピーします。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c32636d20bf76..116a1f15a139b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7148,7 +7148,6 @@ "xpack.transform.transformList.stopActionName": "停止", "xpack.transform.transformList.stopTransformSuccessMessage": "数据帧作业 {transformId} 停止成功。", "xpack.transform.pivotPreview.copyClipboardTooltip": "将透视预览的开发控制台语句复制到剪贴板。", - "xpack.transform.pivotPreview.statusCodeLabel": "状态代码", "xpack.transform.progress": "进度", "xpack.transform.sourceIndex": "源索引", "xpack.transform.sourceIndexPreview.copyClipboardTooltip": "将源索引预览的开发控制台语句复制到剪贴板。", From 6dd1b61980065788c331ae010bb5715177bd5cc2 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Wed, 23 Oct 2019 15:48:43 +0100 Subject: [PATCH 083/191] [ML] Adding missing script fields to advanced field selects (#48812) * [ML] Adding missing script fields to advanced field selects * refactoring select option creation * refactoring select option creation * reverting accidental change * refactoring based on review --- .../legacy/plugins/ml/common/types/fields.ts | 8 ++ .../job_creator/advanced_job_creator.ts | 2 +- .../common/job_creator/job_creator.ts | 21 +++++ .../job_creator/multi_metric_job_creator.ts | 2 +- .../job_creator/population_job_creator.ts | 2 +- .../job_creator/single_metric_job_creator.ts | 2 +- .../common/job_creator/util/general.ts | 89 ++++++++++++++++--- .../json_editor_flyout/json_editor_flyout.tsx | 42 +++++---- .../time_field/time_field_select.tsx | 11 ++- .../advanced_detector_modal.tsx | 75 ++++++++-------- .../categorization_field_select.tsx | 21 +++-- .../influencers/influencers_select.tsx | 25 +++--- .../summary_count_field_select.tsx | 20 +++-- 13 files changed, 217 insertions(+), 103 deletions(-) diff --git a/x-pack/legacy/plugins/ml/common/types/fields.ts b/x-pack/legacy/plugins/ml/common/types/fields.ts index ac9e8702e0945..9e1b992eec907 100644 --- a/x-pack/legacy/plugins/ml/common/types/fields.ts +++ b/x-pack/legacy/plugins/ml/common/types/fields.ts @@ -10,6 +10,7 @@ import { KIBANA_AGGREGATION, ES_AGGREGATION, } from '../../common/constants/aggregation_types'; +import { MLCATEGORY } from '../../common/constants/field_types'; export const EVENT_RATE_FIELD_ID = '__ml_event_rate_count__'; export const METRIC_AGG_TYPE = 'metrics'; @@ -81,3 +82,10 @@ export interface AggFieldNamePair { }; excludeFrequent?: string; } + +export const mlCategory: Field = { + id: MLCATEGORY, + name: MLCATEGORY, + type: ES_FIELD_TYPES.KEYWORD, + aggregatable: false, +}; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/advanced_job_creator.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/advanced_job_creator.ts index 39f222e96abc0..54e704767b992 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/advanced_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/advanced_job_creator.ts @@ -179,7 +179,7 @@ export class AdvancedJobCreator extends JobCreator { public cloneFromExistingJob(job: Job, datafeed: Datafeed) { this._overrideConfigs(job, datafeed); - const detectors = getRichDetectors(job, datafeed, true); + const detectors = getRichDetectors(job, datafeed, this.scriptFields, true); // keep track of the custom rules for each detector const customRules = this._detectors.map(d => d.custom_rules); diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/job_creator.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/job_creator.ts index ee6f30ca4f0d3..aa16da08e3a3a 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/job_creator.ts @@ -8,6 +8,7 @@ import { SavedSearch } from 'src/legacy/core_plugins/kibana/public/discover/type import { IndexPattern } from 'ui/index_patterns'; import { IndexPatternTitle } from '../../../../../common/types/kibana'; import { ML_JOB_AGGREGATION } from '../../../../../common/constants/aggregation_types'; +import { ES_FIELD_TYPES } from '../../../../../../../../../src/plugins/data/common'; import { Job, Datafeed, Detector, JobId, DatafeedId, BucketSpan } from './configs'; import { Aggregation, Field } from '../../../../../common/types/fields'; import { createEmptyJob, createEmptyDatafeed } from './util/default_configs'; @@ -33,6 +34,7 @@ export class JobCreator { protected _subscribers: ProgressSubscriber[] = []; protected _aggs: Aggregation[] = []; protected _fields: Field[] = []; + protected _scriptFields: Field[] = []; protected _sparseData: boolean = false; private _stopAllRefreshPolls: { stop: boolean; @@ -413,6 +415,14 @@ export class JobCreator { } } + public get indices(): string[] { + return this._datafeed_config.indices; + } + + public get scriptFields(): Field[] { + return this._scriptFields; + } + public get subscribers(): ProgressSubscriber[] { return this._subscribers; } @@ -549,5 +559,16 @@ export class JobCreator { this.useDedicatedIndex = true; } this._sparseData = isSparseDataJob(job, datafeed); + + if (this._datafeed_config.script_fields !== undefined) { + this._scriptFields = Object.keys(this._datafeed_config.script_fields).map(f => ({ + id: f, + name: f, + type: ES_FIELD_TYPES.KEYWORD, + aggregatable: true, + })); + } else { + this._scriptFields = []; + } } } diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/multi_metric_job_creator.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/multi_metric_job_creator.ts index 39958b6d8f084..05a253a0962e9 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/multi_metric_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/multi_metric_job_creator.ts @@ -141,7 +141,7 @@ export class MultiMetricJobCreator extends JobCreator { public cloneFromExistingJob(job: Job, datafeed: Datafeed) { this._overrideConfigs(job, datafeed); this.createdBy = CREATED_BY_LABEL.MULTI_METRIC; - const detectors = getRichDetectors(job, datafeed, false); + const detectors = getRichDetectors(job, datafeed, this.scriptFields, false); if (datafeed.aggregations !== undefined) { // if we've converting from a single metric job, diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/population_job_creator.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/population_job_creator.ts index 89611743a4404..ac7161422628d 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/population_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/population_job_creator.ts @@ -126,7 +126,7 @@ export class PopulationJobCreator extends JobCreator { public cloneFromExistingJob(job: Job, datafeed: Datafeed) { this._overrideConfigs(job, datafeed); this.createdBy = CREATED_BY_LABEL.POPULATION; - const detectors = getRichDetectors(job, datafeed, false); + const detectors = getRichDetectors(job, datafeed, this.scriptFields, false); this.removeAllDetectors(); diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/single_metric_job_creator.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/single_metric_job_creator.ts index 5c5b7bfe712a3..aba3b08f330e8 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/single_metric_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/single_metric_job_creator.ts @@ -186,7 +186,7 @@ export class SingleMetricJobCreator extends JobCreator { public cloneFromExistingJob(job: Job, datafeed: Datafeed) { this._overrideConfigs(job, datafeed); this.createdBy = CREATED_BY_LABEL.SINGLE_METRIC; - const detectors = getRichDetectors(job, datafeed, false); + const detectors = getRichDetectors(job, datafeed, this.scriptFields, false); this.removeAllDetectors(); diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/general.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/general.ts index 15cbe5b7b8e5e..10a9260598dea 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/general.ts +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/general.ts @@ -11,32 +11,99 @@ import { ML_JOB_AGGREGATION, SPARSE_DATA_AGGREGATIONS, } from '../../../../../../common/constants/aggregation_types'; -import { EVENT_RATE_FIELD_ID, AggFieldPair } from '../../../../../../common/types/fields'; +import { MLCATEGORY } from '../../../../../../common/constants/field_types'; +import { + EVENT_RATE_FIELD_ID, + Field, + AggFieldPair, + mlCategory, +} from '../../../../../../common/types/fields'; import { mlJobService } from '../../../../../services/job_service'; import { JobCreatorType, isMultiMetricJobCreator, isPopulationJobCreator } from '../'; import { CREATED_BY_LABEL, JOB_TYPE } from './constants'; +const getFieldByIdFactory = (scriptFields: Field[]) => (id: string) => { + let field = newJobCapsService.getFieldById(id); + // if no field could be found it may be a pretend field, like mlcategory or a script field + if (field === null) { + if (id === MLCATEGORY) { + field = mlCategory; + } else if (scriptFields.length) { + field = scriptFields.find(f => f.id === id) || null; + } + } + return field; +}; + // populate the detectors with Field and Agg objects loaded from the job capabilities service -export function getRichDetectors(job: Job, datafeed: Datafeed, advanced: boolean = false) { +export function getRichDetectors( + job: Job, + datafeed: Datafeed, + scriptFields: Field[], + advanced: boolean = false +) { const detectors = advanced ? getDetectorsAdvanced(job, datafeed) : getDetectors(job, datafeed); + + const getFieldById = getFieldByIdFactory(scriptFields); + return detectors.map(d => { + let field = null; + let byField = null; + let overField = null; + let partitionField = null; + + if (d.field_name !== undefined) { + field = getFieldById(d.field_name); + } + if (d.by_field_name !== undefined) { + byField = getFieldById(d.by_field_name); + } + if (d.over_field_name !== undefined) { + overField = getFieldById(d.over_field_name); + } + if (d.partition_field_name !== undefined) { + partitionField = getFieldById(d.partition_field_name); + } + return { agg: newJobCapsService.getAggById(d.function), - field: d.field_name !== undefined ? newJobCapsService.getFieldById(d.field_name) : null, - byField: - d.by_field_name !== undefined ? newJobCapsService.getFieldById(d.by_field_name) : null, - overField: - d.over_field_name !== undefined ? newJobCapsService.getFieldById(d.over_field_name) : null, - partitionField: - d.partition_field_name !== undefined - ? newJobCapsService.getFieldById(d.partition_field_name) - : null, + field, + byField, + overField, + partitionField, excludeFrequent: d.exclude_frequent || null, description: d.detector_description || null, }; }); } +export function createFieldOptions(fields: Field[], filterOverride?: (f: Field) => boolean) { + const filter = filterOverride || (f => f.id !== EVENT_RATE_FIELD_ID); + return fields + .filter(filter) + .map(f => ({ + label: f.name, + })) + .sort((a, b) => a.label.localeCompare(b.label)); +} + +export function createScriptFieldOptions(scriptFields: Field[]) { + return scriptFields.map(f => ({ + label: f.id, + })); +} + +export function createMlcategoryFieldOption(categorizationFieldName: string | null) { + if (categorizationFieldName === null) { + return []; + } + return [ + { + label: MLCATEGORY, + }, + ]; +} + function getDetectorsAdvanced(job: Job, datafeed: Datafeed) { return processFieldlessAggs(job.analysis_config.detectors); } diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/common/json_editor_flyout/json_editor_flyout.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/common/json_editor_flyout/json_editor_flyout.tsx index 8a14a92f86843..cf26d6f532d0d 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/common/json_editor_flyout/json_editor_flyout.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/common/json_editor_flyout/json_editor_flyout.tsx @@ -18,7 +18,7 @@ import { EuiFlyoutBody, EuiSpacer, } from '@elastic/eui'; -import { Job, Datafeed } from '../../../../common/job_creator/configs'; +import { Datafeed } from '../../../../common/job_creator/configs'; import { MLJobEditor } from '../../../../../jobs_list/components/ml_job_editor'; import { isValidJson } from '../../../../../../../common/util/validation_utils'; import { JobCreatorContext } from '../../job_creator_context'; @@ -52,26 +52,32 @@ export const JsonEditorFlyout: FC = ({ isDisabled, jobEditorMode, datafee const editJsonMode = jobEditorMode === EDITOR_MODE.HIDDEN || datafeedEditorMode === EDITOR_MODE.HIDDEN; const flyOutSize = editJsonMode ? 'm' : 'l'; + const readOnlyMode = + jobEditorMode === EDITOR_MODE.READONLY && datafeedEditorMode === EDITOR_MODE.READONLY; function toggleJsonFlyout() { setSaveable(false); setShowJsonFlyout(!showJsonFlyout); } - function updateSavable(json: string, originalConfig: Job | Datafeed) { + function onJobChange(json: string) { + setJobConfigString(json); const valid = isValidJson(json); setSaveable(valid); } - function onJobChange(json: string) { - setJobConfigString(json); - - updateSavable(json, jobCreator.jobConfig); - } function onDatafeedChange(json: string) { setDatafeedConfigString(json); - - updateSavable(json, jobCreator.datafeedConfig); + let valid = isValidJson(json); + if (valid) { + // ensure that the user hasn't altered the indices list in the json. + const { indices }: Datafeed = JSON.parse(json); + const originalIndices = jobCreator.indices.sort(); + valid = + originalIndices.length === indices.length && + originalIndices.every((value, index) => value === indices[index]); + } + setSaveable(valid); } function onSave() { @@ -130,14 +136,16 @@ export const JsonEditorFlyout: FC = ({ isDisabled, jobEditorMode, datafee />
- - - - - + {readOnlyMode === false && ( + + + + + + )} diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx index 26508e13e7157..25e462dfa2286 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx @@ -9,6 +9,7 @@ import { EuiComboBox, EuiComboBoxOptionProps } from '@elastic/eui'; import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../../common/types/fields'; import { ES_FIELD_TYPES } from '../../../../../../../../../../../../src/plugins/data/public'; +import { createFieldOptions } from '../../../../../common/job_creator/util/general'; interface Props { fields: Field[]; @@ -17,12 +18,10 @@ interface Props { } export const TimeFieldSelect: FC = ({ fields, changeHandler, selectedField }) => { - const options: EuiComboBoxOptionProps[] = fields - .filter(f => f.id !== EVENT_RATE_FIELD_ID && f.type === ES_FIELD_TYPES.DATE) - .map(f => ({ - label: f.name, - })) - .sort((a, b) => a.label.localeCompare(b.label)); + const options: EuiComboBoxOptionProps[] = createFieldOptions( + fields, + f => f.id !== EVENT_RATE_FIELD_ID && f.type === ES_FIELD_TYPES.DATE + ); const selection: EuiComboBoxOptionProps[] = [ { diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx index b60239dcddd27..fb1f71f0d298a 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx @@ -15,16 +15,20 @@ import { EuiTextArea, } from '@elastic/eui'; import { JobCreatorContext } from '../../../job_creator_context'; -import { AdvancedJobCreator, JobCreatorType } from '../../../../../common/job_creator'; +import { AdvancedJobCreator } from '../../../../../common/job_creator'; +import { + createFieldOptions, + createScriptFieldOptions, + createMlcategoryFieldOption, +} from '../../../../../common/job_creator/util/general'; import { Field, Aggregation, EVENT_RATE_FIELD_ID, + mlCategory, } from '../../../../../../../../common/types/fields'; import { RichDetector } from '../../../../../common/job_creator/advanced_job_creator'; -import { ES_FIELD_TYPES } from '../../../../../../../../../../../../src/plugins/data/public'; import { ModalWrapper } from './modal_wrapper'; -import { MLCATEGORY } from '../../../../../../../../common/constants/field_types'; import { detectorToString } from '../../../../../../../util/string_utils'; import { createBasicDetector } from '../../../../../common/job_creator/util/default_configs'; @@ -55,13 +59,6 @@ const emptyOption: EuiComboBoxOptionProps = { label: '', }; -const mlCategory: Field = { - id: MLCATEGORY, - name: MLCATEGORY, - type: ES_FIELD_TYPES.KEYWORD, - aggregatable: false, -}; - const excludeFrequentOptions: EuiComboBoxOptionProps[] = [{ label: 'all' }, { label: 'none' }]; export const AdvancedDetectorModal: FC = ({ @@ -91,19 +88,28 @@ export const AdvancedDetectorModal: FC = ({ const [fieldOptionEnabled, setFieldOptionEnabled] = useState(true); const { descriptionPlaceholder, setDescriptionPlaceholder } = useDetectorPlaceholder(detector); - // list of aggregation combobox options. filtering out any aggs with no fields. + const usingScriptFields = jobCreator.scriptFields.length > 0; + // list of aggregation combobox options. + const aggOptions: EuiComboBoxOptionProps[] = aggs - .filter(a => a.fields !== undefined && a.fields.length) + .filter(agg => filterAggs(agg, usingScriptFields)) .map(createAggOption); // fields available for the selected agg - const { currentFieldOptions, setCurrentFieldOptions } = useCurrentFieldOptions(detector.agg); + const { currentFieldOptions, setCurrentFieldOptions } = useCurrentFieldOptions( + detector.agg, + jobCreator.scriptFields + ); - const allFieldOptions: EuiComboBoxOptionProps[] = fields - .filter(f => f.id !== EVENT_RATE_FIELD_ID) - .map(createFieldOption); + const allFieldOptions: EuiComboBoxOptionProps[] = [ + ...createFieldOptions(fields), + ...createScriptFieldOptions(jobCreator.scriptFields), + ]; - const splitFieldOptions = [...allFieldOptions, ...createMlcategoryField(jobCreator)]; + const splitFieldOptions = [ + ...allFieldOptions, + ...createMlcategoryFieldOption(jobCreator.categorizationFieldName), + ]; const eventRateField = fields.find(f => f.id === EVENT_RATE_FIELD_ID); @@ -120,7 +126,9 @@ export const AdvancedDetectorModal: FC = ({ if (title === mlCategory.id) { return mlCategory; } - return fields.find(a => a.id === title) || null; + return ( + fields.find(f => f.id === title) || jobCreator.scriptFields.find(f => f.id === title) || null + ); } useEffect(() => { @@ -306,6 +314,13 @@ function createAggOption(agg: Aggregation | null): EuiComboBoxOptionProps { }; } +// get list of aggregations, filtering out any aggs with no fields, +// unless script fields are being used, in which case list all fields, as it's not possible +// to determine the type of a script field and so all aggs should be available. +function filterAggs(agg: Aggregation, usingScriptFields: boolean) { + return agg.fields !== undefined && (usingScriptFields || agg.fields.length); +} + function createFieldOption(field: Field | null): EuiComboBoxOptionProps { if (field === null) { return emptyOption; @@ -331,17 +346,6 @@ function isFieldlessAgg(agg: Aggregation) { return agg.fields && agg.fields.length === 1 && agg.fields[0].id === EVENT_RATE_FIELD_ID; } -function createMlcategoryField(jobCreator: JobCreatorType): EuiComboBoxOptionProps[] { - if (jobCreator.categorizationFieldName === null) { - return []; - } - return [ - { - label: MLCATEGORY, - }, - ]; -} - function useDetectorPlaceholder(detector: RichDetector) { const [descriptionPlaceholder, setDescriptionPlaceholderString] = useState( createDefaultDescription(detector) @@ -355,22 +359,21 @@ function useDetectorPlaceholder(detector: RichDetector) { } // creates list of combobox options based on an aggregation's field list -function createFieldOptionList(agg: Aggregation | null) { - return (agg !== null && agg.fields !== undefined ? agg.fields : []) - .filter(f => f.id !== EVENT_RATE_FIELD_ID) - .map(createFieldOption); +function createFieldOptionsFromAgg(agg: Aggregation | null) { + return createFieldOptions(agg !== null && agg.fields !== undefined ? agg.fields : []); } // custom hook for storing combobox options based on an aggregation field list -function useCurrentFieldOptions(aggregation: Aggregation | null) { +function useCurrentFieldOptions(aggregation: Aggregation | null, scriptFields: Field[]) { const [currentFieldOptions, setCurrentFieldOptions] = useState( - createFieldOptionList(aggregation) + createFieldOptionsFromAgg(aggregation) ); + const scriptFieldOptions = createScriptFieldOptions(scriptFields); return { currentFieldOptions, setCurrentFieldOptions: (agg: Aggregation | null) => - setCurrentFieldOptions(createFieldOptionList(agg)), + setCurrentFieldOptions([...createFieldOptionsFromAgg(agg), ...scriptFieldOptions]), }; } diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx index 226ce20c72da7..f9d99f7d0f4e0 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx @@ -4,11 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC } from 'react'; +import React, { FC, useContext } from 'react'; import { EuiComboBox, EuiComboBoxOptionProps } from '@elastic/eui'; +import { JobCreatorContext } from '../../../job_creator_context'; import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../../common/types/fields'; import { ES_FIELD_TYPES } from '../../../../../../../../../../../../src/plugins/data/public'; +import { + createFieldOptions, + createScriptFieldOptions, +} from '../../../../../common/job_creator/util/general'; interface Props { fields: Field[]; @@ -17,12 +22,14 @@ interface Props { } export const CategorizationFieldSelect: FC = ({ fields, changeHandler, selectedField }) => { - const options: EuiComboBoxOptionProps[] = fields - .filter(f => f.id !== EVENT_RATE_FIELD_ID && f.type === ES_FIELD_TYPES.KEYWORD) - .map(f => ({ - label: f.name, - })) - .sort((a, b) => a.label.localeCompare(b.label)); + const { jobCreator } = useContext(JobCreatorContext); + const options: EuiComboBoxOptionProps[] = [ + ...createFieldOptions( + fields, + f => f.id !== EVENT_RATE_FIELD_ID && f.type === ES_FIELD_TYPES.KEYWORD + ), + ...createScriptFieldOptions(jobCreator.scriptFields), + ]; const selection: EuiComboBoxOptionProps[] = [ { diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/influencers/influencers_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/influencers/influencers_select.tsx index b1f9c6dbcf555..293202415ced0 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/influencers/influencers_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/influencers/influencers_select.tsx @@ -8,8 +8,12 @@ import React, { FC, useContext } from 'react'; import { EuiComboBox, EuiComboBoxOptionProps } from '@elastic/eui'; import { JobCreatorContext } from '../../../job_creator_context'; -import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../../common/types/fields'; -import { MLCATEGORY } from '../../../../../../../../common/constants/field_types'; +import { Field } from '../../../../../../../../common/types/fields'; +import { + createFieldOptions, + createScriptFieldOptions, + createMlcategoryFieldOption, +} from '../../../../../common/job_creator/util/general'; interface Props { fields: Field[]; @@ -19,18 +23,11 @@ interface Props { export const InfluencersSelect: FC = ({ fields, changeHandler, selectedInfluencers }) => { const { jobCreator } = useContext(JobCreatorContext); - const options: EuiComboBoxOptionProps[] = fields - .filter(f => f.id !== EVENT_RATE_FIELD_ID) - .map(f => ({ - label: f.name, - })) - .sort((a, b) => a.label.localeCompare(b.label)); - - if (jobCreator.categorizationFieldName !== null) { - options.push({ - label: MLCATEGORY, - }); - } + const options: EuiComboBoxOptionProps[] = [ + ...createFieldOptions(fields), + ...createScriptFieldOptions(jobCreator.scriptFields), + ...createMlcategoryFieldOption(jobCreator.categorizationFieldName), + ]; const selection: EuiComboBoxOptionProps[] = selectedInfluencers.map(i => ({ label: i })); diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/summary_count_field/summary_count_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/summary_count_field/summary_count_field_select.tsx index d22d2ee111805..6bf510a70bfcb 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/summary_count_field/summary_count_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/summary_count_field/summary_count_field_select.tsx @@ -4,10 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { FC } from 'react'; +import React, { FC, useContext } from 'react'; import { EuiComboBox, EuiComboBoxOptionProps } from '@elastic/eui'; -import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../../common/types/fields'; +import { JobCreatorContext } from '../../../job_creator_context'; +import { Field } from '../../../../../../../../common/types/fields'; +import { + createFieldOptions, + createScriptFieldOptions, +} from '../../../../../common/job_creator/util/general'; interface Props { fields: Field[]; @@ -16,12 +21,11 @@ interface Props { } export const SummaryCountFieldSelect: FC = ({ fields, changeHandler, selectedField }) => { - const options: EuiComboBoxOptionProps[] = fields - .filter(f => f.id !== EVENT_RATE_FIELD_ID) - .map(f => ({ - label: f.name, - })) - .sort((a, b) => a.label.localeCompare(b.label)); + const { jobCreator } = useContext(JobCreatorContext); + const options: EuiComboBoxOptionProps[] = [ + ...createFieldOptions(fields), + ...createScriptFieldOptions(jobCreator.scriptFields), + ]; const selection: EuiComboBoxOptionProps[] = [ { From c29ffbaa6032b10add8ad1afd88900a4b664b999 Mon Sep 17 00:00:00 2001 From: Chris Davies Date: Wed, 23 Oct 2019 11:28:27 -0400 Subject: [PATCH 084/191] [Lens] Add loading indicator and improved empty state to datapanel (#48566) --- .../indexpattern_plugin/datapanel.test.tsx | 118 +++++++++++++++++- .../public/indexpattern_plugin/datapanel.tsx | 105 +++++++++------- .../plugins/lens/public/loader.test.tsx | 57 +++++++++ x-pack/legacy/plugins/lens/public/loader.tsx | 47 +++++++ 4 files changed, 281 insertions(+), 46 deletions(-) create mode 100644 x-pack/legacy/plugins/lens/public/loader.test.tsx create mode 100644 x-pack/legacy/plugins/lens/public/loader.tsx diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx index f7f56b948cfe6..ec933d8e82876 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx @@ -13,6 +13,7 @@ import { coreMock } from 'src/core/public/mocks'; import { IndexPatternPrivateState } from './types'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import { ChangeIndexPattern } from './change_indexpattern'; +import { EuiProgress } from '@elastic/eui'; jest.mock('ui/new_platform'); jest.mock('../../../../../../src/legacy/ui/public/registry/field_formats'); @@ -265,7 +266,14 @@ describe('IndexPattern Data Panel', () => { }); describe('loading existence data', () => { - async function testExistenceLoading(stateChanges?: unknown, propChanges?: unknown) { + function waitForPromises() { + return Promise.resolve() + .catch(() => {}) + .then(() => {}) + .then(() => {}); + } + + function testProps() { const setState = jest.fn(); core.http.get = jest.fn(async (url: string) => { const parts = url.split('/'); @@ -277,7 +285,7 @@ describe('IndexPattern Data Panel', () => { ), }; }); - const props = { + return { ...defaultProps, changeIndexPattern: jest.fn(), setState, @@ -301,8 +309,17 @@ describe('IndexPattern Data Panel', () => { }, } as IndexPatternPrivateState, }; + } + + async function testExistenceLoading(stateChanges?: unknown, propChanges?: unknown) { + const props = testProps(); const inst = mountWithIntl(); - inst.update(); + + act(() => { + inst.update(); + }); + + await waitForPromises(); if (stateChanges || propChanges) { act(() => { @@ -316,9 +333,10 @@ describe('IndexPattern Data Panel', () => { }); inst.update(); }); + await waitForPromises(); } - return setState; + return props.setState; } it('loads existence data', async () => { @@ -446,6 +464,98 @@ describe('IndexPattern Data Panel', () => { }, }); }); + + it('shows a loading indicator when loading', async () => { + const inst = mountWithIntl(); + + expect(inst.find(EuiProgress).length).toEqual(1); + + await waitForPromises(); + inst.update(); + + expect(inst.find(EuiProgress).length).toEqual(0); + }); + + it('does not perform multiple queries at once', async () => { + let queryCount = 0; + let overlapCount = 0; + const props = testProps(); + + core.http.get = jest.fn((url: string) => { + if (queryCount) { + ++overlapCount; + } + ++queryCount; + + const parts = url.split('/'); + const indexPatternTitle = parts[parts.length - 1]; + const result = Promise.resolve({ + indexPatternTitle, + existingFieldNames: ['field_1', 'field_2'].map( + fieldName => `${indexPatternTitle}_${fieldName}` + ), + }); + + result.then(() => --queryCount); + + return result; + }); + + const inst = mountWithIntl(); + + inst.update(); + + act(() => { + ((inst.setProps as unknown) as (props: unknown) => {})({ + ...props, + dateRange: { fromDate: '2019-01-01', toDate: '2020-01-02' }, + }); + inst.update(); + }); + + act(() => { + ((inst.setProps as unknown) as (props: unknown) => {})({ + ...props, + dateRange: { fromDate: '2019-01-01', toDate: '2020-01-03' }, + }); + inst.update(); + }); + + await waitForPromises(); + + expect(core.http.get).toHaveBeenCalledTimes(2); + expect(overlapCount).toEqual(0); + }); + + it('shows all fields if empty state button is clicked', async () => { + const props = testProps(); + + core.http.get = jest.fn((url: string) => { + return Promise.resolve({ + indexPatternTitle: props.currentIndexPatternId, + existingFieldNames: [], + }); + }); + + const inst = mountWithIntl(); + + inst.update(); + await waitForPromises(); + + expect(inst.find('[data-test-subj="lnsFieldListPanelField"]').length).toEqual(0); + + act(() => { + inst + .find('[data-test-subj="lnsDataPanelShowAllFields"]') + .first() + .simulate('click'); + inst.update(); + }); + + expect( + props.setState.mock.calls.map(([fn]) => fn(props.state)).filter(s => s.showEmptyFields) + ).toHaveLength(1); + }); }); describe('while showing empty fields', () => { diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx index 7fa8175e1857c..e65f7bbc5ba6c 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx @@ -23,6 +23,7 @@ import { EuiSwitch, EuiFacetButton, EuiIcon, + EuiButton, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -38,6 +39,7 @@ import { import { trackUiEvent } from '../lens_ui_telemetry'; import { syncExistingFields } from './loader'; import { fieldExists } from './pure_helpers'; +import { Loader } from '../loader'; export type Props = DatasourceDataPanelProps & { changeIndexPattern: ( @@ -86,9 +88,16 @@ export function IndexPatternDataPanel({ [state, setState] ); - const onToggleEmptyFields = useCallback(() => { - setState(prevState => ({ ...prevState, showEmptyFields: !prevState.showEmptyFields })); - }, [setState]); + const onToggleEmptyFields = useCallback( + (showEmptyFields?: boolean) => { + setState(prevState => ({ + ...prevState, + showEmptyFields: + showEmptyFields === undefined ? !prevState.showEmptyFields : showEmptyFields, + })); + }, + [setState] + ); const indexPatternList = uniq( Object.values(state.layers) @@ -102,34 +111,38 @@ export function IndexPatternDataPanel({ timeFieldName: indexPatterns[id].timeFieldName, })); - useEffect(() => { - syncExistingFields({ - dateRange, - setState, - indexPatterns: indexPatternList, - fetchJson: core.http.get, - }); - }, [ - dateRange.fromDate, - dateRange.toDate, - indexPatternList.map(x => `${x.title}:${x.timeFieldName}`).join(','), - ]); - return ( - + <> + + syncExistingFields({ + dateRange, + setState, + indexPatterns: indexPatternList, + fetchJson: core.http.get, + }) + } + loadDeps={[ + dateRange.fromDate, + dateRange.toDate, + indexPatternList.map(x => `${x.title}:${x.timeFieldName}`).join(','), + ]} + /> + + ); } @@ -158,7 +171,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ indexPatterns: Record; dragDropContext: DragContextState; showEmptyFields: boolean; - onToggleEmptyFields: () => void; + onToggleEmptyFields: (showEmptyFields?: boolean) => void; onChangeIndexPattern: (newId: string) => void; existingFields: IndexPatternPrivateState['existingFields']; }) { @@ -201,6 +214,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ const currentIndexPattern = indexPatterns[currentIndexPatternId]; const allFields = currentIndexPattern.fields; const fieldByName = indexBy(allFields, 'name'); + const clearLocalState = () => setLocalState(s => ({ ...s, nameFilter: '', typeFilter: [] })); const lazyScroll = () => { if (scrollContainer) { @@ -279,12 +293,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ indexPatternRefs={indexPatternRefs} onChangeIndexPattern={(newId: string) => { onChangeIndexPattern(newId); - - setLocalState(s => ({ - ...s, - nameFilter: '', - typeFilter: [], - })); + clearLocalState(); }} /> @@ -303,11 +312,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ }), onClick: () => { trackUiEvent('indexpattern_filters_cleared'); - setLocalState(s => ({ - ...s, - nameFilter: '', - typeFilter: [], - })); + clearLocalState(); }, }} > @@ -448,6 +453,22 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ })}

+ {(!showEmptyFields || + localState.typeFilter.length || + localState.nameFilter.length) && ( + { + trackUiEvent('show_empty_fields_clicked'); + clearLocalState(); + onToggleEmptyFields(true); + }} + > + {i18n.translate('xpack.lens.indexPatterns.showAllFields.buttonText', { + defaultMessage: 'Show All Fields', + })} + + )}
)} diff --git a/x-pack/legacy/plugins/lens/public/loader.test.tsx b/x-pack/legacy/plugins/lens/public/loader.test.tsx new file mode 100644 index 0000000000000..f448849d1043c --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/loader.test.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiProgress } from '@elastic/eui'; +import { Loader } from './loader'; +import { mount } from 'enzyme'; + +describe('loader', () => { + it('shows a loading indicator when loading', async () => { + const load = jest.fn(() => Promise.resolve()); + const inst = mount(); + + expect(inst.find(EuiProgress).length).toEqual(1); + + await load(); + inst.update(); + + expect(inst.find(EuiProgress).length).toEqual(0); + }); + + it('hides loading indicator when failed', async () => { + const load = jest.fn(() => Promise.reject()); + const inst = mount(); + + expect(inst.find(EuiProgress).length).toEqual(1); + + await Promise.resolve(); + inst.update(); + + expect(inst.find(EuiProgress).length).toEqual(0); + }); + + it('does not run load in parallel', async () => { + let count = 0; + let ranInParallel = false; + const load = jest.fn(() => { + if (count) { + ranInParallel = true; + } + ++count; + return Promise.resolve().then(() => --count); + }); + const inst = mount(); + inst.setProps({ loadDeps: ['foo'] }); + inst.update(); + + await Promise.resolve(); + inst.update(); + + expect(load).toHaveBeenCalledTimes(2); + expect(ranInParallel).toBeFalsy(); + }); +}); diff --git a/x-pack/legacy/plugins/lens/public/loader.tsx b/x-pack/legacy/plugins/lens/public/loader.tsx new file mode 100644 index 0000000000000..ebbb006d837b0 --- /dev/null +++ b/x-pack/legacy/plugins/lens/public/loader.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useEffect, useRef } from 'react'; +import { EuiProgress } from '@elastic/eui'; + +/** + * Executes the specified load function any time loadDeps changes. Ensures the load + * function is never run in parallel. Shows a loading indicator while loading. + */ +export function Loader(props: { load: () => Promise; loadDeps: unknown[] }) { + const [isProcessing, setIsProcessing] = useState(false); + const prevRequest = useRef | undefined>(undefined); + const nextRequest = useRef<(() => void) | undefined>(undefined); + + useEffect(function performLoad() { + if (prevRequest.current) { + nextRequest.current = performLoad; + return; + } + + setIsProcessing(true); + prevRequest.current = props + .load() + .catch(() => {}) + .then(() => { + const reload = nextRequest.current; + prevRequest.current = undefined; + nextRequest.current = undefined; + + if (reload) { + reload(); + } else { + setIsProcessing(false); + } + }); + }, props.loadDeps); + + if (!isProcessing) { + return null; + } + + return ; +} From 52574e476a31d1414aeb6e2fd4078c5cc18861cb Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 23 Oct 2019 17:29:11 +0200 Subject: [PATCH 085/191] Initial proposal for fix (#48880) --- .../editor/legacy/console_editor/keyboard_shortcuts.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/keyboard_shortcuts.ts b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/keyboard_shortcuts.ts index 1be571f2739ac..d1605c1aefa56 100644 --- a/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/keyboard_shortcuts.ts +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/editor/legacy/console_editor/keyboard_shortcuts.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import { throttle } from 'lodash'; interface Actions { input: any; // TODO: Wrap this in an editor interface @@ -24,6 +25,10 @@ interface Actions { } export function registerCommands({ input, sendCurrentRequestToES, openDocumentation }: Actions) { + const throttledAutoIndent = throttle(() => input.autoIndent(), 500, { + leading: true, + trailing: true, + }); input.commands.addCommand({ name: 'send to elasticsearch', bindKey: { win: 'Ctrl-Enter', mac: 'Command-Enter' }, @@ -40,7 +45,7 @@ export function registerCommands({ input, sendCurrentRequestToES, openDocumentat name: 'auto indent request', bindKey: { win: 'Ctrl-I', mac: 'Command-I' }, exec: () => { - input.autoIndent(); + throttledAutoIndent(); }, }); input.commands.addCommand({ From 0b2c3cd438f0e8f391aa2952676795c5c580c5f2 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Wed, 23 Oct 2019 10:50:54 -0600 Subject: [PATCH 086/191] [SIEM] Fixes SIEM App not loading in IE11 (#49047) ## Summary Resolves https://github.com/elastic/kibana/issues/47609 by updating [react-reverse-portal](https://github.com/httptoolkit/react-reverse-portal) to 1.0.4 which includes an ES5 distribution that fixes the SIEM app not loading in IE11. SIEM App now loads and DnD from within the custom map tooltips functions as intended: ![ie11-map-tooltip-fix](https://user-images.githubusercontent.com/2946766/67401431-6158e680-f56c-11e9-8eb3-b1eb6c393c31.gif) ### Checklist Use ~~strikethroughs~~ to remove checklist items you don't feel are applicable to this PR. - [x] This was checked for cross-browser compatibility, [including a check against IE11](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) * Tested in Chrome, FF, Safari & our good friend IE11 - [ ] ~Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md)~ - [ ] ~[Documentation](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#writing-documentation) was added for features that require explanation or tutorials~ - [ ] ~[Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios~ - [ ] ~This was checked for [keyboard-only and screenreader accessibility](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Accessibility_testing_checklist)~ ### For maintainers - [ ] ~This was checked for breaking API changes and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)~ - [ ] ~This includes a feature addition or change that requires a release note and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)~ --- x-pack/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index f8480d7ad9a5b..d55910ccd5a5c 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -336,7 +336,7 @@ "react-redux": "^5.1.1", "react-redux-request": "^1.5.6", "react-resize-detector": "^4.2.0", - "react-reverse-portal": "^1.0.2", + "react-reverse-portal": "^1.0.4", "react-router-dom": "^4.3.1", "react-select": "^1.2.1", "react-shortcuts": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index ec29bdee338ef..934c908497d0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23332,10 +23332,10 @@ react-resize-detector@^4.0.5, react-resize-detector@^4.2.0: raf-schd "^4.0.0" resize-observer-polyfill "^1.5.1" -react-reverse-portal@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/react-reverse-portal/-/react-reverse-portal-1.0.3.tgz#38cd2d40f40862352dd63905f9b923f9c41f474b" - integrity sha512-mCtpp3BzPedmGTAMqT2v5U1hwnAvRfSqMusriON/GxnedT9gvNNTvai24NnrfKfQ78zqPo4e3N5nWPLpY7bORQ== +react-reverse-portal@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/react-reverse-portal/-/react-reverse-portal-1.0.4.tgz#d127d2c9147549b25c4959aba1802eca4b144cd4" + integrity sha512-WESex/wSjxHwdG7M0uwPNkdQXaLauXNHi4INQiRybmFIXVzAqgf/Ak2OzJ4MLf4UuCD/IzEwJOkML2SxnnontA== react-router-dom@4.2.2: version "4.2.2" From 7f55c9573ac2e9347bc0bba7cc1fd1f2945764a6 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Wed, 23 Oct 2019 18:03:09 +0100 Subject: [PATCH 087/191] [ML] Fixes field formatter used for chart and anomaly table values (#49030) --- .../ml/public/services/field_format_service.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/services/field_format_service.js b/x-pack/legacy/plugins/ml/public/services/field_format_service.js index ddcf156069639..4d99ec3fe48d1 100644 --- a/x-pack/legacy/plugins/ml/public/services/field_format_service.js +++ b/x-pack/legacy/plugins/ml/public/services/field_format_service.js @@ -79,8 +79,11 @@ class FieldFormatService { // e.g. distinct_count(clientip) should be formatted as a count, not as an IP address. let fieldFormat = undefined; if (esAggName !== 'cardinality') { - const indexPatternFields = _.get(fullIndexPattern, 'fields', []); - fieldFormat = _.get(indexPatternFields, [fieldName, 'format']); + const fieldList = _.get(fullIndexPattern, 'fields', []); + const field = fieldList.getByName(fieldName); + if (field !== undefined) { + fieldFormat = field.format; + } } return fieldFormat; @@ -99,13 +102,16 @@ class FieldFormatService { getIndexPatternById(indexPatternId) .then((indexPatternData) => { // Store the FieldFormat for each job by detector_index. - const fieldsByName = _.get(indexPatternData, 'fields', []); + const fieldList = _.get(indexPatternData, 'fields', []); _.each(detectors, (dtr) => { const esAgg = mlFunctionToESAggregation(dtr.function); // distinct_count detectors should fall back to the default // formatter as the values are just counts. if (dtr.field_name !== undefined && esAgg !== 'cardinality') { - formatsByDetector[dtr.detector_index] = _.get(fieldsByName, [dtr.field_name, 'format']); + const field = fieldList.getByName(dtr.field_name); + if (field !== undefined) { + formatsByDetector[dtr.detector_index] = field.format; + } } }); From bd3525eb20d87ff7b7024b7a7bf4d503c33b17b6 Mon Sep 17 00:00:00 2001 From: Zacqary Adam Xeper Date: Wed, 23 Oct 2019 12:29:59 -0500 Subject: [PATCH 088/191] [Logs UI] Fix initial accuracy of logs minimap click (#48826) * [Logs UI] Fix initial accuracy of logs minimap click * Fix aberrant request to loadEntriesAfter when using minimap --- .../components/logging/log_minimap/log_minimap.tsx | 3 ++- .../logging/log_text_stream/vertical_scroll_panel.tsx | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx index 9c81cda0a3fb6..90b1e455d477e 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx @@ -80,7 +80,8 @@ export class LogMinimap extends React.Component { - const { svgPosition } = this.state; + if (!this.dragTargetArea) return; + const svgPosition = this.dragTargetArea.getBoundingClientRect(); const clickedYPosition = event.clientY - svgPosition.top; const clickedTime = Math.floor(this.getYScale().invert(clickedYPosition)); this.setState({ diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx index 8edec4d1777d0..7ff4a2cacee09 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx @@ -155,7 +155,7 @@ export class VerticalScrollPanel extends React.PureComponent< } = this; if (scrollRef.current === null || !target || childDimensions.size <= 0) { - return; + return false; } const targetDimensions = childDimensions.get(target); @@ -166,15 +166,20 @@ export class VerticalScrollPanel extends React.PureComponent< // opposed to being in direct response to user input this.nextScrollEventFromCenterTarget = true; scrollRef.current.scrollTop = targetDimensions.top + targetOffset - scrollViewHeight / 2; + return true; } + return false; }; public handleUpdatedChildren = (target: Child | undefined, offset: number | undefined) => { this.updateChildDimensions(); + let centerTargetWillReportChildren = false; if (!!target) { - this.centerTarget(target, offset); + centerTargetWillReportChildren = this.centerTarget(target, offset); + } + if (!centerTargetWillReportChildren) { + this.reportVisibleChildren(); } - this.reportVisibleChildren(); }; public componentDidMount() { From fb7310335251882a295b2be181baedff80f129cd Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Wed, 23 Oct 2019 12:56:00 -0500 Subject: [PATCH 089/191] Add lru-cache shim (#49014) --- webpackShims/lru-cache.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 webpackShims/lru-cache.js diff --git a/webpackShims/lru-cache.js b/webpackShims/lru-cache.js new file mode 100644 index 0000000000000..9cc11a516378e --- /dev/null +++ b/webpackShims/lru-cache.js @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +module.exports = require('../node_modules/lru-cache'); From db6d2251e194149933af92ed6e5a096302d0a070 Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Wed, 23 Oct 2019 11:04:03 -0700 Subject: [PATCH 090/191] Updating debug to 2.6.9 (#48997) --- package.json | 3 ++- yarn.lock | 14 +------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 36fb116a3dc18..101cee27aa28f 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,8 @@ "**/typescript": "3.5.3", "**/graphql-toolkit/lodash": "^4.17.13", "**/isomorphic-git/**/base64-js": "^1.2.1", - "**/babel-plugin-inline-react-svg/svgo/js-yaml": "^3.13.1" + "**/babel-plugin-inline-react-svg/svgo/js-yaml": "^3.13.1", + "**/image-diff/gm/debug": "^2.6.9" }, "workspaces": { "packages": [ diff --git a/yarn.lock b/yarn.lock index 934c908497d0d..67954e168ac91 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9756,7 +9756,7 @@ debug-fabulous@1.X: memoizee "0.4.X" object-assign "4.X" -debug@2.6.9, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.0.0, debug@^2.1.0, debug@^2.1.1, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9, debug@~2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -9791,13 +9791,6 @@ debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" -debug@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - integrity sha1-+HBX6ZWxofauaklgZkE3vFbwOdo= - dependencies: - ms "0.7.1" - debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -19708,11 +19701,6 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" From ef8c746d653a45909e7542d3db40fbae29008461 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Wed, 23 Oct 2019 14:26:16 -0400 Subject: [PATCH 091/191] [ML] DF Analytics: check source index contains numerical fields only once it has been selected (#48843) * Move sourceIndex fields check from flyout open to source index selection * reset sourceIndex checks when switching job type. add helpful text for no field options for regression * update types. use FormattedMessages * use comboBox options format to store sourceIndex title/id in one place * small refactors and remove loadIndexPatterns from resolver * refactor destinationIndexPatternTitleExists checks in reducer --- .../create_analytics_form.tsx | 112 +++++++++++++----- .../use_create_analytics_form/actions.ts | 5 +- .../use_create_analytics_form/reducer.ts | 15 +-- .../hooks/use_create_analytics_form/state.ts | 15 ++- .../use_create_analytics_form.ts | 47 +++----- .../pages/analytics_management/route.ts | 2 - 6 files changed, 116 insertions(+), 80 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx index 35a0e1c82cf33..ab8cc5a5982bb 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_form/create_analytics_form.tsx @@ -17,6 +17,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { metadata } from 'ui/metadata'; import { IndexPattern, INDEX_PATTERN_ILLEGAL_CHARACTERS } from 'ui/index_patterns'; @@ -46,19 +47,14 @@ const NUMERICAL_FIELD_TYPES = new Set([ 'scaled_float', ]); +// List of system fields we want to ignore for the numeric field check. +const OMIT_FIELDS: string[] = ['_source', '_type', '_index', '_id', '_version', '_score']; + export const CreateAnalyticsForm: FC = ({ actions, state }) => { const { setFormState } = actions; const kibanaContext = useKibanaContext(); - const { - form, - indexPatternsMap, - indexPatternsWithNumericFields, - indexPatternTitles, - isAdvancedEditorEnabled, - isJobCreated, - requestMessages, - } = state; + const { form, indexPatternsMap, isAdvancedEditorEnabled, isJobCreated, requestMessages } = state; const { createIndexPattern, @@ -80,14 +76,44 @@ export const CreateAnalyticsForm: FC = ({ actions, sta sourceIndex, sourceIndexNameEmpty, sourceIndexNameValid, + sourceIndexContainsNumericalFields, + sourceIndexFieldsCheckFailed, trainingPercent, } = form; + // Find out if index pattern contain numeric fields. Provides a hint in the form + // that an analytics jobs is not able to identify outliers if there are no numeric fields present. + const validateSourceIndexFields = async () => { + try { + const indexPattern: IndexPattern = await kibanaContext.indexPatterns.get( + indexPatternsMap[sourceIndex].value + ); + const containsNumericalFields: boolean = indexPattern.fields.some( + ({ name, type }) => !OMIT_FIELDS.includes(name) && type === 'number' + ); + + setFormState({ + sourceIndexContainsNumericalFields: containsNumericalFields, + sourceIndexFieldsCheckFailed: false, + }); + } catch (e) { + setFormState({ + sourceIndexFieldsCheckFailed: true, + }); + } + }; + const loadDependentFieldOptions = async () => { - setFormState({ loadingDepFieldOptions: true, dependentVariable: '' }); + setFormState({ + loadingDepFieldOptions: true, + dependentVariable: '', + // Reset outlier detection sourceIndex checks to default values if we've switched to regression + sourceIndexFieldsCheckFailed: false, + sourceIndexContainsNumericalFields: true, + }); try { const indexPattern: IndexPattern = await kibanaContext.indexPatterns.get( - indexPatternsMap[sourceIndex] + indexPatternsMap[sourceIndex].value ); if (indexPattern !== undefined) { @@ -109,14 +135,43 @@ export const CreateAnalyticsForm: FC = ({ actions, sta }); } } catch (e) { - // TODO: ensure error messages show up correctly setFormState({ loadingDepFieldOptions: false, dependentVariableFetchFail: true }); } }; + const getSourceIndexErrorMessages = () => { + const errors = []; + if (!sourceIndexNameEmpty && !sourceIndexNameValid) { + errors.push( + + + + ); + } + + if (sourceIndexFieldsCheckFailed === true) { + errors.push( + + + + ); + } + + return errors; + }; + useEffect(() => { if (jobType === JOB_TYPES.REGRESSION && sourceIndexNameEmpty === false) { loadDependentFieldOptions(); + } else if (jobType === JOB_TYPES.OUTLIER_DETECTION && sourceIndexNameEmpty === false) { + validateSourceIndexFields(); } }, [sourceIndex, jobType, sourceIndexNameEmpty]); @@ -201,32 +256,20 @@ export const CreateAnalyticsForm: FC = ({ actions, sta isInvalid={(!jobIdEmpty && !jobIdValid) || jobIdExists} /> - {/* TODO: Does the source index message below apply for regression jobs as well? Same for all validation messages below */} - {i18n.translate('xpack.ml.dataframe.analytics.create.sourceIndexInvalidError', { - defaultMessage: - 'Invalid source index name, it cannot contain spaces or the characters: {characterList}', - values: { characterList }, - })} -
, - ] - } + error={getSourceIndexErrorMessages()} > {!isJobCreated && ( @@ -238,9 +281,11 @@ export const CreateAnalyticsForm: FC = ({ actions, sta } )} singleSelection={{ asPlainText: true }} - options={indexPatternTitles.sort().map(d => ({ label: d }))} + options={Object.values(indexPatternsMap).sort((a, b) => + a.label.localeCompare(b.label) + )} selectedOptions={ - indexPatternTitles.includes(sourceIndex) ? [{ label: sourceIndex }] : [] + indexPatternsMap[sourceIndex] !== undefined ? [{ label: sourceIndex }] : [] } onChange={selectedOptions => setFormState({ sourceIndex: selectedOptions[0].label || '' }) @@ -323,6 +368,17 @@ export const CreateAnalyticsForm: FC = ({ actions, sta defaultMessage: 'Dependent variable', } )} + helpText={ + dependentVariableOptions.length === 0 && + dependentVariableFetchFail === false && + !sourceIndexNameEmpty && + i18n.translate( + 'xpack.ml.dataframe.analytics.create.dependentVariableOptionsNoNumericalFields', + { + defaultMessage: 'No numeric type fields were found for this index pattern.', + } + ) + } error={ dependentVariableFetchFail === true && [ diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts index f9d11605b167a..a763bd9639bf3 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/actions.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { FormMessage, State } from './state'; +import { FormMessage, State, SourceIndexMap } from './state'; export enum ACTION { ADD_REQUEST_MESSAGE, @@ -48,8 +48,7 @@ export type Action = | { type: ACTION.SET_INDEX_PATTERN_TITLES; payload: { - indexPatternTitles: State['indexPatternTitles']; - indexPatternsWithNumericFields: State['indexPatternsWithNumericFields']; + indexPatternsMap: SourceIndexMap; }; } | { type: ACTION.SET_IS_JOB_CREATED; isJobCreated: State['isJobCreated'] } diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts index 135f29adf1bae..037ec95ec17cc 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts @@ -61,9 +61,8 @@ export const validateAdvancedEditor = (state: State): State => { const destinationIndexName = idx(jobConfig, _ => _.dest.index) || ''; const destinationIndexNameEmpty = destinationIndexName === ''; const destinationIndexNameValid = isValidIndexName(destinationIndexName); - const destinationIndexPatternTitleExists = state.indexPatternTitles.some( - name => destinationIndexName === name - ); + const destinationIndexPatternTitleExists = + state.indexPatternsMap[destinationIndexName] !== undefined; let dependentVariableEmpty = false; if (isRegressionAnalysis(jobConfig.analysis)) { @@ -207,9 +206,8 @@ export function reducer(state: State, action: Action): State { ); newFormState.destinationIndexNameEmpty = newFormState.destinationIndex === ''; newFormState.destinationIndexNameValid = isValidIndexName(newFormState.destinationIndex); - newFormState.destinationIndexPatternTitleExists = state.indexPatternTitles.some( - name => newFormState.destinationIndex === name - ); + newFormState.destinationIndexPatternTitleExists = + state.indexPatternsMap[newFormState.destinationIndex] !== undefined; } if (action.payload.jobId !== undefined) { @@ -244,9 +242,8 @@ export function reducer(state: State, action: Action): State { ...state, ...action.payload, }; - newState.form.destinationIndexPatternTitleExists = newState.indexPatternTitles.some( - name => newState.form.destinationIndex === name - ); + newState.form.destinationIndexPatternTitleExists = + newState.indexPatternsMap[newState.form.destinationIndex] !== undefined; return newState; } diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index cddc3577413cf..bce0a800098fd 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -16,6 +16,11 @@ export type EsIndexName = string; export type DependentVariable = string; export type IndexPatternTitle = string; export type AnalyticsJobType = JOB_TYPES | undefined; +type IndexPatternId = string; +export type SourceIndexMap = Record< + IndexPatternTitle, + { label: IndexPatternTitle; value: IndexPatternId } +>; export interface FormMessage { error?: string; @@ -50,13 +55,13 @@ export interface State { sourceIndex: EsIndexName; sourceIndexNameEmpty: boolean; sourceIndexNameValid: boolean; + sourceIndexContainsNumericalFields: boolean; + sourceIndexFieldsCheckFailed: boolean; trainingPercent: number; }; disabled: boolean; indexNames: EsIndexName[]; - indexPatternsMap: any; // TODO: update type - indexPatternTitles: IndexPatternTitle[]; - indexPatternsWithNumericFields: IndexPatternTitle[]; + indexPatternsMap: SourceIndexMap; isAdvancedEditorEnabled: boolean; isJobCreated: boolean; isJobStarted: boolean; @@ -91,6 +96,8 @@ export const getInitialState = (): State => ({ sourceIndex: '', sourceIndexNameEmpty: true, sourceIndexNameValid: false, + sourceIndexContainsNumericalFields: true, + sourceIndexFieldsCheckFailed: false, trainingPercent: 80, }, jobConfig: {}, @@ -99,8 +106,6 @@ export const getInitialState = (): State => ({ !checkPermission('canStartStopDataFrameAnalytics'), indexNames: [], indexPatternsMap: {}, - indexPatternTitles: [], - indexPatternsWithNumericFields: [], isAdvancedEditorEnabled: false, isJobCreated: false, isJobStarted: false, diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts index 18db5bf2205c1..34451e2d22dda 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/use_create_analytics_form.ts @@ -7,7 +7,9 @@ import { useReducer } from 'react'; import { i18n } from '@kbn/i18n'; +import { idx } from '@kbn/elastic-idx'; +import { SimpleSavedObject } from 'src/core/public'; import { ml } from '../../../../../services/ml_api_service'; import { useKibanaContext } from '../../../../../contexts/kibana'; @@ -24,8 +26,8 @@ import { getJobConfigFromFormState, EsIndexName, FormMessage, - IndexPatternTitle, State, + SourceIndexMap, } from './state'; export interface CreateAnalyticsFormProps { @@ -33,9 +35,6 @@ export interface CreateAnalyticsFormProps { state: State; } -// List of system fields we want to ignore for the numeric field check. -const OMIT_FIELDS: string[] = ['_source', '_type', '_index', '_id', '_version', '_score']; - export function getErrorMessage(error: any) { if (typeof error === 'object' && typeof error.message === 'string') { return error.message; @@ -66,11 +65,8 @@ export const useCreateAnalyticsForm = () => { const setAdvancedEditorRawString = (advancedEditorRawString: string) => dispatch({ type: ACTION.SET_ADVANCED_EDITOR_RAW_STRING, advancedEditorRawString }); - const setIndexPatternTitles = (payload: { - indexPatternTitles: IndexPatternTitle[]; - indexPatternsWithNumericFields: IndexPatternTitle[]; - indexPatternsMap: any; // TODO: update this type - }) => dispatch({ type: ACTION.SET_INDEX_PATTERN_TITLES, payload }); + const setIndexPatternTitles = (payload: { indexPatternsMap: SourceIndexMap }) => + dispatch({ type: ACTION.SET_INDEX_PATTERN_TITLES, payload }); const setIsJobCreated = (isJobCreated: boolean) => dispatch({ type: ACTION.SET_IS_JOB_CREATED, isJobCreated }); @@ -230,31 +226,16 @@ export const useCreateAnalyticsForm = () => { try { // Set the index pattern titles which the user can choose as the source. - const indexPatternTitles = await kibanaContext.indexPatterns.getTitles(true); - // Find out which index patterns contain numeric fields. - // This will be used to provide a hint in the form that an analytics jobs is not - // able to identify outliers if there are no numeric fields present. - const ids = await kibanaContext.indexPatterns.getIds(true); - const indexPatternsWithNumericFields: IndexPatternTitle[] = []; - const indexPatternsMap = {}; // TODO: add type, add to state to keep track of - ids - .filter(f => !!f) - .forEach(async id => { - const indexPattern = await kibanaContext.indexPatterns.get(id!); - if ( - indexPattern.fields - .filter(f => !OMIT_FIELDS.includes(f.name)) - .map(f => f.type) - .includes('number') - ) { - indexPatternsWithNumericFields.push(indexPattern.title); - // @ts-ignore TODO: fix this type - indexPatternsMap[indexPattern.title] = id; - } - }); + const indexPatternsMap: SourceIndexMap = {}; + const savedObjects = (await kibanaContext.indexPatterns.getCache()) || []; + savedObjects.forEach((obj: SimpleSavedObject>) => { + const title = idx(obj, _ => _.attributes.title); + if (title !== undefined) { + const id = idx(obj, _ => _.id) || ''; + indexPatternsMap[title] = { label: title, value: id }; + } + }); setIndexPatternTitles({ - indexPatternTitles, - indexPatternsWithNumericFields, indexPatternsMap, }); } catch (e) { diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/route.ts b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/route.ts index f5ad63e422911..d3e9277b646c3 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/route.ts +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/route.ts @@ -12,7 +12,6 @@ import { checkGetJobsPrivilege } from '../../../privilege/check_privilege'; import { loadCurrentIndexPattern, loadCurrentSavedSearch, - loadIndexPatterns, // @ts-ignore } from '../../../util/index_utils'; import { getDataFrameAnalyticsBreadcrumbs } from '../../breadcrumbs'; @@ -26,7 +25,6 @@ uiRoutes.when('/data_frame_analytics/?', { CheckLicense: checkFullLicense, privileges: checkGetJobsPrivilege, indexPattern: loadCurrentIndexPattern, - indexPatterns: loadIndexPatterns, savedSearch: loadCurrentSavedSearch, }, }); From e3e742f3faf65cd0e3781db3a4834b16c010673c Mon Sep 17 00:00:00 2001 From: Chris Davies Date: Wed, 23 Oct 2019 15:17:33 -0400 Subject: [PATCH 092/191] [Lens] Replace '' with '(empty)' in Lens visualizations (#49071) --- .../rename_columns.test.ts | 19 +++++++++++++++++++ .../indexpattern_plugin/rename_columns.ts | 14 ++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/rename_columns.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/rename_columns.test.ts index 74de89d584d2b..61823fd09c967 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/rename_columns.test.ts +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/rename_columns.test.ts @@ -61,6 +61,25 @@ describe('rename_columns', () => { `); }); + it('should replace "" with a visible value', () => { + const input: KibanaDatatable = { + type: 'kibana_datatable', + columns: [{ id: 'a', name: 'A' }], + rows: [{ a: '' }], + }; + + const idMap = { + a: { + id: 'a', + label: 'Austrailia', + }, + }; + + expect(renameColumns.fn(input, { idMap: JSON.stringify(idMap) }, {}).rows[0].a).toEqual( + '(empty)' + ); + }); + it('should keep columns which are not mapped', () => { const input: KibanaDatatable = { type: 'kibana_datatable', diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/rename_columns.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/rename_columns.ts index 87e51cb62ba1d..66073c6a5e9d4 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/rename_columns.ts +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/rename_columns.ts @@ -54,9 +54,9 @@ export const renameColumns: ExpressionFunction< Object.entries(row).forEach(([id, value]) => { if (id in idMap) { - mappedRow[idMap[id].id] = value; + mappedRow[idMap[id].id] = sanitizeValue(value); } else { - mappedRow[id] = value; + mappedRow[id] = sanitizeValue(value); } }); @@ -91,3 +91,13 @@ function getColumnName(originalColumn: OriginalColumn, newColumn: KibanaDatatabl return originalColumn.label; } + +function sanitizeValue(value: unknown) { + if (value === '') { + return i18n.translate('xpack.lens.indexpattern.emptyTextColumnValue', { + defaultMessage: '(empty)', + }); + } + + return value; +} From 500cf271b09500fbe95ba2d3a739c93c296aed1e Mon Sep 17 00:00:00 2001 From: Chris Davies Date: Wed, 23 Oct 2019 15:23:50 -0400 Subject: [PATCH 093/191] Add Lens to dashboard privileges (#49066) --- x-pack/plugins/features/server/oss_features.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/features/server/oss_features.ts b/x-pack/plugins/features/server/oss_features.ts index ff19df62bc3db..d70f72a7ff085 100644 --- a/x-pack/plugins/features/server/oss_features.ts +++ b/x-pack/plugins/features/server/oss_features.ts @@ -84,6 +84,7 @@ export const buildOSSFeatures = ({ savedObjectTypes, includeTimelion }: BuildOSS 'visualization', 'timelion-sheet', 'canvas-workpad', + 'lens', 'map', ], }, From d68eba6d96c704e0821aefcbb1404b002841fb5f Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Wed, 23 Oct 2019 16:13:15 -0400 Subject: [PATCH 094/191] Ensure es/kibana cleanup always happens when using scripts/functional_tests (#48986) --- .../kbn-test/src/functional_tests/tasks.js | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/kbn-test/src/functional_tests/tasks.js b/packages/kbn-test/src/functional_tests/tasks.js index 6ebc49679fbf3..d50f6a15c2e0b 100644 --- a/packages/kbn-test/src/functional_tests/tasks.js +++ b/packages/kbn-test/src/functional_tests/tasks.js @@ -82,12 +82,20 @@ export async function runTests(options) { await withProcRunner(log, async procs => { const config = await readConfigFile(log, configPath); - const es = await runElasticsearch({ config, options: opts }); - await runKibanaServer({ procs, config, options: opts }); - await runFtr({ configPath, options: opts }); - - await procs.stop('kibana'); - await es.cleanup(); + let es; + try { + es = await runElasticsearch({ config, options: opts }); + await runKibanaServer({ procs, config, options: opts }); + await runFtr({ configPath, options: opts }); + } finally { + try { + await procs.stop('kibana'); + } finally { + if (es) { + await es.cleanup(); + } + } + } }); } } From a8e218584fb5fb33eda23501571941160cb51930 Mon Sep 17 00:00:00 2001 From: Chris Davies Date: Wed, 23 Oct 2019 16:28:18 -0400 Subject: [PATCH 095/191] Fix XY chart icon and error on layer flyout (#48577) --- .../public/xy_visualization_plugin/xy_config_panel.tsx | 3 ++- .../xy_visualization_plugin/xy_visualization.test.ts | 9 +++++++++ .../public/xy_visualization_plugin/xy_visualization.tsx | 6 +++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx index 322e1f1ea4a0e..f285cb90f225a 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx @@ -102,7 +102,8 @@ function LayerSettings({ options={visualizationTypes .filter(t => isHorizontalSeries(t.id as SeriesType) === horizontalOnly) .map(t => ({ - ...t, + id: t.id, + label: t.label, iconType: t.icon || 'empty', }))} idSelected={layer.seriesType} diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts index 5cd0791ae3da9..4b03c6c346ce5 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts @@ -50,6 +50,15 @@ describe('xy_visualization', () => { expect(desc.label).toEqual('Mixed XY Chart'); }); + it('should show the preferredSeriesType if there are no layers', () => { + const desc = xyVisualization.getDescription(mixedState()); + + // 'test-file-stub' is a hack, but it at least means we aren't using + // a standard icon here. + expect(desc.icon).toEqual('test-file-stub'); + expect(desc.label).toEqual('Bar Chart'); + }); + it('should show mixed horizontal bar chart when multiple horizontal bar types', () => { const desc = xyVisualization.getDescription( mixedState('bar_horizontal', 'bar_horizontal_stacked') diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx index 0c9cb3b6216bb..b56e0d9deb55e 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx @@ -34,7 +34,11 @@ function getDescription(state?: State) { } if (!state.layers.length) { - return visualizationTypes.find(v => v.id === state.preferredSeriesType)!; + const visualizationType = visualizationTypes.find(v => v.id === state.preferredSeriesType)!; + return { + icon: visualizationType.largeIcon || visualizationType.icon, + label: visualizationType.label, + }; } const visualizationType = visualizationTypes.find(t => t.id === state.layers[0].seriesType)!; From a8c645926c59a49d92175c2712404a76aaa3c355 Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Wed, 23 Oct 2019 13:41:46 -0700 Subject: [PATCH 096/191] Update set-value to 2.0.1 (#49005) * Updating set-value to 2.0.1 * update kbn/pm dist --- packages/kbn-pm/dist/index.js | 748 ++++++++++++++++------------------ yarn.lock | 26 +- 2 files changed, 349 insertions(+), 425 deletions(-) diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index f52c194cfee6a..3dd27e7ef3800 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -38648,7 +38648,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(405); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(613); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(612); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -38828,8 +38828,8 @@ const EventEmitter = __webpack_require__(46); const path = __webpack_require__(16); const arrify = __webpack_require__(407); const globby = __webpack_require__(408); -const cpFile = __webpack_require__(603); -const CpyError = __webpack_require__(611); +const cpFile = __webpack_require__(602); +const CpyError = __webpack_require__(610); const preprocessSrcPath = (srcPath, options) => options.cwd ? path.resolve(options.cwd, srcPath) : srcPath; @@ -38958,8 +38958,8 @@ const fs = __webpack_require__(23); const arrayUnion = __webpack_require__(170); const glob = __webpack_require__(37); const fastGlob = __webpack_require__(409); -const dirGlob = __webpack_require__(596); -const gitignore = __webpack_require__(599); +const dirGlob = __webpack_require__(595); +const gitignore = __webpack_require__(598); const DEFAULT_FILTER = () => false; @@ -39128,11 +39128,11 @@ module.exports.generateTasks = pkg.generateTasks; Object.defineProperty(exports, "__esModule", { value: true }); var optionsManager = __webpack_require__(411); var taskManager = __webpack_require__(412); -var reader_async_1 = __webpack_require__(566); -var reader_stream_1 = __webpack_require__(590); -var reader_sync_1 = __webpack_require__(591); -var arrayUtils = __webpack_require__(593); -var streamUtils = __webpack_require__(594); +var reader_async_1 = __webpack_require__(565); +var reader_stream_1 = __webpack_require__(589); +var reader_sync_1 = __webpack_require__(590); +var arrayUtils = __webpack_require__(592); +var streamUtils = __webpack_require__(593); /** * Synchronous API. */ @@ -39790,17 +39790,17 @@ module.exports = function isGlob(str, options) { var util = __webpack_require__(29); var braces = __webpack_require__(420); -var toRegex = __webpack_require__(524); -var extend = __webpack_require__(532); +var toRegex = __webpack_require__(523); +var extend = __webpack_require__(531); /** * Local dependencies */ -var compilers = __webpack_require__(535); -var parsers = __webpack_require__(562); -var cache = __webpack_require__(563); -var utils = __webpack_require__(564); +var compilers = __webpack_require__(534); +var parsers = __webpack_require__(561); +var cache = __webpack_require__(562); +var utils = __webpack_require__(563); var MAX_LENGTH = 1024 * 64; /** @@ -46382,9 +46382,9 @@ module.exports = Braces; var Base = __webpack_require__(461); var define = __webpack_require__(422); -var Compiler = __webpack_require__(491); -var Parser = __webpack_require__(521); -var utils = __webpack_require__(501); +var Compiler = __webpack_require__(490); +var Parser = __webpack_require__(520); +var utils = __webpack_require__(500); var regexCache = {}; var cache = {}; @@ -46566,9 +46566,9 @@ var define = __webpack_require__(462); var CacheBase = __webpack_require__(463); var Emitter = __webpack_require__(464); var isObject = __webpack_require__(440); -var merge = __webpack_require__(482); -var pascal = __webpack_require__(485); -var cu = __webpack_require__(486); +var merge = __webpack_require__(481); +var pascal = __webpack_require__(484); +var cu = __webpack_require__(485); /** * Optionally define a custom `cache` namespace to use. @@ -47049,7 +47049,7 @@ var union = __webpack_require__(469); var del = __webpack_require__(473); var get = __webpack_require__(471); var has = __webpack_require__(478); -var set = __webpack_require__(481); +var set = __webpack_require__(472); /** * Create a `Cache` constructor that when instantiated will @@ -47775,60 +47775,52 @@ function toString(val) { -var toPath = __webpack_require__(468); +var split = __webpack_require__(436); var extend = __webpack_require__(430); var isPlainObject = __webpack_require__(439); var isObject = __webpack_require__(431); -module.exports = function(obj, path, val) { +module.exports = function(obj, prop, val) { if (!isObject(obj)) { return obj; } - if (Array.isArray(path)) { - path = toPath(path); + if (Array.isArray(prop)) { + prop = [].concat.apply([], prop).join('.'); } - if (typeof path !== 'string') { + if (typeof prop !== 'string') { return obj; } - var segs = path.split('.'); - var len = segs.length, i = -1; - var res = obj; - var last; - - while (++i < len) { - var key = segs[i]; - - while (key[key.length - 1] === '\\') { - key = key.slice(0, -1) + '.' + segs[++i]; - } - - if (i === len - 1) { - last = key; - break; - } + var keys = split(prop, {sep: '.', brackets: true}).filter(isValidKey); + var len = keys.length; + var idx = -1; + var current = obj; - if (!isObject(obj[key])) { - obj[key] = {}; + while (++idx < len) { + var key = keys[idx]; + if (idx !== len - 1) { + if (!isObject(current[key])) { + current[key] = {}; + } + current = current[key]; + continue; } - obj = obj[key]; - } - if (obj.hasOwnProperty(last) && isObject(obj[last])) { - if (isPlainObject(val)) { - extend(obj[last], val); + if (isPlainObject(current[key]) && isPlainObject(val)) { + current[key] = extend({}, current[key], val); } else { - obj[last] = val; + current[key] = val; } - - } else { - obj[last] = val; } - return res; + + return obj; }; +function isValidKey(key) { + return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'; +} /***/ }), @@ -48191,68 +48183,10 @@ module.exports = function kindOf(val) { /***/ (function(module, exports, __webpack_require__) { "use strict"; -/*! - * set-value - * - * Copyright (c) 2014-2015, 2017, Jon Schlinkert. - * Released under the MIT License. - */ - - - -var split = __webpack_require__(436); -var extend = __webpack_require__(430); -var isPlainObject = __webpack_require__(439); -var isObject = __webpack_require__(431); -module.exports = function(obj, prop, val) { - if (!isObject(obj)) { - return obj; - } - - if (Array.isArray(prop)) { - prop = [].concat.apply([], prop).join('.'); - } - - if (typeof prop !== 'string') { - return obj; - } - - var keys = split(prop, {sep: '.', brackets: true}); - var len = keys.length; - var idx = -1; - var current = obj; - - while (++idx < len) { - var key = keys[idx]; - if (idx !== len - 1) { - if (!isObject(current[key])) { - current[key] = {}; - } - current = current[key]; - continue; - } - - if (isPlainObject(current[key]) && isPlainObject(val)) { - current[key] = extend({}, current[key], val); - } else { - current[key] = val; - } - } - - return obj; -}; - -/***/ }), -/* 482 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isExtendable = __webpack_require__(483); -var forIn = __webpack_require__(484); +var isExtendable = __webpack_require__(482); +var forIn = __webpack_require__(483); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -48316,7 +48250,7 @@ module.exports = mixinDeep; /***/ }), -/* 483 */ +/* 482 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48337,7 +48271,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 484 */ +/* 483 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48360,7 +48294,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 485 */ +/* 484 */ /***/ (function(module, exports) { /*! @@ -48387,14 +48321,14 @@ module.exports = pascalcase; /***/ }), -/* 486 */ +/* 485 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var utils = __webpack_require__(487); +var utils = __webpack_require__(486); /** * Expose class utils @@ -48759,7 +48693,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 487 */ +/* 486 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48776,7 +48710,7 @@ var utils = {}; utils.union = __webpack_require__(470); utils.define = __webpack_require__(422); utils.isObj = __webpack_require__(440); -utils.staticExtend = __webpack_require__(488); +utils.staticExtend = __webpack_require__(487); /** @@ -48787,7 +48721,7 @@ module.exports = utils; /***/ }), -/* 488 */ +/* 487 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48800,7 +48734,7 @@ module.exports = utils; -var copy = __webpack_require__(489); +var copy = __webpack_require__(488); var define = __webpack_require__(422); var util = __webpack_require__(29); @@ -48884,14 +48818,14 @@ module.exports = extend; /***/ }), -/* 489 */ +/* 488 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var typeOf = __webpack_require__(445); -var copyDescriptor = __webpack_require__(490); +var copyDescriptor = __webpack_require__(489); var define = __webpack_require__(422); /** @@ -49065,7 +48999,7 @@ module.exports.has = has; /***/ }), -/* 490 */ +/* 489 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49153,16 +49087,16 @@ function isObject(val) { /***/ }), -/* 491 */ +/* 490 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(492); +var use = __webpack_require__(491); var define = __webpack_require__(422); -var debug = __webpack_require__(494)('snapdragon:compiler'); -var utils = __webpack_require__(501); +var debug = __webpack_require__(493)('snapdragon:compiler'); +var utils = __webpack_require__(500); /** * Create a new `Compiler` with the given `options`. @@ -49316,7 +49250,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(520); + var sourcemaps = __webpack_require__(519); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -49337,7 +49271,7 @@ module.exports = Compiler; /***/ }), -/* 492 */ +/* 491 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49350,7 +49284,7 @@ module.exports = Compiler; -var utils = __webpack_require__(493); +var utils = __webpack_require__(492); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -49465,7 +49399,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 493 */ +/* 492 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49495,7 +49429,7 @@ module.exports = utils; /***/ }), -/* 494 */ +/* 493 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -49504,14 +49438,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(495); + module.exports = __webpack_require__(494); } else { - module.exports = __webpack_require__(498); + module.exports = __webpack_require__(497); } /***/ }), -/* 495 */ +/* 494 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -49520,7 +49454,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(496); +exports = module.exports = __webpack_require__(495); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -49702,7 +49636,7 @@ function localstorage() { /***/ }), -/* 496 */ +/* 495 */ /***/ (function(module, exports, __webpack_require__) { @@ -49718,7 +49652,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(497); +exports.humanize = __webpack_require__(496); /** * The currently active debug mode names, and names to skip. @@ -49910,7 +49844,7 @@ function coerce(val) { /***/ }), -/* 497 */ +/* 496 */ /***/ (function(module, exports) { /** @@ -50068,14 +50002,14 @@ function plural(ms, n, name) { /***/ }), -/* 498 */ +/* 497 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(499); +var tty = __webpack_require__(498); var util = __webpack_require__(29); /** @@ -50084,7 +50018,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(496); +exports = module.exports = __webpack_require__(495); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -50263,7 +50197,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(500); + var net = __webpack_require__(499); stream = new net.Socket({ fd: fd, readable: false, @@ -50322,19 +50256,19 @@ exports.enable(load()); /***/ }), -/* 499 */ +/* 498 */ /***/ (function(module, exports) { module.exports = require("tty"); /***/ }), -/* 500 */ +/* 499 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 501 */ +/* 500 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50345,8 +50279,8 @@ module.exports = require("net"); */ exports.extend = __webpack_require__(430); -exports.SourceMap = __webpack_require__(502); -exports.sourceMapResolve = __webpack_require__(513); +exports.SourceMap = __webpack_require__(501); +exports.sourceMapResolve = __webpack_require__(512); /** * Convert backslash in the given string to forward slashes @@ -50389,7 +50323,7 @@ exports.last = function(arr, n) { /***/ }), -/* 502 */ +/* 501 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -50397,13 +50331,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(503).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(509).SourceMapConsumer; -exports.SourceNode = __webpack_require__(512).SourceNode; +exports.SourceMapGenerator = __webpack_require__(502).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(508).SourceMapConsumer; +exports.SourceNode = __webpack_require__(511).SourceNode; /***/ }), -/* 503 */ +/* 502 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50413,10 +50347,10 @@ exports.SourceNode = __webpack_require__(512).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(504); -var util = __webpack_require__(506); -var ArraySet = __webpack_require__(507).ArraySet; -var MappingList = __webpack_require__(508).MappingList; +var base64VLQ = __webpack_require__(503); +var util = __webpack_require__(505); +var ArraySet = __webpack_require__(506).ArraySet; +var MappingList = __webpack_require__(507).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -50825,7 +50759,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 504 */ +/* 503 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50865,7 +50799,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(505); +var base64 = __webpack_require__(504); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -50971,7 +50905,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 505 */ +/* 504 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51044,7 +50978,7 @@ exports.decode = function (charCode) { /***/ }), -/* 506 */ +/* 505 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51467,7 +51401,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 507 */ +/* 506 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51477,7 +51411,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(506); +var util = __webpack_require__(505); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -51594,7 +51528,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 508 */ +/* 507 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51604,7 +51538,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(506); +var util = __webpack_require__(505); /** * Determine whether mappingB is after mappingA with respect to generated @@ -51679,7 +51613,7 @@ exports.MappingList = MappingList; /***/ }), -/* 509 */ +/* 508 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51689,11 +51623,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(506); -var binarySearch = __webpack_require__(510); -var ArraySet = __webpack_require__(507).ArraySet; -var base64VLQ = __webpack_require__(504); -var quickSort = __webpack_require__(511).quickSort; +var util = __webpack_require__(505); +var binarySearch = __webpack_require__(509); +var ArraySet = __webpack_require__(506).ArraySet; +var base64VLQ = __webpack_require__(503); +var quickSort = __webpack_require__(510).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -52767,7 +52701,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 510 */ +/* 509 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -52884,7 +52818,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 511 */ +/* 510 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -53004,7 +52938,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 512 */ +/* 511 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -53014,8 +52948,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(503).SourceMapGenerator; -var util = __webpack_require__(506); +var SourceMapGenerator = __webpack_require__(502).SourceMapGenerator; +var util = __webpack_require__(505); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -53423,17 +53357,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 513 */ +/* 512 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(514) -var resolveUrl = __webpack_require__(515) -var decodeUriComponent = __webpack_require__(516) -var urix = __webpack_require__(518) -var atob = __webpack_require__(519) +var sourceMappingURL = __webpack_require__(513) +var resolveUrl = __webpack_require__(514) +var decodeUriComponent = __webpack_require__(515) +var urix = __webpack_require__(517) +var atob = __webpack_require__(518) @@ -53731,7 +53665,7 @@ module.exports = { /***/ }), -/* 514 */ +/* 513 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -53794,7 +53728,7 @@ void (function(root, factory) { /***/ }), -/* 515 */ +/* 514 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -53812,13 +53746,13 @@ module.exports = resolveUrl /***/ }), -/* 516 */ +/* 515 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(517) +var decodeUriComponent = __webpack_require__(516) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -53829,7 +53763,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 517 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53930,7 +53864,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 518 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -53953,7 +53887,7 @@ module.exports = urix /***/ }), -/* 519 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53967,7 +53901,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 520 */ +/* 519 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53976,7 +53910,7 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); var define = __webpack_require__(422); -var utils = __webpack_require__(501); +var utils = __webpack_require__(500); /** * Expose `mixin()`. @@ -54119,19 +54053,19 @@ exports.comment = function(node) { /***/ }), -/* 521 */ +/* 520 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(492); +var use = __webpack_require__(491); var util = __webpack_require__(29); -var Cache = __webpack_require__(522); +var Cache = __webpack_require__(521); var define = __webpack_require__(422); -var debug = __webpack_require__(494)('snapdragon:parser'); -var Position = __webpack_require__(523); -var utils = __webpack_require__(501); +var debug = __webpack_require__(493)('snapdragon:parser'); +var Position = __webpack_require__(522); +var utils = __webpack_require__(500); /** * Create a new `Parser` with the given `input` and `options`. @@ -54659,7 +54593,7 @@ module.exports = Parser; /***/ }), -/* 522 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54766,7 +54700,7 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 523 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54787,16 +54721,16 @@ module.exports = function Position(start, parser) { /***/ }), -/* 524 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(525); -var define = __webpack_require__(531); -var extend = __webpack_require__(532); -var not = __webpack_require__(534); +var safe = __webpack_require__(524); +var define = __webpack_require__(530); +var extend = __webpack_require__(531); +var not = __webpack_require__(533); var MAX_LENGTH = 1024 * 64; /** @@ -54949,10 +54883,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 525 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(526); +var parse = __webpack_require__(525); var types = parse.types; module.exports = function (re, opts) { @@ -54998,13 +54932,13 @@ function isRegExp (x) { /***/ }), -/* 526 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(527); -var types = __webpack_require__(528); -var sets = __webpack_require__(529); -var positions = __webpack_require__(530); +var util = __webpack_require__(526); +var types = __webpack_require__(527); +var sets = __webpack_require__(528); +var positions = __webpack_require__(529); module.exports = function(regexpStr) { @@ -55286,11 +55220,11 @@ module.exports.types = types; /***/ }), -/* 527 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(528); -var sets = __webpack_require__(529); +var types = __webpack_require__(527); +var sets = __webpack_require__(528); // All of these are private and only used by randexp. @@ -55403,7 +55337,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 528 */ +/* 527 */ /***/ (function(module, exports) { module.exports = { @@ -55419,10 +55353,10 @@ module.exports = { /***/ }), -/* 529 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(528); +var types = __webpack_require__(527); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -55507,10 +55441,10 @@ exports.anyChar = function() { /***/ }), -/* 530 */ +/* 529 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(528); +var types = __webpack_require__(527); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -55530,7 +55464,7 @@ exports.end = function() { /***/ }), -/* 531 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55575,13 +55509,13 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 532 */ +/* 531 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(533); +var isExtendable = __webpack_require__(532); var assignSymbols = __webpack_require__(441); module.exports = Object.assign || function(obj/*, objects*/) { @@ -55642,7 +55576,7 @@ function isEnum(obj, key) { /***/ }), -/* 533 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55663,14 +55597,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 534 */ +/* 533 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(532); -var safe = __webpack_require__(525); +var extend = __webpack_require__(531); +var safe = __webpack_require__(524); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -55742,14 +55676,14 @@ module.exports = toRegex; /***/ }), -/* 535 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(536); -var extglob = __webpack_require__(551); +var nanomatch = __webpack_require__(535); +var extglob = __webpack_require__(550); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -55826,7 +55760,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 536 */ +/* 535 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55838,16 +55772,16 @@ function escapeExtglobs(compiler) { var util = __webpack_require__(29); var toRegex = __webpack_require__(421); -var extend = __webpack_require__(537); +var extend = __webpack_require__(536); /** * Local dependencies */ -var compilers = __webpack_require__(539); -var parsers = __webpack_require__(540); -var cache = __webpack_require__(543); -var utils = __webpack_require__(545); +var compilers = __webpack_require__(538); +var parsers = __webpack_require__(539); +var cache = __webpack_require__(542); +var utils = __webpack_require__(544); var MAX_LENGTH = 1024 * 64; /** @@ -56671,13 +56605,13 @@ module.exports = nanomatch; /***/ }), -/* 537 */ +/* 536 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(538); +var isExtendable = __webpack_require__(537); var assignSymbols = __webpack_require__(441); module.exports = Object.assign || function(obj/*, objects*/) { @@ -56738,7 +56672,7 @@ function isEnum(obj, key) { /***/ }), -/* 538 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56759,7 +56693,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 539 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57105,7 +57039,7 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 540 */ +/* 539 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57113,7 +57047,7 @@ module.exports = function(nanomatch, options) { var regexNot = __webpack_require__(432); var toRegex = __webpack_require__(421); -var isOdd = __webpack_require__(541); +var isOdd = __webpack_require__(540); /** * Characters to use in negation regex (we want to "not" match @@ -57499,7 +57433,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 541 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57512,7 +57446,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(542); +var isNumber = __webpack_require__(541); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -57526,7 +57460,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 542 */ +/* 541 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57554,14 +57488,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 543 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(544))(); +module.exports = new (__webpack_require__(543))(); /***/ }), -/* 544 */ +/* 543 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57574,7 +57508,7 @@ module.exports = new (__webpack_require__(544))(); -var MapCache = __webpack_require__(522); +var MapCache = __webpack_require__(521); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -57696,7 +57630,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 545 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57709,13 +57643,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var isWindows = __webpack_require__(546)(); +var isWindows = __webpack_require__(545)(); var Snapdragon = __webpack_require__(460); -utils.define = __webpack_require__(547); -utils.diff = __webpack_require__(548); -utils.extend = __webpack_require__(537); -utils.pick = __webpack_require__(549); -utils.typeOf = __webpack_require__(550); +utils.define = __webpack_require__(546); +utils.diff = __webpack_require__(547); +utils.extend = __webpack_require__(536); +utils.pick = __webpack_require__(548); +utils.typeOf = __webpack_require__(549); utils.unique = __webpack_require__(433); /** @@ -58082,7 +58016,7 @@ utils.unixify = function(options) { /***/ }), -/* 546 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -58110,7 +58044,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 547 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58155,7 +58089,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 548 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58209,7 +58143,7 @@ function diffArray(one, two) { /***/ }), -/* 549 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58251,7 +58185,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 550 */ +/* 549 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -58386,7 +58320,7 @@ function isBuffer(val) { /***/ }), -/* 551 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58404,10 +58338,10 @@ var toRegex = __webpack_require__(421); * Local dependencies */ -var compilers = __webpack_require__(552); -var parsers = __webpack_require__(558); -var Extglob = __webpack_require__(561); -var utils = __webpack_require__(560); +var compilers = __webpack_require__(551); +var parsers = __webpack_require__(557); +var Extglob = __webpack_require__(560); +var utils = __webpack_require__(559); var MAX_LENGTH = 1024 * 64; /** @@ -58724,13 +58658,13 @@ module.exports = extglob; /***/ }), -/* 552 */ +/* 551 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(553); +var brackets = __webpack_require__(552); /** * Extglob compilers @@ -58900,7 +58834,7 @@ module.exports = function(extglob) { /***/ }), -/* 553 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58910,14 +58844,14 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(554); -var parsers = __webpack_require__(556); +var compilers = __webpack_require__(553); +var parsers = __webpack_require__(555); /** * Module dependencies */ -var debug = __webpack_require__(494)('expand-brackets'); +var debug = __webpack_require__(493)('expand-brackets'); var extend = __webpack_require__(430); var Snapdragon = __webpack_require__(460); var toRegex = __webpack_require__(421); @@ -59118,13 +59052,13 @@ module.exports = brackets; /***/ }), -/* 554 */ +/* 553 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(555); +var posix = __webpack_require__(554); module.exports = function(brackets) { brackets.compiler @@ -59212,7 +59146,7 @@ module.exports = function(brackets) { /***/ }), -/* 555 */ +/* 554 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59241,13 +59175,13 @@ module.exports = { /***/ }), -/* 556 */ +/* 555 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(557); +var utils = __webpack_require__(556); var define = __webpack_require__(422); /** @@ -59467,7 +59401,7 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 557 */ +/* 556 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59508,15 +59442,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 558 */ +/* 557 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(553); -var define = __webpack_require__(559); -var utils = __webpack_require__(560); +var brackets = __webpack_require__(552); +var define = __webpack_require__(558); +var utils = __webpack_require__(559); /** * Characters to use in text regex (we want to "not" match @@ -59671,7 +59605,7 @@ module.exports = parsers; /***/ }), -/* 559 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59709,14 +59643,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 560 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var regex = __webpack_require__(432); -var Cache = __webpack_require__(544); +var Cache = __webpack_require__(543); /** * Utils @@ -59785,7 +59719,7 @@ utils.createRegex = function(str) { /***/ }), -/* 561 */ +/* 560 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59796,15 +59730,15 @@ utils.createRegex = function(str) { */ var Snapdragon = __webpack_require__(460); -var define = __webpack_require__(559); +var define = __webpack_require__(558); var extend = __webpack_require__(430); /** * Local dependencies */ -var compilers = __webpack_require__(552); -var parsers = __webpack_require__(558); +var compilers = __webpack_require__(551); +var parsers = __webpack_require__(557); /** * Customize Snapdragon parser and renderer @@ -59870,16 +59804,16 @@ module.exports = Extglob; /***/ }), -/* 562 */ +/* 561 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(551); -var nanomatch = __webpack_require__(536); +var extglob = __webpack_require__(550); +var nanomatch = __webpack_require__(535); var regexNot = __webpack_require__(432); -var toRegex = __webpack_require__(524); +var toRegex = __webpack_require__(523); var not; /** @@ -59960,14 +59894,14 @@ function textRegex(pattern) { /***/ }), -/* 563 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(544))(); +module.exports = new (__webpack_require__(543))(); /***/ }), -/* 564 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59981,11 +59915,11 @@ var path = __webpack_require__(16); */ var Snapdragon = __webpack_require__(460); -utils.define = __webpack_require__(531); -utils.diff = __webpack_require__(548); -utils.extend = __webpack_require__(532); -utils.pick = __webpack_require__(549); -utils.typeOf = __webpack_require__(565); +utils.define = __webpack_require__(530); +utils.diff = __webpack_require__(547); +utils.extend = __webpack_require__(531); +utils.pick = __webpack_require__(548); +utils.typeOf = __webpack_require__(564); utils.unique = __webpack_require__(433); /** @@ -60283,7 +60217,7 @@ utils.unixify = function(options) { /***/ }), -/* 565 */ +/* 564 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -60418,7 +60352,7 @@ function isBuffer(val) { /***/ }), -/* 566 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60437,9 +60371,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(567); -var reader_1 = __webpack_require__(580); -var fs_stream_1 = __webpack_require__(584); +var readdir = __webpack_require__(566); +var reader_1 = __webpack_require__(579); +var fs_stream_1 = __webpack_require__(583); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -60500,15 +60434,15 @@ exports.default = ReaderAsync; /***/ }), -/* 567 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(568); -const readdirAsync = __webpack_require__(576); -const readdirStream = __webpack_require__(579); +const readdirSync = __webpack_require__(567); +const readdirAsync = __webpack_require__(575); +const readdirStream = __webpack_require__(578); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -60592,7 +60526,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 568 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60600,11 +60534,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(569); +const DirectoryReader = __webpack_require__(568); let syncFacade = { - fs: __webpack_require__(574), - forEach: __webpack_require__(575), + fs: __webpack_require__(573), + forEach: __webpack_require__(574), sync: true }; @@ -60633,7 +60567,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 569 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60642,9 +60576,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(28).Readable; const EventEmitter = __webpack_require__(46).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(570); -const stat = __webpack_require__(572); -const call = __webpack_require__(573); +const normalizeOptions = __webpack_require__(569); +const stat = __webpack_require__(571); +const call = __webpack_require__(572); /** * Asynchronously reads the contents of a directory and streams the results @@ -61020,14 +60954,14 @@ module.exports = DirectoryReader; /***/ }), -/* 570 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(571); +const globToRegExp = __webpack_require__(570); module.exports = normalizeOptions; @@ -61204,7 +61138,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 571 */ +/* 570 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -61341,13 +61275,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 572 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(573); +const call = __webpack_require__(572); module.exports = stat; @@ -61422,7 +61356,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 573 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61483,14 +61417,14 @@ function callOnce (fn) { /***/ }), -/* 574 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(573); +const call = __webpack_require__(572); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -61554,7 +61488,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 575 */ +/* 574 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61583,7 +61517,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 576 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61591,12 +61525,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(577); -const DirectoryReader = __webpack_require__(569); +const maybe = __webpack_require__(576); +const DirectoryReader = __webpack_require__(568); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(578), + forEach: __webpack_require__(577), async: true }; @@ -61638,7 +61572,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 577 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61665,7 +61599,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 578 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61701,7 +61635,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 579 */ +/* 578 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61709,11 +61643,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(569); +const DirectoryReader = __webpack_require__(568); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(578), + forEach: __webpack_require__(577), async: true }; @@ -61733,16 +61667,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 580 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(581); -var entry_1 = __webpack_require__(583); -var pathUtil = __webpack_require__(582); +var deep_1 = __webpack_require__(580); +var entry_1 = __webpack_require__(582); +var pathUtil = __webpack_require__(581); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -61808,13 +61742,13 @@ exports.default = Reader; /***/ }), -/* 581 */ +/* 580 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(582); +var pathUtils = __webpack_require__(581); var patternUtils = __webpack_require__(413); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { @@ -61898,7 +61832,7 @@ exports.default = DeepFilter; /***/ }), -/* 582 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61929,13 +61863,13 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 583 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(582); +var pathUtils = __webpack_require__(581); var patternUtils = __webpack_require__(413); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { @@ -62021,7 +61955,7 @@ exports.default = EntryFilter; /***/ }), -/* 584 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62041,8 +61975,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(28); -var fsStat = __webpack_require__(585); -var fs_1 = __webpack_require__(589); +var fsStat = __webpack_require__(584); +var fs_1 = __webpack_require__(588); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -62092,14 +62026,14 @@ exports.default = FileSystemStream; /***/ }), -/* 585 */ +/* 584 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(586); -const statProvider = __webpack_require__(588); +const optionsManager = __webpack_require__(585); +const statProvider = __webpack_require__(587); /** * Asynchronous API. */ @@ -62130,13 +62064,13 @@ exports.statSync = statSync; /***/ }), -/* 586 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(587); +const fsAdapter = __webpack_require__(586); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -62149,7 +62083,7 @@ exports.prepare = prepare; /***/ }), -/* 587 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62172,7 +62106,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 588 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62224,7 +62158,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 589 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62255,7 +62189,7 @@ exports.default = FileSystem; /***/ }), -/* 590 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62275,9 +62209,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(28); -var readdir = __webpack_require__(567); -var reader_1 = __webpack_require__(580); -var fs_stream_1 = __webpack_require__(584); +var readdir = __webpack_require__(566); +var reader_1 = __webpack_require__(579); +var fs_stream_1 = __webpack_require__(583); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -62345,7 +62279,7 @@ exports.default = ReaderStream; /***/ }), -/* 591 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62364,9 +62298,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(567); -var reader_1 = __webpack_require__(580); -var fs_sync_1 = __webpack_require__(592); +var readdir = __webpack_require__(566); +var reader_1 = __webpack_require__(579); +var fs_sync_1 = __webpack_require__(591); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -62426,7 +62360,7 @@ exports.default = ReaderSync; /***/ }), -/* 592 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62445,8 +62379,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(585); -var fs_1 = __webpack_require__(589); +var fsStat = __webpack_require__(584); +var fs_1 = __webpack_require__(588); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -62492,7 +62426,7 @@ exports.default = FileSystemSync; /***/ }), -/* 593 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62508,13 +62442,13 @@ exports.flatten = flatten; /***/ }), -/* 594 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(595); +var merge2 = __webpack_require__(594); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -62529,7 +62463,7 @@ exports.merge = merge; /***/ }), -/* 595 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62643,13 +62577,13 @@ function pauseStreams (streams, options) { /***/ }), -/* 596 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(597); +const pathType = __webpack_require__(596); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -62715,13 +62649,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 597 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(598); +const pify = __webpack_require__(597); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -62764,7 +62698,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 598 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62855,7 +62789,7 @@ module.exports = (obj, opts) => { /***/ }), -/* 599 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62863,9 +62797,9 @@ module.exports = (obj, opts) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const fastGlob = __webpack_require__(409); -const gitIgnore = __webpack_require__(600); -const pify = __webpack_require__(601); -const slash = __webpack_require__(602); +const gitIgnore = __webpack_require__(599); +const pify = __webpack_require__(600); +const slash = __webpack_require__(601); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -62963,7 +62897,7 @@ module.exports.sync = options => { /***/ }), -/* 600 */ +/* 599 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -63432,7 +63366,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 601 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63507,7 +63441,7 @@ module.exports = (input, options) => { /***/ }), -/* 602 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63525,17 +63459,17 @@ module.exports = input => { /***/ }), -/* 603 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const {Buffer} = __webpack_require__(604); -const CpFileError = __webpack_require__(606); -const fs = __webpack_require__(608); -const ProgressEmitter = __webpack_require__(610); +const {Buffer} = __webpack_require__(603); +const CpFileError = __webpack_require__(605); +const fs = __webpack_require__(607); +const ProgressEmitter = __webpack_require__(609); const cpFile = (source, destination, options) => { if (!source || !destination) { @@ -63689,11 +63623,11 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 604 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { /* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(605) +var buffer = __webpack_require__(604) var Buffer = buffer.Buffer // alternative to using Object.keys for old browsers @@ -63757,18 +63691,18 @@ SafeBuffer.allocUnsafeSlow = function (size) { /***/ }), -/* 605 */ +/* 604 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 606 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(607); +const NestedError = __webpack_require__(606); class CpFileError extends NestedError { constructor(message, nested) { @@ -63782,7 +63716,7 @@ module.exports = CpFileError; /***/ }), -/* 607 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(44); @@ -63836,15 +63770,15 @@ module.exports = NestedError; /***/ }), -/* 608 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(22); const makeDir = __webpack_require__(115); -const pify = __webpack_require__(609); -const CpFileError = __webpack_require__(606); +const pify = __webpack_require__(608); +const CpFileError = __webpack_require__(605); const fsP = pify(fs); @@ -63989,7 +63923,7 @@ if (fs.copyFileSync) { /***/ }), -/* 609 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64064,7 +63998,7 @@ module.exports = (input, options) => { /***/ }), -/* 610 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64105,12 +64039,12 @@ module.exports = ProgressEmitter; /***/ }), -/* 611 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(612); +const NestedError = __webpack_require__(611); class CpyError extends NestedError { constructor(message, nested) { @@ -64124,7 +64058,7 @@ module.exports = CpyError; /***/ }), -/* 612 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -64180,7 +64114,7 @@ module.exports = NestedError; /***/ }), -/* 613 */ +/* 612 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/yarn.lock b/yarn.lock index 67954e168ac91..606487f607648 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25377,20 +25377,10 @@ set-immediate-shim@^1.0.0, set-immediate-shim@~1.0.1: resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -28468,14 +28458,14 @@ union-find@^1.0.0: integrity sha1-KSusQV5q06iVNdI3AQ20pTYoTlg= union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" get-value "^2.0.6" is-extendable "^0.1.1" - set-value "^0.4.3" + set-value "^2.0.1" uniq@^1.0.1: version "1.0.1" From b23cfbdf5de22f826e3cf100392a111246ae1f06 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Wed, 23 Oct 2019 14:48:57 -0700 Subject: [PATCH 097/191] [Reporting/New Platform] Prepare Typedefs for Legacy Shimming (#48825) * [Reporting/New Platform] Prepare Typedefs for Legacy Shim * cleanup redundant * fix opts.interval / opts.pollInterval * comment on next todo * fix pretty * captureconfig typo * fix typescript conflict with shim * clean up loc * custom response toolkit type * remove unecessary route options * move getRouteOptions CSV * fix route configs * cleanup * split up type exports * fix types * fix ts errors * remove an any type --- .../plugins/reporting/common/constants.ts | 2 + .../reporting/common/get_absolute_url.ts | 7 +- .../common/execute_job/decrypt_job_headers.ts | 4 +- .../execute_job/get_conditional_headers.ts | 6 +- .../common/execute_job/get_custom_logo.ts | 4 +- .../common/execute_job/get_full_urls.ts | 4 +- .../execute_job/omit_blacklisted_headers.ts | 4 +- .../common/layouts/create_layout.ts | 4 +- .../common/layouts/print_layout.ts | 4 +- .../common/lib/screenshots/index.ts | 11 +- .../common/lib/screenshots/wait_for_render.ts | 3 +- .../export_types/csv/server/create_job.ts | 9 +- .../reporting/export_types/csv/types.d.ts | 5 +- .../server/create_job/create_job.ts | 10 +- .../server/execute_job.ts | 17 ++- .../server/lib/generate_csv.ts | 12 +- .../server/lib/generate_csv_search.ts | 12 +- .../server/lib/get_job_params_from_request.ts | 4 +- .../csv_from_savedobject/types.d.ts | 4 +- .../png/server/create_job/index.ts | 14 +- .../png/server/lib/generate_png.ts | 4 +- .../reporting/export_types/png/types.d.ts | 5 +- .../printable_pdf/server/lib/generate_pdf.ts | 4 +- .../export_types/printable_pdf/types.d.ts | 7 +- x-pack/legacy/plugins/reporting/index.js | 20 ++- .../plugins/reporting/log_configuration.js | 4 +- .../browsers/browsers.ts => reporting.d.ts} | 8 +- .../browsers/create_browser_driver_factory.ts | 39 +++--- .../browsers/download/ensure_downloaded.ts | 7 +- .../reporting/server/browsers/index.ts | 7 +- .../browsers/{browser_types.ts => types.d.ts} | 2 +- .../reporting/server/lib/create_queue.ts | 6 +- .../server/lib/create_worker.test.ts | 6 +- .../reporting/server/lib/create_worker.ts | 38 +++--- .../plugins/reporting/server/lib/crypto.ts | 4 +- .../reporting/server/lib/enqueue_job.ts | 24 ++-- .../server/lib/export_types_registry.ts | 4 +- .../reporting/server/lib/once_per_server.ts | 8 +- .../reporting/server/lib/validate/index.ts | 10 +- .../server/lib/validate/validate_browser.ts | 8 +- .../server/routes/generate_from_jobparams.ts | 41 +++--- .../routes/generate_from_savedobject.ts | 60 ++++----- .../generate_from_savedobject_immediate.ts | 21 ++- .../plugins/reporting/server/routes/index.ts | 10 +- .../plugins/reporting/server/routes/jobs.ts | 34 ++--- .../plugins/reporting/server/routes/legacy.ts | 19 +-- .../routes/lib/route_config_factories.ts | 21 +-- .../reporting/server/routes/types.d.ts | 7 +- .../test_helpers/create_mock_server.ts | 6 +- x-pack/legacy/plugins/reporting/types.d.ts | 124 ++++++++++++------ 50 files changed, 371 insertions(+), 327 deletions(-) rename x-pack/legacy/plugins/reporting/{server/browsers/browsers.ts => reporting.d.ts} (62%) rename x-pack/legacy/plugins/reporting/server/browsers/{browser_types.ts => types.d.ts} (86%) diff --git a/x-pack/legacy/plugins/reporting/common/constants.ts b/x-pack/legacy/plugins/reporting/common/constants.ts index 6f1f43fe11fe5..723320e74bfbd 100644 --- a/x-pack/legacy/plugins/reporting/common/constants.ts +++ b/x-pack/legacy/plugins/reporting/common/constants.ts @@ -6,6 +6,8 @@ export const PLUGIN_ID = 'reporting'; +export const BROWSER_TYPE = 'chromium'; + export const JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY = 'xpack.reporting.jobCompletionNotifications'; diff --git a/x-pack/legacy/plugins/reporting/common/get_absolute_url.ts b/x-pack/legacy/plugins/reporting/common/get_absolute_url.ts index 299cde58891d3..79c5a274d8c77 100644 --- a/x-pack/legacy/plugins/reporting/common/get_absolute_url.ts +++ b/x-pack/legacy/plugins/reporting/common/get_absolute_url.ts @@ -5,12 +5,11 @@ */ import url from 'url'; -// @ts-ignore import { oncePerServer } from '../server/lib/once_per_server'; -import { ConfigObject, KbnServer } from '../types'; +import { ServerFacade } from '../types'; -function getAbsoluteUrlFn(server: KbnServer) { - const config: ConfigObject = server.config(); +function getAbsoluteUrlFn(server: ServerFacade) { + const config = server.config(); return function getAbsoluteUrl({ basePath = config.get('server.basePath'), diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts index e933056c79441..887f4dbb11be7 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/decrypt_job_headers.ts @@ -5,14 +5,14 @@ */ // @ts-ignore import { cryptoFactory } from '../../../server/lib/crypto'; -import { CryptoFactory, JobDocPayload, KbnServer } from '../../../types'; +import { CryptoFactory, JobDocPayload, ServerFacade } from '../../../types'; export const decryptJobHeaders = async ({ job, server, }: { job: JobDocPayload; - server: KbnServer; + server: ServerFacade; }) => { const crypto: CryptoFactory = cryptoFactory(server); const decryptedHeaders: string = await crypto.decrypt(job.headers); diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts index 04959712a117a..9522d6c087a89 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_conditional_headers.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ConditionalHeaders, ConfigObject, JobDocPayload, KbnServer } from '../../../types'; +import { ConditionalHeaders, JobDocPayload, ServerFacade } from '../../../types'; export const getConditionalHeaders = ({ job, @@ -12,9 +12,9 @@ export const getConditionalHeaders = ({ }: { job: JobDocPayload; filteredHeaders: Record; - server: KbnServer; + server: ServerFacade; }) => { - const config: ConfigObject = server.config(); + const config = server.config(); const [hostname, port, basePath, protocol] = [ config.get('xpack.reporting.kibanaServer.hostname') || config.get('server.host'), config.get('xpack.reporting.kibanaServer.port') || config.get('server.port'), diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts index 00cdd0410fac2..749ab3c50f1c0 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_custom_logo.ts @@ -5,7 +5,7 @@ */ import { UI_SETTINGS_CUSTOM_PDF_LOGO } from '../../../common/constants'; -import { ConditionalHeaders, KbnServer } from '../../../types'; +import { ConditionalHeaders, ServerFacade } from '../../../types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; // Logo is PDF only export const getCustomLogo = async ({ @@ -15,7 +15,7 @@ export const getCustomLogo = async ({ }: { job: JobDocPayloadPDF; conditionalHeaders: ConditionalHeaders; - server: KbnServer; + server: ServerFacade; }) => { const serverBasePath: string = server.config().get('server.basePath'); diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts index e1ca599b38d41..3b82852073421 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/get_full_urls.ts @@ -12,7 +12,7 @@ import { } from 'url'; import { getAbsoluteUrlFactory } from '../../../common/get_absolute_url'; import { validateUrls } from '../../../common/validate_urls'; -import { KbnServer } from '../../../types'; +import { ServerFacade } from '../../../types'; import { JobDocPayloadPNG } from '../../png/types'; import { JobDocPayloadPDF } from '../../printable_pdf/types'; @@ -26,7 +26,7 @@ export async function getFullUrls({ ...mergeValues // pass-throughs }: { job: JobDocPayloadPNG | JobDocPayloadPDF; - server: KbnServer; + server: ServerFacade; }) { const getAbsoluteUrl = getAbsoluteUrlFactory(server); diff --git a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/omit_blacklisted_headers.ts b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/omit_blacklisted_headers.ts index 44a9ed5a8ee51..a0aa4d973298d 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/execute_job/omit_blacklisted_headers.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/execute_job/omit_blacklisted_headers.ts @@ -5,7 +5,7 @@ */ import { omit } from 'lodash'; import { KBN_SCREENSHOT_HEADER_BLACKLIST } from '../../../common/constants'; -import { JobDocPayload, KbnServer } from '../../../types'; +import { JobDocPayload, ServerFacade } from '../../../types'; export const omitBlacklistedHeaders = ({ job, @@ -14,7 +14,7 @@ export const omitBlacklistedHeaders = ({ }: { job: JobDocPayload; decryptedHeaders: Record; - server: KbnServer; + server: ServerFacade; }) => { const filteredHeaders: Record = omit( decryptedHeaders, diff --git a/x-pack/legacy/plugins/reporting/export_types/common/layouts/create_layout.ts b/x-pack/legacy/plugins/reporting/export_types/common/layouts/create_layout.ts index 17c540e807211..0cb83352d4606 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/layouts/create_layout.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/layouts/create_layout.ts @@ -3,13 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { KbnServer } from '../../../types'; +import { ServerFacade } from '../../../types'; import { LayoutTypes } from '../constants'; import { Layout, LayoutParams } from './layout'; import { PreserveLayout } from './preserve_layout'; import { PrintLayout } from './print_layout'; -export function createLayout(server: KbnServer, layoutParams?: LayoutParams): Layout { +export function createLayout(server: ServerFacade, layoutParams?: LayoutParams): Layout { if (layoutParams && layoutParams.id === LayoutTypes.PRESERVE_LAYOUT) { return new PreserveLayout(layoutParams.dimensions); } diff --git a/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts b/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts index 9d672318000c1..44361181e3262 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/layouts/print_layout.ts @@ -7,7 +7,7 @@ import path from 'path'; import { EvaluateFn, SerializableOrJSHandle } from 'puppeteer'; import { LevelLogger } from '../../../server/lib'; import { HeadlessChromiumDriver } from '../../../server/browsers/chromium/driver'; -import { KbnServer } from '../../../types'; +import { ServerFacade } from '../../../types'; import { LayoutTypes } from '../constants'; import { getDefaultLayoutSelectors, Layout, LayoutSelectorDictionary, Size } from './layout'; import { CaptureConfig } from './types'; @@ -20,7 +20,7 @@ export class PrintLayout extends Layout { public readonly groupCount = 2; private captureConfig: CaptureConfig; - constructor(server: KbnServer) { + constructor(server: ServerFacade) { super(LayoutTypes.PRINT); this.captureConfig = server.config().get('xpack.reporting.capture'); } diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts index 9713adc76a5fa..0c63def67bd04 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/index.ts @@ -6,8 +6,7 @@ import * as Rx from 'rxjs'; import { first, mergeMap } from 'rxjs/operators'; -import { KbnServer } from '../../../../types'; -import { HeadlessChromiumDriverFactory } from '../../../../server/browsers/chromium/driver_factory'; +import { ServerFacade, CaptureConfig } from '../../../../types'; import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers/chromium/driver'; import { ElementsPositionAndAttribute, @@ -29,14 +28,14 @@ import { skipTelemetry } from './skip_telemetry'; // NOTE: Typescript does not throw an error if this interface has errors! interface ScreenshotResults { - timeRange: TimeRange; + timeRang: TimeRange; screenshots: Screenshot[]; } -export function screenshotsObservableFactory(server: KbnServer) { - const browserDriverFactory: HeadlessChromiumDriverFactory = server.plugins.reporting.browserDriverFactory; // prettier-ignore +export function screenshotsObservableFactory(server: ServerFacade) { const config = server.config(); - const captureConfig = config.get('xpack.reporting.capture'); + const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); + const { browserDriverFactory } = server.plugins.reporting!; return function screenshotsObservable({ logger, diff --git a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_render.ts b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_render.ts index b49b52e18ded7..df0d591ff913c 100644 --- a/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_render.ts +++ b/x-pack/legacy/plugins/reporting/export_types/common/lib/screenshots/wait_for_render.ts @@ -4,12 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import { CaptureConfig } from '../../../../types'; import { HeadlessChromiumDriver as HeadlessBrowser } from '../../../../server/browsers/chromium/driver'; import { LevelLogger } from '../../../../server/lib'; import { LayoutInstance } from '../../layouts/layout'; export const waitForRenderComplete = async ( - captureConfig: any, + captureConfig: CaptureConfig, browser: HeadlessBrowser, layout: LayoutInstance, logger: LevelLogger diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts index 952547790adbb..b1713e1753eea 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/create_job.ts @@ -4,19 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; import { oncePerServer } from '../../../server/lib/once_per_server'; import { cryptoFactory } from '../../../server/lib/crypto'; -import { KbnServer, ConditionalHeaders, CreateJobFactory } from '../../../types'; +import { ConditionalHeaders, CreateJobFactory, ServerFacade, RequestFacade } from '../../../types'; import { JobParamsDiscoverCsv, ESQueueCreateJobFnDiscoverCsv } from '../types'; -function createJobFn(server: KbnServer) { +function createJobFn(server: ServerFacade) { const crypto = cryptoFactory(server); return async function createJob( jobParams: JobParamsDiscoverCsv, headers: ConditionalHeaders, - request: Request + request: RequestFacade ) { const serializedEncryptedHeaders = await crypto.encrypt(headers); @@ -36,5 +35,5 @@ function createJobFn(server: KbnServer) { } export const createJobFactory: CreateJobFactory = oncePerServer(createJobFn as ( - server: KbnServer + server: ServerFacade ) => ESQueueCreateJobFnDiscoverCsv); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts index 3906c2bb1449d..09f32833915b6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; -import { JobDocPayload, JobParamPostPayload, ConditionalHeaders } from '../../types'; +import { JobDocPayload, JobParamPostPayload, ConditionalHeaders, RequestFacade } from '../../types'; export interface JobParamPostPayloadDiscoverCsv extends JobParamPostPayload { state?: { @@ -30,5 +29,5 @@ export interface JobDocPayloadDiscoverCsv extends JobDocPayload { export type ESQueueCreateJobFnDiscoverCsv = ( jobParams: JobParamsDiscoverCsv, headers: ConditionalHeaders, - request: Request + request: RequestFacade ) => Promise; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts index 07fdf42a15171..0bcfc6f1ca07c 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/create_job/create_job.ts @@ -5,12 +5,10 @@ */ import { notFound, notImplemented } from 'boom'; -import { Request } from 'hapi'; import { get } from 'lodash'; - import { PLUGIN_ID, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../../common/constants'; import { cryptoFactory, LevelLogger, oncePerServer } from '../../../../server/lib'; -import { KbnServer } from '../../../../types'; +import { ServerFacade, RequestFacade } from '../../../../types'; import { SavedObject, SavedObjectServiceError, @@ -32,10 +30,10 @@ interface VisData { type CreateJobFn = ( jobParams: JobParamsPanelCsv, headers: any, - req: Request + req: RequestFacade ) => Promise; -function createJobFn(server: KbnServer): CreateJobFn { +function createJobFn(server: ServerFacade): CreateJobFn { const crypto = cryptoFactory(server); const logger = LevelLogger.createForServer(server, [ PLUGIN_ID, @@ -46,7 +44,7 @@ function createJobFn(server: KbnServer): CreateJobFn { return async function createJob( jobParams: JobParamsPanelCsv, headers: any, - req: Request + req: RequestFacade ): Promise { const { savedObjectType, savedObjectId } = jobParams; const serializedEncryptedHeaders = await crypto.encrypt(headers); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts index ece5217a56205..9d4bcf1e4b27a 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/execute_job.ts @@ -4,11 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; import { i18n } from '@kbn/i18n'; - import { cryptoFactory, LevelLogger, oncePerServer } from '../../../server/lib'; -import { JobDocOutputExecuted, KbnServer, ExecuteImmediateJobFactory } from '../../../types'; +import { + JobDocOutputExecuted, + ServerFacade, + ExecuteImmediateJobFactory, + RequestFacade, +} from '../../../types'; import { CONTENT_TYPE_CSV, CSV_FROM_SAVEDOBJECT_JOB_TYPE, @@ -20,10 +23,10 @@ import { createGenerateCsv } from './lib'; type ExecuteJobFn = ( jobId: string | null, job: JobDocPayloadPanelCsv, - realRequest?: Request + realRequest?: RequestFacade ) => Promise; -function executeJobFactoryFn(server: KbnServer): ExecuteJobFn { +function executeJobFactoryFn(server: ServerFacade): ExecuteJobFn { const crypto = cryptoFactory(server); const logger = LevelLogger.createForServer(server, [ PLUGIN_ID, @@ -34,7 +37,7 @@ function executeJobFactoryFn(server: KbnServer): ExecuteJobFn { return async function executeJob( jobId: string | null, job: JobDocPayloadPanelCsv, - realRequest?: Request + realRequest?: RequestFacade ): Promise { // There will not be a jobID for "immediate" generation. // jobID is only for "queued" jobs @@ -46,7 +49,7 @@ function executeJobFactoryFn(server: KbnServer): ExecuteJobFn { jobLogger.debug(`Execute job generating [${visType}] csv`); - let requestObject: Request | FakeRequest; + let requestObject: RequestFacade | FakeRequest; if (isImmediate && realRequest) { jobLogger.info(`Executing job from immediate API`); requestObject = realRequest; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv.ts index aafad4674a1b2..6a4c6df5e1ace 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv.ts @@ -5,16 +5,14 @@ */ import { badRequest } from 'boom'; -import { Request } from 'hapi'; -import { KbnServer, Logger } from '../../../../types'; -import { SearchPanel, VisPanel, JobParamsPanelCsv } from '../../types'; -import { FakeRequest } from '../../types'; +import { ServerFacade, RequestFacade, Logger } from '../../../../types'; +import { SearchPanel, VisPanel, JobParamsPanelCsv, FakeRequest } from '../../types'; import { generateCsvSearch } from './generate_csv_search'; export function createGenerateCsv(logger: Logger) { return async function generateCsv( - request: Request | FakeRequest, - server: KbnServer, + request: RequestFacade | FakeRequest, + server: ServerFacade, visType: string, panel: VisPanel | SearchPanel, jobParams: JobParamsPanelCsv @@ -27,7 +25,7 @@ export function createGenerateCsv(logger: Logger) { switch (visType) { case 'search': return await generateCsvSearch( - request as Request, + request as RequestFacade, server, logger, panel as SearchPanel, diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts index da2c184d2d6e0..2e2c8635fca5f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts @@ -4,15 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; - import { buildEsQuery } from '@kbn/es-query'; // @ts-ignore no module definition import { createGenerateCsv } from '../../../csv/server/lib/generate_csv'; - import { CancellationToken } from '../../../../common/cancellation_token'; - -import { KbnServer, Logger } from '../../../../types'; +import { ServerFacade, RequestFacade, Logger } from '../../../../types'; import { IndexPatternSavedObject, SavedSearchObjectAttributes, @@ -50,8 +46,8 @@ const getUiSettings = async (config: any) => { }; export async function generateCsvSearch( - req: Request, - server: KbnServer, + req: RequestFacade, + server: ServerFacade, logger: Logger, searchPanel: SearchPanel, jobParams: JobParamsDiscoverCsv @@ -140,7 +136,7 @@ export async function generateCsvSearch( }, }; const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); - const callCluster = (...params: any[]) => callWithRequest(req, ...params); + const callCluster = (...params: [string, object]) => callWithRequest(req, ...params); const config = server.config(); const uiSettings = await getUiSettings(uiConfig); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_job_params_from_request.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_job_params_from_request.ts index 2041b1253ee51..774e430d593cd 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_job_params_from_request.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/get_job_params_from_request.ts @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; +import { RequestFacade } from '../../../../types'; import { JobParamsPostPayloadPanelCsv, JobParamsPanelCsv } from '../../types'; export function getJobParamsFromRequest( - request: Request, + request: RequestFacade, opts: { isImmediate: boolean } ): Partial { const { savedObjectType, savedObjectId } = request.params; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts index aa681210fc740..f8692c336b292 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/types.d.ts @@ -5,11 +5,11 @@ */ import { CancellationToken } from '../../common/cancellation_token'; -import { JobParamPostPayload, JobDocPayload, KbnServer } from '../../types'; +import { JobParamPostPayload, JobDocPayload, ServerFacade } from '../../types'; export interface FakeRequest { headers: any; - server: KbnServer; + server: ServerFacade; } export interface JobParamsPostPayloadPanelCsv extends JobParamPostPayload { diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts b/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts index 2ee1e7a874355..4176a1351d654 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/create_job/index.ts @@ -4,20 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; -import { KbnServer, ConditionalHeaders, CreateJobFactory } from '../../../../types'; +import { + ServerFacade, + RequestFacade, + ConditionalHeaders, + CreateJobFactory, +} from '../../../../types'; import { validateUrls } from '../../../../common/validate_urls'; import { cryptoFactory } from '../../../../server/lib/crypto'; import { oncePerServer } from '../../../../server/lib/once_per_server'; import { JobParamsPNG, ESQueueCreateJobFnPNG } from '../../types'; -function createJobFn(server: KbnServer) { +function createJobFn(server: ServerFacade) { const crypto = cryptoFactory(server); return async function createJob( { objectType, title, relativeUrl, browserTimezone, layout }: JobParamsPNG, headers: ConditionalHeaders, - request: Request + request: RequestFacade ) { const serializedEncryptedHeaders = await crypto.encrypt(headers); @@ -37,5 +41,5 @@ function createJobFn(server: KbnServer) { } export const createJobFactory: CreateJobFactory = oncePerServer(createJobFn as ( - server: KbnServer + server: ServerFacade ) => ESQueueCreateJobFnPNG); diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/lib/generate_png.ts b/x-pack/legacy/plugins/reporting/export_types/png/server/lib/generate_png.ts index 3d09d2dae42a1..5980f1884ab2f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/lib/generate_png.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/lib/generate_png.ts @@ -7,7 +7,7 @@ import * as Rx from 'rxjs'; import { toArray, mergeMap } from 'rxjs/operators'; import { LevelLogger } from '../../../../server/lib'; -import { KbnServer, ConditionalHeaders } from '../../../../types'; +import { ServerFacade, ConditionalHeaders } from '../../../../types'; import { oncePerServer } from '../../../../server/lib/once_per_server'; import { screenshotsObservableFactory } from '../../../common/lib/screenshots'; import { PreserveLayout } from '../../../common/layouts/preserve_layout'; @@ -21,7 +21,7 @@ interface UrlScreenshot { screenshots: ScreenshotData[]; } -function generatePngObservableFn(server: KbnServer) { +function generatePngObservableFn(server: ServerFacade) { const screenshotsObservable = screenshotsObservableFactory(server); const captureConcurrency = 1; diff --git a/x-pack/legacy/plugins/reporting/export_types/png/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/png/types.d.ts index f0590f98da362..c7ea2bdfba59f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/png/types.d.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; import { LayoutInstance } from '../common/layouts/layout'; -import { ConditionalHeaders, KbnServer, JobDocPayload } from '../../types'; +import { ConditionalHeaders, JobDocPayload, RequestFacade } from '../../types'; // Job params: structure of incoming user request data export interface JobParamsPNG { @@ -30,5 +29,5 @@ export interface JobDocPayloadPNG extends JobDocPayload { export type ESQueueCreateJobFnPNG = ( jobParams: JobParamsPNG, headers: ConditionalHeaders, - request: Request + request: RequestFacade ) => Promise; diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/lib/generate_pdf.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/lib/generate_pdf.ts index e57e18eff1b67..0d2243acfef9b 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/lib/generate_pdf.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/lib/generate_pdf.ts @@ -8,7 +8,7 @@ import * as Rx from 'rxjs'; import { toArray, mergeMap } from 'rxjs/operators'; import { groupBy } from 'lodash'; import { LevelLogger } from '../../../../server/lib'; -import { KbnServer, ConditionalHeaders } from '../../../../types'; +import { ServerFacade, ConditionalHeaders } from '../../../../types'; // @ts-ignore untyped module import { pdf } from './pdf'; import { oncePerServer } from '../../../../server/lib/once_per_server'; @@ -38,7 +38,7 @@ const getTimeRange = (urlScreenshots: UrlScreenshot[]) => { return null; }; -function generatePdfObservableFn(server: KbnServer) { +function generatePdfObservableFn(server: ServerFacade) { const screenshotsObservable = screenshotsObservableFactory(server); const captureConcurrency = 1; diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts index a27b4aed48760..d1e5e58f0f0a5 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/types.d.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; import { LayoutInstance } from '../common/layouts/layout'; -import { ConditionalHeaders, KbnServer, JobDocPayload } from '../../types'; +import { ConditionalHeaders, JobDocPayload, ServerFacade, RequestFacade } from '../../types'; // Job params: structure of incoming user request data, after being parsed from RISON export interface JobParamsPDF { @@ -32,7 +31,7 @@ export interface JobDocPayloadPDF extends JobDocPayload { export type ESQueueCreateJobFnPDF = ( jobParams: JobParamsPDF, headers: ConditionalHeaders, - request: Request + request: RequestFacade ) => Promise; -export type CreateJobFactoryPDF = (server: KbnServer) => ESQueueCreateJobFnPDF; +export type CreateJobFactoryPDF = (server: ServerFacade) => ESQueueCreateJobFnPDF; diff --git a/x-pack/legacy/plugins/reporting/index.js b/x-pack/legacy/plugins/reporting/index.js index 95c792d9d5171..1fe83124e2b45 100644 --- a/x-pack/legacy/plugins/reporting/index.js +++ b/x-pack/legacy/plugins/reporting/index.js @@ -5,7 +5,7 @@ */ import { resolve } from 'path'; -import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants'; +import { PLUGIN_ID, BROWSER_TYPE, UI_SETTINGS_CUSTOM_PDF_LOGO } from './common/constants'; import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status'; import { registerRoutes } from './server/routes'; import { @@ -16,13 +16,8 @@ import { runValidations, } from './server/lib'; import { config as appConfig } from './server/config/config'; -import { - CHROMIUM, - createBrowserDriverFactory, - getDefaultChromiumSandboxDisabled, -} from './server/browsers'; +import { createBrowserDriverFactory, getDefaultChromiumSandboxDisabled } from './server/browsers'; import { logConfiguration } from './log_configuration'; - import { getReportingUsageCollector } from './server/usage'; import { i18n } from '@kbn/i18n'; @@ -116,7 +111,7 @@ export const reporting = (kibana) => { settleTime: Joi.number().integer().default(1000), //deprecated concurrency: Joi.number().integer().default(appConfig.concurrency), //deprecated browser: Joi.object({ - type: Joi.any().valid(CHROMIUM).default(CHROMIUM), + type: Joi.any().valid(BROWSER_TYPE).default(BROWSER_TYPE), autoDownload: Joi.boolean().when('$dist', { is: true, then: Joi.default(false), @@ -182,22 +177,23 @@ export const reporting = (kibana) => { }).default(); }, + // TODO: Decouple Hapi: Build a server facade object based on the server to + // pass through to the libs. Do not pass server directly init: async function (server) { let isCollectorReady = false; const isReady = () => isCollectorReady; // Register a function with server to manage the collection of usage stats server.usage.collectorSet.register(getReportingUsageCollector(server, isReady)); - const logger = LevelLogger.createForServer(server, [PLUGIN_ID], true); + const logger = LevelLogger.createForServer(server, [PLUGIN_ID]); const [exportTypesRegistry, browserFactory] = await Promise.all([ exportTypesRegistryFactory(server), createBrowserDriverFactory(server), ]); server.expose('exportTypesRegistry', exportTypesRegistry); - const config = server.config(); - logConfiguration(config, logger); - runValidations(server, config, logger, browserFactory); + logConfiguration(server, logger); + runValidations(server, logger, browserFactory); const { xpack_main: xpackMainPlugin } = server.plugins; mirrorPluginStatus(xpackMainPlugin, this); diff --git a/x-pack/legacy/plugins/reporting/log_configuration.js b/x-pack/legacy/plugins/reporting/log_configuration.js index ef4dab2ee3be7..94ff90f5944d0 100644 --- a/x-pack/legacy/plugins/reporting/log_configuration.js +++ b/x-pack/legacy/plugins/reporting/log_configuration.js @@ -9,7 +9,9 @@ import { promisify } from 'util'; const getos = promisify(getosSync); -export async function logConfiguration(config, logger) { +export async function logConfiguration(server, logger) { + const config = server.config(); + const browserType = config.get('xpack.reporting.capture.browser.type'); logger.debug(`Browser type: ${browserType}`); diff --git a/x-pack/legacy/plugins/reporting/server/browsers/browsers.ts b/x-pack/legacy/plugins/reporting/reporting.d.ts similarity index 62% rename from x-pack/legacy/plugins/reporting/server/browsers/browsers.ts rename to x-pack/legacy/plugins/reporting/reporting.d.ts index ff9dece504ea6..d4a7943f6d067 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/browsers.ts +++ b/x-pack/legacy/plugins/reporting/reporting.d.ts @@ -4,10 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -import * as chromium from './chromium'; - -export type BrowserType = keyof typeof BROWSERS_BY_TYPE; - -export const BROWSERS_BY_TYPE = { - chromium, -}; +export { ReportingPlugin } from './types'; diff --git a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts index de4312ea1bef4..a253988b01952 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/create_browser_driver_factory.ts @@ -4,44 +4,43 @@ * you may not use this file except in compliance with the Elastic License. */ -import { BROWSERS_BY_TYPE, BrowserType } from './browsers'; import { ensureBrowserDownloaded } from './download'; import { installBrowser } from './install'; import { LevelLogger } from '../lib/level_logger'; -import { KbnServer } from '../../types'; -import { PLUGIN_ID } from '../../common/constants'; +import { ServerFacade, CaptureConfig } from '../../types'; +import { PLUGIN_ID, BROWSER_TYPE } from '../../common/constants'; +import { chromium } from './index'; import { HeadlessChromiumDriverFactory } from './chromium/driver_factory'; export async function createBrowserDriverFactory( - server: KbnServer + server: ServerFacade ): Promise { const config = server.config(); const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'browser-driver']); - const DATA_DIR = config.get('path.data'); - const CAPTURE_CONFIG = config.get('xpack.reporting.capture'); - const BROWSER_TYPE: BrowserType = CAPTURE_CONFIG.browser.type; - const BROWSER_AUTO_DOWNLOAD = CAPTURE_CONFIG.browser.autoDownload; - const BROWSER_CONFIG = CAPTURE_CONFIG.browser[BROWSER_TYPE]; - const NETWORK_POLICY = CAPTURE_CONFIG.networkPolicy; - const REPORTING_TIMEOUT = config.get('xpack.reporting.queue.timeout'); + const dataDir: string = config.get('path.data'); + const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); + const browserType = captureConfig.browser.type; + const browserAutoDownload = captureConfig.browser.autoDownload; + const browserConfig = captureConfig.browser[BROWSER_TYPE]; + const networkPolicy = captureConfig.networkPolicy; + const reportingTimeout: number = config.get('xpack.reporting.queue.timeout'); - if (BROWSER_CONFIG.disableSandbox) { + if (browserConfig.disableSandbox) { logger.warning(`Enabling the Chromium sandbox provides an additional layer of protection.`); } - if (BROWSER_AUTO_DOWNLOAD) { - await ensureBrowserDownloaded(BROWSER_TYPE); + if (browserAutoDownload) { + await ensureBrowserDownloaded(browserType); } try { - const browser = BROWSERS_BY_TYPE[BROWSER_TYPE]; // NOTE: unecessary indirection: this is always a Chromium browser object, as of PhantomJS removal - const { binaryPath } = await installBrowser(logger, browser, DATA_DIR); - return browser.createDriverFactory( + const { binaryPath } = await installBrowser(logger, chromium, dataDir); + return chromium.createDriverFactory( binaryPath, logger, - BROWSER_CONFIG, - REPORTING_TIMEOUT, - NETWORK_POLICY + browserConfig, + reportingTimeout, + networkPolicy ); } catch (error) { if (error.cause && ['EACCES', 'EEXIST'].includes(error.cause.code)) { diff --git a/x-pack/legacy/plugins/reporting/server/browsers/download/ensure_downloaded.ts b/x-pack/legacy/plugins/reporting/server/browsers/download/ensure_downloaded.ts index d322566f9aa1d..c79d2c263b2e1 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/download/ensure_downloaded.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/download/ensure_downloaded.ts @@ -7,7 +7,8 @@ import { resolve as resolvePath } from 'path'; import { existsSync } from 'fs'; -import { BROWSERS_BY_TYPE, BrowserType } from '../browsers'; +import { chromium } from '../index'; +import { BrowserType } from '../types'; import { md5 } from './checksum'; import { asyncMap } from './util'; @@ -21,7 +22,7 @@ import { clean } from './clean'; * @return {Promise} */ export async function ensureBrowserDownloaded(browserType: BrowserType) { - await ensureDownloaded([BROWSERS_BY_TYPE[browserType]]); + await ensureDownloaded([chromium]); } /** @@ -29,7 +30,7 @@ export async function ensureBrowserDownloaded(browserType: BrowserType) { * @return {Promise} */ export async function ensureAllBrowsersDownloaded() { - await ensureDownloaded(Object.values(BROWSERS_BY_TYPE)); + await ensureDownloaded([chromium]); } /** diff --git a/x-pack/legacy/plugins/reporting/server/browsers/index.ts b/x-pack/legacy/plugins/reporting/server/browsers/index.ts index 3f97a1368246b..a5ecc405bf9c5 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/index.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/index.ts @@ -3,8 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import * as chromiumDefinition from './chromium'; export { ensureAllBrowsersDownloaded } from './download'; export { createBrowserDriverFactory } from './create_browser_driver_factory'; export { getDefaultChromiumSandboxDisabled } from './default_chromium_sandbox_disabled'; -export { CHROMIUM } from './browser_types'; + +export const chromium = { + paths: chromiumDefinition.paths, + createDriverFactory: chromiumDefinition.createDriverFactory, +}; diff --git a/x-pack/legacy/plugins/reporting/server/browsers/browser_types.ts b/x-pack/legacy/plugins/reporting/server/browsers/types.d.ts similarity index 86% rename from x-pack/legacy/plugins/reporting/server/browsers/browser_types.ts rename to x-pack/legacy/plugins/reporting/server/browsers/types.d.ts index 0d67678c183ad..43cbb0f13a5a7 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/browser_types.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/types.d.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export const CHROMIUM = 'chromium'; +export type BrowserType = 'chromium'; diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts index 9519b7170d76f..a7e81093c136a 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_queue.ts @@ -5,7 +5,7 @@ */ import { PLUGIN_ID } from '../../common/constants'; -import { KbnServer } from '../../types'; +import { ServerFacade, QueueConfig } from '../../types'; // @ts-ignore import { Esqueue } from './esqueue'; import { createWorkerFactory } from './create_worker'; @@ -14,8 +14,8 @@ import { LevelLogger } from './level_logger'; // @ts-ignore import { createTaggedLogger } from './create_tagged_logger'; // TODO remove createTaggedLogger once esqueue is removed -function createQueueFn(server: KbnServer): Esqueue { - const queueConfig = server.config().get('xpack.reporting.queue'); +function createQueueFn(server: ServerFacade): Esqueue { + const queueConfig: QueueConfig = server.config().get('xpack.reporting.queue'); const index = server.config().get('xpack.reporting.index'); const queueOptions = { diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts index 28997ce0a388d..afad8f096a8bb 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.test.ts @@ -5,7 +5,7 @@ */ import * as sinon from 'sinon'; -import { KbnServer } from '../../types'; +import { ServerFacade } from '../../types'; import { createWorkerFactory } from './create_worker'; // @ts-ignore import { Esqueue } from './esqueue'; @@ -24,13 +24,13 @@ const executeJobFactoryStub = sinon.stub(); const getMockServer = ( exportTypes: any[] = [{ executeJobFactory: executeJobFactoryStub }] -): KbnServer => { +): ServerFacade => { return ({ log: sinon.stub(), expose: sinon.stub(), config: () => ({ get: configGetStub }), plugins: { reporting: { exportTypesRegistry: { getAll: () => exportTypes } } }, - } as unknown) as KbnServer; + } as unknown) as ServerFacade; }; describe('Create Worker', () => { diff --git a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts index 0e53fe23a4f29..7166659487c9b 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/create_worker.ts @@ -7,42 +7,50 @@ import { PLUGIN_ID } from '../../common/constants'; import { ESQueueInstance, + QueueConfig, + ExportTypeDefinition, ESQueueWorkerExecuteFn, - ExportType, + ImmediateExecuteFn, JobDoc, + JobDocPayload, JobSource, - KbnServer, + ServerFacade, } from '../../types'; // @ts-ignore untyped dependency import { events as esqueueEvents } from './esqueue'; import { LevelLogger } from './level_logger'; import { oncePerServer } from './once_per_server'; -function createWorkerFn(server: KbnServer) { +function createWorkerFn(server: ServerFacade) { const config = server.config(); - const queueConfig = config.get('xpack.reporting.queue'); - const kibanaName = config.get('server.name'); - const kibanaId = config.get('server.uuid'); - const exportTypesRegistry = server.plugins.reporting.exportTypesRegistry; const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'queue-worker']); + const queueConfig: QueueConfig = config.get('xpack.reporting.queue'); + const kibanaName: string = config.get('server.name'); + const kibanaId: string = config.get('server.uuid'); + const { exportTypesRegistry } = server.plugins.reporting!; // Once more document types are added, this will need to be passed in return function createWorker(queue: ESQueueInstance) { // export type / execute job map - const jobExectors: Map = new Map(); + const jobExecutors: Map = new Map(); - for (const exportType of exportTypesRegistry.getAll() as ExportType[]) { - const executeJob = exportType.executeJobFactory(server); - jobExectors.set(exportType.jobType, executeJob); + for (const exportType of exportTypesRegistry.getAll() as ExportTypeDefinition[]) { + const executeJobFactory = exportType.executeJobFactory(server); + jobExecutors.set(exportType.jobType, executeJobFactory); } - const workerFn = (job: JobSource, jobdoc: JobDoc, cancellationToken: any) => { + const workerFn = (job: JobSource, jobdoc: JobDocPayload | JobDoc, cancellationToken?: any) => { // pass the work to the jobExecutor - const jobExecutor = jobExectors.get(job._source.jobtype); - if (!jobExecutor) { + if (!jobExecutors.get(job._source.jobtype)) { throw new Error(`Unable to find a job executor for the claimed job: [${job._id}]`); } - return jobExecutor(job._id, jobdoc, cancellationToken); + if (job._id) { + const jobExecutor = jobExecutors.get(job._source.jobtype) as ESQueueWorkerExecuteFn; + return jobExecutor(job._id, jobdoc as JobDoc, cancellationToken); + } else { + const jobExecutor = jobExecutors.get(job._source.jobtype) as ImmediateExecuteFn; + return jobExecutor(null, jobdoc as JobDocPayload, cancellationToken); + } }; const workerOptions = { kibanaName, diff --git a/x-pack/legacy/plugins/reporting/server/lib/crypto.ts b/x-pack/legacy/plugins/reporting/server/lib/crypto.ts index 60e558479af5e..dbc01fc947f8b 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/crypto.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/crypto.ts @@ -6,9 +6,9 @@ import nodeCrypto from '@elastic/node-crypto'; import { oncePerServer } from './once_per_server'; -import { KbnServer } from '../../types'; +import { ServerFacade } from '../../types'; -function cryptoFn(server: KbnServer) { +function cryptoFn(server: ServerFacade) { const encryptionKey = server.config().get('xpack.reporting.encryptionKey'); return nodeCrypto({ encryptionKey }); } diff --git a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts index ec0ffdf51733e..c264c0ca7e0eb 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/enqueue_job.ts @@ -4,12 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; import { get } from 'lodash'; // @ts-ignore import { events as esqueueEvents } from './esqueue'; import { oncePerServer } from './once_per_server'; -import { KbnServer, Logger, ConditionalHeaders } from '../../types'; +import { + ServerFacade, + RequestFacade, + Logger, + CaptureConfig, + QueueConfig, + ConditionalHeaders, +} from '../../types'; interface ConfirmedJob { id: string; @@ -18,13 +24,13 @@ interface ConfirmedJob { _primary_term: number; } -function enqueueJobFn(server: KbnServer) { - const jobQueue = server.plugins.reporting.queue; +function enqueueJobFn(server: ServerFacade) { const config = server.config(); - const queueConfig = config.get('xpack.reporting.queue'); - const browserType = config.get('xpack.reporting.capture.browser.type'); - const maxAttempts = config.get('xpack.reporting.capture.maxAttempts'); - const exportTypesRegistry = server.plugins.reporting.exportTypesRegistry; + const captureConfig: CaptureConfig = config.get('xpack.reporting.capture'); + const browserType = captureConfig.browser.type; + const maxAttempts = captureConfig.maxAttempts; + const queueConfig: QueueConfig = config.get('xpack.reporting.queue'); + const { exportTypesRegistry, queue: jobQueue } = server.plugins.reporting!; return async function enqueueJob( parentLogger: Logger, @@ -32,7 +38,7 @@ function enqueueJobFn(server: KbnServer) { jobParams: object, user: string, headers: ConditionalHeaders, - request: Request + request: RequestFacade ) { const logger = parentLogger.clone(['queue-job']); const exportType = exportTypesRegistry.getById(exportTypeId); diff --git a/x-pack/legacy/plugins/reporting/server/lib/export_types_registry.ts b/x-pack/legacy/plugins/reporting/server/lib/export_types_registry.ts index 21f954fe739d7..35c97f1db10dc 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/export_types_registry.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/export_types_registry.ts @@ -6,7 +6,7 @@ import { resolve as pathResolve } from 'path'; import glob from 'glob'; -import { KbnServer } from '../../types'; +import { ServerFacade } from '../../types'; import { PLUGIN_ID } from '../../common/constants'; import { oncePerServer } from './once_per_server'; import { LevelLogger } from './level_logger'; @@ -26,7 +26,7 @@ function scan(pattern: string) { } const pattern = pathResolve(__dirname, '../../export_types/*/server/index.[jt]s'); -async function exportTypesRegistryFn(server: KbnServer) { +async function exportTypesRegistryFn(server: ServerFacade) { const logger = LevelLogger.createForServer(server, [PLUGIN_ID, 'exportTypes']); const exportTypesRegistry = new ExportTypesRegistry(); const files: string[] = (await scan(pattern)) as string[]; diff --git a/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts b/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts index d4fa35908917d..d73a5b73fecd0 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/once_per_server.ts @@ -5,10 +5,10 @@ */ import { memoize, MemoizedFunction } from 'lodash'; -import { KbnServer } from '../../types'; +import { ServerFacade } from '../../types'; -type ServerFn = (server: KbnServer) => any; -type Memo = ((server: KbnServer) => any) & MemoizedFunction; +type ServerFn = (server: ServerFacade) => any; +type Memo = ((server: ServerFacade) => any) & MemoizedFunction; /** * allow this function to be called multiple times, but @@ -22,7 +22,7 @@ type Memo = ((server: KbnServer) => any) & MemoizedFunction; * @return {any} */ export function oncePerServer(fn: ServerFn) { - const memoized: Memo = memoize(function(server: KbnServer) { + const memoized: Memo = memoize(function(server: ServerFacade) { if (arguments.length !== 1) { throw new TypeError('This function expects to be called with a single argument'); } diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts index f785fac58d486..e0382c0205345 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/index.ts @@ -4,18 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ConfigObject, KbnServer, Logger } from '../../../types'; +import { ServerFacade, Logger } from '../../../types'; import { validateBrowser } from './validate_browser'; import { validateConfig } from './validate_config'; import { validateMaxContentLength } from './validate_max_content_length'; -export async function runValidations( - server: KbnServer, - config: ConfigObject, - logger: Logger, - browserFactory: any -) { +export async function runValidations(server: ServerFacade, logger: Logger, browserFactory: any) { try { + const config = server.config(); await Promise.all([ validateBrowser(server, browserFactory, logger), validateConfig(config, logger), diff --git a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_browser.ts b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_browser.ts index 7d011e6c0886e..031709c85284c 100644 --- a/x-pack/legacy/plugins/reporting/server/lib/validate/validate_browser.ts +++ b/x-pack/legacy/plugins/reporting/server/lib/validate/validate_browser.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { Browser } from 'puppeteer'; -import { KbnServer, Logger } from '../../../types'; -import { CHROMIUM } from '../../browsers/browser_types'; +import { BROWSER_TYPE } from '../../../common/constants'; +import { ServerFacade, Logger } from '../../../types'; import { HeadlessChromiumDriverFactory } from '../../browsers/chromium/driver_factory'; /* @@ -13,11 +13,11 @@ import { HeadlessChromiumDriverFactory } from '../../browsers/chromium/driver_fa * to the locally running Kibana instance. */ export const validateBrowser = async ( - server: KbnServer, + server: ServerFacade, browserFactory: HeadlessChromiumDriverFactory, logger: Logger ) => { - if (browserFactory.type === CHROMIUM) { + if (browserFactory.type === BROWSER_TYPE) { return browserFactory .test({ viewport: { width: 800, height: 600 } }, logger) .then((browser: Browser | null) => { diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts index 9dc1e9d12e308..9c7e0a5f27786 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_jobparams.ts @@ -6,28 +6,33 @@ import boom from 'boom'; import Joi from 'joi'; -import { Request, ResponseToolkit } from 'hapi'; import rison from 'rison-node'; import { API_BASE_URL } from '../../common/constants'; -import { KbnServer } from '../../types'; -import { getRouteConfigFactoryReportingPre } from './lib/route_config_factories'; +import { ServerFacade, RequestFacade, ReportingResponseToolkit } from '../../types'; +import { + getRouteConfigFactoryReportingPre, + GetRouteConfigFactoryFn, + RouteConfigFactory, +} from './lib/route_config_factories'; import { HandlerErrorFunction, HandlerFunction } from './types'; const BASE_GENERATE = `${API_BASE_URL}/generate`; export function registerGenerateFromJobParams( - server: KbnServer, + server: ServerFacade, handler: HandlerFunction, handleError: HandlerErrorFunction ) { - const getRouteConfig = getRouteConfigFactoryReportingPre(server); + const getRouteConfig = () => { + const getOriginalRouteConfig: GetRouteConfigFactoryFn = getRouteConfigFactoryReportingPre( + server + ); + const routeConfigFactory: RouteConfigFactory = getOriginalRouteConfig( + ({ params: { exportType } }) => exportType + ); - // generate report - server.route({ - path: `${BASE_GENERATE}/{exportType}`, - method: 'POST', - config: { - ...getRouteConfig(request => request.params.exportType), + return { + ...routeConfigFactory, validate: { params: Joi.object({ exportType: Joi.string().required(), @@ -41,8 +46,15 @@ export function registerGenerateFromJobParams( jobParams: Joi.string().default(null), }).default(), }, - }, - handler: async (request: Request, h: ResponseToolkit) => { + }; + }; + + // generate report + server.route({ + path: `${BASE_GENERATE}/{exportType}`, + method: 'POST', + options: getRouteConfig(), + handler: async (request: RequestFacade, h: ReportingResponseToolkit) => { let jobParamsRison: string | null; if (request.payload) { @@ -73,11 +85,10 @@ export function registerGenerateFromJobParams( }, }); - // show error about GET method to user + // Get route to generation endpoint: show error about GET method to user server.route({ path: `${BASE_GENERATE}/{p*}`, method: 'GET', - config: getRouteConfig(), handler: () => { const err = boom.methodNotAllowed('GET is not allowed'); err.output.headers.allow = 'POST'; diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts index baadbc99e82f7..ec0a56f8de442 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject.ts @@ -4,41 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request, ResponseToolkit } from 'hapi'; import { get } from 'lodash'; - import { API_BASE_GENERATE_V1, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../common/constants'; -import { KbnServer } from '../../types'; +import { ServerFacade, RequestFacade, ReportingResponseToolkit } from '../../types'; import { HandlerErrorFunction, HandlerFunction, QueuedJobPayload } from './types'; -import { getRouteOptions } from './lib/route_config_factories'; +import { getRouteOptionsCsv } from './lib/route_config_factories'; import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request'; -/* - * 1. Build `jobParams` object: job data that execution will need to reference in various parts of the lifecycle - * 2. Pass the jobParams and other common params to `handleRoute`, a shared function to enqueue the job with the params - * 3. Ensure that details for a queued job were returned - */ -const getJobFromRouteHandler = async ( - handleRoute: HandlerFunction, - handleRouteError: HandlerErrorFunction, - request: Request, - h: ResponseToolkit -): Promise => { - let result: QueuedJobPayload; - try { - const jobParams = getJobParamsFromRequest(request, { isImmediate: false }); - result = await handleRoute(CSV_FROM_SAVEDOBJECT_JOB_TYPE, jobParams, request, h); - } catch (err) { - throw handleRouteError(CSV_FROM_SAVEDOBJECT_JOB_TYPE, err); - } - - if (get(result, 'source.job') == null) { - throw new Error(`The Export handler is expected to return a result with job info! ${result}`); - } - - return result; -}; - /* * This function registers API Endpoints for queuing Reporting jobs. The API inputs are: * - saved object type and ID @@ -49,18 +21,38 @@ const getJobFromRouteHandler = async ( * - local (transient) changes the user made to the saved object */ export function registerGenerateCsvFromSavedObject( - server: KbnServer, + server: ServerFacade, handleRoute: HandlerFunction, handleRouteError: HandlerErrorFunction ) { - const routeOptions = getRouteOptions(server); + const routeOptions = getRouteOptionsCsv(server); server.route({ path: `${API_BASE_GENERATE_V1}/csv/saved-object/{savedObjectType}:{savedObjectId}`, method: 'POST', options: routeOptions, - handler: async (request: Request, h: ResponseToolkit) => { - return getJobFromRouteHandler(handleRoute, handleRouteError, request, h); + handler: async (request: RequestFacade, h: ReportingResponseToolkit) => { + /* + * 1. Build `jobParams` object: job data that execution will need to reference in various parts of the lifecycle + * 2. Pass the jobParams and other common params to `handleRoute`, a shared function to enqueue the job with the params + * 3. Ensure that details for a queued job were returned + */ + + let result: QueuedJobPayload; + try { + const jobParams = getJobParamsFromRequest(request, { isImmediate: false }); + result = await handleRoute(CSV_FROM_SAVEDOBJECT_JOB_TYPE, jobParams, request, h); + } catch (err) { + throw handleRouteError(CSV_FROM_SAVEDOBJECT_JOB_TYPE, err); + } + + if (get(result, 'source.job') == null) { + throw new Error( + `The Export handler is expected to return a result with job info! ${result}` + ); + } + + return result; }, }); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts index 8321cf16820c0..557f7c3702038 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/generate_from_savedobject_immediate.ts @@ -4,24 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request, ResponseObject, ResponseToolkit } from 'hapi'; - import { API_BASE_GENERATE_V1 } from '../../common/constants'; import { createJobFactory, executeJobFactory } from '../../export_types/csv_from_savedobject'; import { - KbnServer, + ServerFacade, + RequestFacade, + ResponseFacade, + ReportingResponseToolkit, Logger, JobDocPayload, JobIDForImmediate, JobDocOutputExecuted, } from '../../types'; -import { getRouteOptions } from './lib/route_config_factories'; +import { getRouteOptionsCsv } from './lib/route_config_factories'; import { getJobParamsFromRequest } from '../../export_types/csv_from_savedobject/server/lib/get_job_params_from_request'; -interface KibanaResponse extends ResponseObject { - isBoom: boolean; -} - /* * This function registers API Endpoints for immediate Reporting jobs. The API inputs are: * - saved object type and ID @@ -32,10 +29,10 @@ interface KibanaResponse extends ResponseObject { * - local (transient) changes the user made to the saved object */ export function registerGenerateCsvFromSavedObjectImmediate( - server: KbnServer, + server: ServerFacade, parentLogger: Logger ) { - const routeOptions = getRouteOptions(server); + const routeOptions = getRouteOptionsCsv(server); /* * CSV export with the `immediate` option does not queue a job with Reporting's ESQueue to run the job async. Instead, this does: @@ -46,7 +43,7 @@ export function registerGenerateCsvFromSavedObjectImmediate( path: `${API_BASE_GENERATE_V1}/immediate/csv/saved-object/{savedObjectType}:{savedObjectId}`, method: 'POST', options: routeOptions, - handler: async (request: Request, h: ResponseToolkit) => { + handler: async (request: RequestFacade, h: ReportingResponseToolkit) => { const logger = parentLogger.clone(['savedobject-csv']); const jobParams = getJobParamsFromRequest(request, { isImmediate: true }); const createJobFn = createJobFactory(server); @@ -78,7 +75,7 @@ export function registerGenerateCsvFromSavedObjectImmediate( .type(jobOutputContentType); // Set header for buffer download, not streaming - const { isBoom } = response as KibanaResponse; + const { isBoom } = response as ResponseFacade; if (isBoom == null) { response.header('accept-ranges', 'none'); } diff --git a/x-pack/legacy/plugins/reporting/server/routes/index.ts b/x-pack/legacy/plugins/reporting/server/routes/index.ts index cbfd096e7100b..118d6b3d43c17 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/index.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/index.ts @@ -5,9 +5,8 @@ */ import boom from 'boom'; -import { Request, ResponseToolkit } from 'hapi'; import { API_BASE_URL } from '../../common/constants'; -import { KbnServer, Logger } from '../../types'; +import { ServerFacade, RequestFacade, ReportingResponseToolkit, Logger } from '../../types'; import { enqueueJobFactory } from '../lib/enqueue_job'; import { registerGenerateFromJobParams } from './generate_from_jobparams'; import { registerGenerateCsvFromSavedObject } from './generate_from_savedobject'; @@ -15,9 +14,10 @@ import { registerGenerateCsvFromSavedObjectImmediate } from './generate_from_sav import { registerJobs } from './jobs'; import { registerLegacy } from './legacy'; -export function registerRoutes(server: KbnServer, logger: Logger) { +export function registerRoutes(server: ServerFacade, logger: Logger) { const config = server.config(); const DOWNLOAD_BASE_URL = config.get('server.basePath') + `${API_BASE_URL}/jobs/download`; + // @ts-ignore const { errors: esErrors } = server.plugins.elasticsearch.getCluster('admin'); const enqueueJob = enqueueJobFactory(server); @@ -27,8 +27,8 @@ export function registerRoutes(server: KbnServer, logger: Logger) { async function handler( exportTypeId: string, jobParams: any, - request: Request, - h: ResponseToolkit + request: RequestFacade, + h: ReportingResponseToolkit ) { // @ts-ignore const user = request.pre.user; diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts index 1acc40fd0a55b..58a212aa0d7fb 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.ts @@ -5,10 +5,8 @@ */ import boom from 'boom'; -import { RequestQuery } from 'hapi'; -import { Request, ResponseToolkit } from 'hapi'; import { API_BASE_URL } from '../../common/constants'; -import { JobDoc, KbnServer } from '../../types'; +import { JobDoc, ServerFacade, RequestFacade, ReportingResponseToolkit } from '../../types'; // @ts-ignore import { jobsQueryFactory } from '../lib/jobs_query'; // @ts-ignore @@ -20,13 +18,7 @@ import { const MAIN_ENTRY = `${API_BASE_URL}/jobs`; -type ListQuery = RequestQuery & { - page: string; - size: string; - ids?: string; // optional field forbids us from extending RequestQuery -}; - -export function registerJobs(server: KbnServer) { +export function registerJobs(server: ServerFacade) { const jobsQuery = jobsQueryFactory(server); const getRouteConfig = getRouteConfigFactoryManagementPre(server); const getRouteConfigDownload = getRouteConfigFactoryDownloadPre(server); @@ -35,9 +27,9 @@ export function registerJobs(server: KbnServer) { server.route({ path: `${MAIN_ENTRY}/list`, method: 'GET', - config: getRouteConfig(), - handler: (request: Request) => { - const { page: queryPage, size: querySize, ids: queryIds } = request.query as ListQuery; + options: getRouteConfig(), + handler: (request: RequestFacade) => { + const { page: queryPage, size: querySize, ids: queryIds } = request.query; const page = parseInt(queryPage, 10) || 0; const size = Math.min(100, parseInt(querySize, 10) || 10); const jobIds = queryIds ? queryIds.split(',') : null; @@ -57,8 +49,8 @@ export function registerJobs(server: KbnServer) { server.route({ path: `${MAIN_ENTRY}/count`, method: 'GET', - config: getRouteConfig(), - handler: (request: Request) => { + options: getRouteConfig(), + handler: (request: RequestFacade) => { const results = jobsQuery.count(request.pre.management.jobTypes, request.pre.user); return results; }, @@ -68,8 +60,8 @@ export function registerJobs(server: KbnServer) { server.route({ path: `${MAIN_ENTRY}/output/{docId}`, method: 'GET', - config: getRouteConfig(), - handler: (request: Request) => { + options: getRouteConfig(), + handler: (request: RequestFacade) => { const { docId } = request.params; return jobsQuery.get(request.pre.user, docId, { includeContent: true }).then( @@ -94,8 +86,8 @@ export function registerJobs(server: KbnServer) { server.route({ path: `${MAIN_ENTRY}/info/{docId}`, method: 'GET', - config: getRouteConfig(), - handler: (request: Request) => { + options: getRouteConfig(), + handler: (request: RequestFacade) => { const { docId } = request.params; return jobsQuery.get(request.pre.user, docId).then( @@ -127,8 +119,8 @@ export function registerJobs(server: KbnServer) { server.route({ path: `${MAIN_ENTRY}/download/{docId}`, method: 'GET', - config: getRouteConfigDownload(), - handler: async (request: Request, h: ResponseToolkit) => { + options: getRouteConfigDownload(), + handler: async (request: RequestFacade, h: ReportingResponseToolkit) => { const { docId } = request.params; let response = await jobResponseHandler( diff --git a/x-pack/legacy/plugins/reporting/server/routes/legacy.ts b/x-pack/legacy/plugins/reporting/server/routes/legacy.ts index 24caf8003b7d7..011ac4a02bbf9 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/legacy.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/legacy.ts @@ -4,31 +4,34 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request, ResponseToolkit } from 'hapi'; import querystring from 'querystring'; import { API_BASE_URL } from '../../common/constants'; -import { KbnServer } from '../../types'; -import { getRouteConfigFactoryReportingPre } from './lib/route_config_factories'; +import { ServerFacade, RequestFacade, ReportingResponseToolkit } from '../../types'; +import { + getRouteConfigFactoryReportingPre, + GetRouteConfigFactoryFn, +} from './lib/route_config_factories'; import { HandlerErrorFunction, HandlerFunction } from './types'; -const getStaticFeatureConfig = (getRouteConfig: any, featureId: any) => +const getStaticFeatureConfig = (getRouteConfig: GetRouteConfigFactoryFn, featureId: string) => getRouteConfig(() => featureId); + const BASE_GENERATE = `${API_BASE_URL}/generate`; export function registerLegacy( - server: KbnServer, + server: ServerFacade, handler: HandlerFunction, handleError: HandlerErrorFunction ) { const getRouteConfig = getRouteConfigFactoryReportingPre(server); - function createLegacyPdfRoute({ path, objectType }: { path: string; objectType: any }) { + function createLegacyPdfRoute({ path, objectType }: { path: string; objectType: string }) { const exportTypeId = 'printablePdf'; server.route({ path, method: 'POST', - config: getStaticFeatureConfig(getRouteConfig, exportTypeId), - handler: async (request: Request, h: ResponseToolkit) => { + options: getStaticFeatureConfig(getRouteConfig, exportTypeId), + handler: async (request: RequestFacade, h: ReportingResponseToolkit) => { const message = `The following URL is deprecated and will stop working in the next major version: ${request.url.path}`; server.log(['warning', 'reporting', 'deprecation'], message); diff --git a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts index e09db6e536fee..29ded68d403c5 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/lib/route_config_factories.ts @@ -4,18 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; import Joi from 'joi'; -import { KbnServer } from '../../../types'; +import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; +import { ServerFacade, RequestFacade } from '../../../types'; // @ts-ignore import { authorizedUserPreRoutingFactory } from './authorized_user_pre_routing'; // @ts-ignore import { reportingFeaturePreRoutingFactory } from './reporting_feature_pre_routing'; -import { CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../common/constants'; const API_TAG = 'api'; -interface RouteConfigFactory { +export interface RouteConfigFactory { tags?: string[]; pre: any[]; response?: { @@ -23,10 +22,14 @@ interface RouteConfigFactory { }; } -type GetFeatureFunction = (request: Request) => any; +type GetFeatureFunction = (request: RequestFacade) => any; type PreRoutingFunction = (getFeatureId?: GetFeatureFunction) => any; -export function getRouteConfigFactoryReportingPre(server: KbnServer) { +export type GetRouteConfigFactoryFn = ( + getFeatureId?: GetFeatureFunction | undefined +) => RouteConfigFactory; + +export function getRouteConfigFactoryReportingPre(server: ServerFacade): GetRouteConfigFactoryFn { const authorizedUserPreRouting: PreRoutingFunction = authorizedUserPreRoutingFactory(server); const reportingFeaturePreRouting: PreRoutingFunction = reportingFeaturePreRoutingFactory(server); @@ -43,7 +46,7 @@ export function getRouteConfigFactoryReportingPre(server: KbnServer) { }; } -export function getRouteOptions(server: KbnServer) { +export function getRouteOptionsCsv(server: ServerFacade) { const getRouteConfig = getRouteConfigFactoryReportingPre(server); return { ...getRouteConfig(() => CSV_FROM_SAVEDOBJECT_JOB_TYPE), @@ -64,7 +67,7 @@ export function getRouteOptions(server: KbnServer) { }; } -export function getRouteConfigFactoryManagementPre(server: KbnServer) { +export function getRouteConfigFactoryManagementPre(server: ServerFacade): GetRouteConfigFactoryFn { const authorizedUserPreRouting = authorizedUserPreRoutingFactory(server); const reportingFeaturePreRouting = reportingFeaturePreRoutingFactory(server); const managementPreRouting = reportingFeaturePreRouting(() => 'management'); @@ -84,7 +87,7 @@ export function getRouteConfigFactoryManagementPre(server: KbnServer) { // TOC at the end of the PDF, but it's sending multiple cookies and causing our auth to fail with a 401. // Additionally, the range-request doesn't alleviate any performance issues on the server as the entire // download is loaded into memory. -export function getRouteConfigFactoryDownloadPre(server: KbnServer) { +export function getRouteConfigFactoryDownloadPre(server: ServerFacade): GetRouteConfigFactoryFn { const getManagementRouteConfig = getRouteConfigFactoryManagementPre(server); return (): RouteConfigFactory => ({ ...getManagementRouteConfig(), diff --git a/x-pack/legacy/plugins/reporting/server/routes/types.d.ts b/x-pack/legacy/plugins/reporting/server/routes/types.d.ts index 6004811d8a2b4..0b6a9708c7d1a 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/types.d.ts +++ b/x-pack/legacy/plugins/reporting/server/routes/types.d.ts @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request, ResponseToolkit } from 'hapi'; -import { JobDocPayload } from '../../types'; +import { RequestFacade, ReportingResponseToolkit, JobDocPayload } from '../../types'; export type HandlerFunction = ( exportType: any, jobParams: any, - request: Request, - h: ResponseToolkit + request: RequestFacade, + h: ReportingResponseToolkit ) => any; export type HandlerErrorFunction = (exportType: any, err: Error) => any; diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts index 63614a18e829b..226355f5edc61 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_server.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ import { memoize } from 'lodash'; -import { KbnServer } from '../types'; +import { ServerFacade } from '../types'; -export const createMockServer = ({ settings = {} }: any): KbnServer => { +export const createMockServer = ({ settings = {} }: any): ServerFacade => { const mockServer = { expose: () => { ' '; @@ -41,5 +41,5 @@ export const createMockServer = ({ settings = {} }: any): KbnServer => { return key in settings ? settings[key] : defaultSettings[key]; }); - return (mockServer as unknown) as KbnServer; + return (mockServer as unknown) as ServerFacade; }; diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 19c08e59400af..62f8286cdf364 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -4,14 +4,26 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Request } from 'hapi'; - -interface UiSettings { - get: (value: string) => string; +import { ResponseObject } from 'hapi'; +import { EventEmitter } from 'events'; +import { Legacy } from 'kibana'; +import { XPackMainPlugin } from '../xpack_main/xpack_main'; +import { ElasticsearchPlugin } from '../../../../src/legacy/core_plugins/elasticsearch'; +import { HeadlessChromiumDriverFactory } from './server/browsers/chromium/driver_factory'; +import { BrowserType } from './server/browsers/types'; + +type Job = EventEmitter & { id: string }; + +export interface ReportingPlugin { + queue: { + addJob: (type: string, payload: object, options: object) => Job; + }; + exportTypesRegistry: { + getById: (id: string) => ExportTypeDefinition; + getAll: () => ExportTypeDefinition[]; + }; + browserDriverFactory: HeadlessChromiumDriverFactory; } - -type SavedObjectClient = any; - export interface NetworkPolicyRule { allow: boolean; protocol: string; @@ -23,30 +35,61 @@ export interface NetworkPolicy { rules: NetworkPolicyRule[]; } -// these types shoud be in core kibana and are only here temporarily -export interface KbnServer { - info: { protocol: string }; - config: () => ConfigObject; - expose: () => void; - plugins: Record; - route: any; - log: any; - fieldFormatServiceFactory: (uiConfig: any) => any; - savedObjects: { - getScopedSavedObjectsClient: (fakeRequest: { - headers: object; - getBasePath: () => string; - }) => SavedObjectClient; +// Tracks which parts of the legacy plugin system are being used +export type ServerFacade = Legacy.Server & { + plugins: { + reporting?: ReportingPlugin; + xpack_main?: XPackMainPlugin & { + status?: any; + }; }; - uiSettingsServiceFactory: ({ - savedObjectsClient, - }: { - savedObjectsClient: SavedObjectClient; - }) => UiSettings; +}; + +interface ListQuery { + page: string; + size: string; + ids?: string; // optional field forbids us from extending RequestQuery +} +interface GenerateQuery { + jobParams: string; +} +interface GenerateExportTypePayload { + jobParams: string; +} +interface DownloadParams { + docId: string; } -export interface ConfigObject { - get: (path?: string) => any; +// Tracks which parts of the legacy plugin system are being used +interface ReportingRequest { + query: ListQuery & GenerateQuery; + params: DownloadParams; + payload: GenerateExportTypePayload; + pre: { + management: { + jobTypes: any; + }; + user: any; + }; +} + +export type RequestFacade = ReportingRequest & Legacy.Request; + +export type ResponseFacade = ResponseObject & { + isBoom: boolean; +}; + +export type ReportingResponseToolkit = Legacy.ResponseToolkit; + +export interface CaptureConfig { + browser: { + type: BrowserType; + autoDownload: boolean; + chromium: BrowserConfig; + }; + maxAttempts: number; + networkPolicy: NetworkPolicy; + loadDelay: number; } export interface BrowserConfig { @@ -61,6 +104,14 @@ export interface BrowserConfig { }; } +export interface QueueConfig { + indexInterval: string; + pollEnabled: boolean; + pollInterval: number; + pollIntervalErrorMultiplier: number; + timeout: number; +} + export interface ElementPosition { boundingClientRect: { // modern browsers support x/y, but older ones don't @@ -152,7 +203,7 @@ export interface ESQueueWorker { export type ESQueueCreateJobFn = ( jobParams: object, headers: ConditionalHeaders, - request: Request + request: RequestFacade ) => Promise; export type ESQueueWorkerExecuteFn = (jobId: string, job: JobDoc, cancellationToken: any) => void; @@ -161,7 +212,7 @@ export type JobIDForImmediate = null; export type ImmediateExecuteFn = ( jobId: JobIDForImmediate, jobDocPayload: JobDocPayload, - request: Request + request: RequestFacade ) => Promise; export interface ESQueueWorkerOptions { @@ -179,9 +230,9 @@ export interface ESQueueInstance { ) => ESQueueWorker; } -export type CreateJobFactory = (server: KbnServer) => ESQueueCreateJobFn; -export type ExecuteJobFactory = (server: KbnServer) => ESQueueWorkerExecuteFn; -export type ExecuteImmediateJobFactory = (server: KbnServer) => ImmediateExecuteFn; +export type CreateJobFactory = (server: ServerFacade) => ESQueueCreateJobFn; +export type ExecuteJobFactory = (server: ServerFacade) => ESQueueWorkerExecuteFn; +export type ExecuteImmediateJobFactory = (server: ServerFacade) => ImmediateExecuteFn; export interface ExportTypeDefinition { id: string; @@ -193,13 +244,6 @@ export interface ExportTypeDefinition { validLicenses: string[]; } -// Note: this seems to be nearly a duplicate of ExportTypeDefinition -export interface ExportType { - jobType: string; - createJobFactory: any; - executeJobFactory: (server: KbnServer) => ESQueueWorkerExecuteFn; -} - export interface ExportTypesRegistry { register: (exportTypeDefinition: ExportTypeDefinition) => void; } From c718972d11c27477af2cdb7a9a49a44a8b697e9b Mon Sep 17 00:00:00 2001 From: friol Date: Wed, 23 Oct 2019 23:56:50 +0200 Subject: [PATCH 098/191] Add ability to replace any panel in edit mode on the fly (#45095) * First version of change view functionality * Adds the 'replace view' functionality to dashboard edit mode * Fixed type_check errors * Make action part of dashboard_embeddable_container * Fixed import paths for type check errors * Fixed i18n errors * Renamed action to 'Replace panel' and adjusted jest tests to pass type check * test: add functional tests Closes #43900 --- .../public/np_ready/public/index.ts | 2 +- .../np_ready/public/lib/actions/index.ts | 1 + .../lib/actions/open_replace_panel_flyout.tsx | 56 +++++++ .../lib/actions/replace_panel_action.test.tsx | 129 ++++++++++++++++ .../lib/actions/replace_panel_action.tsx | 94 +++++++++++ .../lib/actions/replace_panel_flyout.tsx | 146 ++++++++++++++++++ .../public/np_ready/public/plugin.ts | 10 +- .../apps/dashboard/panel_controls.js | 77 ++++++++- .../functional/page_objects/dashboard_page.js | 3 +- test/functional/services/dashboard/index.js | 1 + .../services/dashboard/panel_actions.js | 21 +++ .../services/dashboard/replace_panel.js | 102 ++++++++++++ test/functional/services/index.ts | 2 + 13 files changed, 636 insertions(+), 8 deletions(-) create mode 100644 src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/open_replace_panel_flyout.tsx create mode 100644 src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.test.tsx create mode 100644 src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.tsx create mode 100644 src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_flyout.tsx create mode 100644 test/functional/services/dashboard/replace_panel.js diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/index.ts b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/index.ts index cbbbd41827853..1dad1b488590e 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/index.ts +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/index.ts @@ -17,7 +17,7 @@ * under the License. */ -import { PluginInitializerContext } from 'kibana/public'; +import { PluginInitializerContext } from '../../../../../../core/public'; import { DashboardEmbeddableContainerPublicPlugin } from './plugin'; export * from './lib'; diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/index.ts b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/index.ts index b0707610cf21b..6c0db82fbbc5b 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/index.ts +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/index.ts @@ -18,3 +18,4 @@ */ export { ExpandPanelAction, EXPAND_PANEL_ACTION } from './expand_panel_action'; +export { ReplacePanelAction, REPLACE_PANEL_ACTION } from './replace_panel_action'; diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/open_replace_panel_flyout.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/open_replace_panel_flyout.tsx new file mode 100644 index 0000000000000..b6652caf3ab83 --- /dev/null +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/open_replace_panel_flyout.tsx @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { CoreStart } from 'src/core/public'; +import { ReplacePanelFlyout } from './replace_panel_flyout'; + +import { + IEmbeddable, + EmbeddableInput, + EmbeddableOutput, +} from '../../../../../../embeddable_api/public/np_ready/public'; + +import { IContainer } from '../../../../../../embeddable_api/public/np_ready/public'; +import { NotificationsStart } from '../../../../../../../../core/public'; + +export async function openReplacePanelFlyout(options: { + embeddable: IContainer; + core: CoreStart; + savedObjectFinder: React.ComponentType; + notifications: NotificationsStart; + panelToRemove: IEmbeddable; +}) { + const { embeddable, core, panelToRemove, savedObjectFinder, notifications } = options; + const flyoutSession = core.overlays.openFlyout( + { + if (flyoutSession) { + flyoutSession.close(); + } + }} + panelToRemove={panelToRemove} + savedObjectsFinder={savedObjectFinder} + notifications={notifications} + />, + { + 'data-test-subj': 'replacePanelFlyout', + } + ); +} diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.test.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.test.tsx new file mode 100644 index 0000000000000..e1d2e3609570c --- /dev/null +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.test.tsx @@ -0,0 +1,129 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { isErrorEmbeddable, EmbeddableFactory } from '../embeddable_api'; +import { ReplacePanelAction } from './replace_panel_action'; +import { DashboardContainer } from '../embeddable'; +import { getSampleDashboardInput, getSampleDashboardPanel } from '../test_helpers'; +import { + CONTACT_CARD_EMBEDDABLE, + ContactCardEmbeddableFactory, + ContactCardEmbeddable, + ContactCardEmbeddableInput, + ContactCardEmbeddableOutput, +} from '../../../../../../embeddable_api/public/np_ready/public/lib/test_samples'; +import { DashboardOptions } from '../embeddable/dashboard_container_factory'; + +const embeddableFactories = new Map(); +embeddableFactories.set( + CONTACT_CARD_EMBEDDABLE, + new ContactCardEmbeddableFactory({} as any, (() => null) as any, {} as any) +); + +let container: DashboardContainer; +let embeddable: ContactCardEmbeddable; + +beforeEach(async () => { + const options: DashboardOptions = { + ExitFullScreenButton: () => null, + SavedObjectFinder: () => null, + application: {} as any, + embeddable: { + getEmbeddableFactory: (id: string) => embeddableFactories.get(id)!, + } as any, + inspector: {} as any, + notifications: {} as any, + overlays: {} as any, + savedObjectMetaData: {} as any, + uiActions: {} as any, + }; + const input = getSampleDashboardInput({ + panels: { + '123': getSampleDashboardPanel({ + explicitInput: { firstName: 'Sam', id: '123' }, + type: CONTACT_CARD_EMBEDDABLE, + }), + }, + }); + container = new DashboardContainer(input, options); + + const contactCardEmbeddable = await container.addNewEmbeddable< + ContactCardEmbeddableInput, + ContactCardEmbeddableOutput, + ContactCardEmbeddable + >(CONTACT_CARD_EMBEDDABLE, { + firstName: 'Kibana', + }); + + if (isErrorEmbeddable(contactCardEmbeddable)) { + throw new Error('Failed to create embeddable'); + } else { + embeddable = contactCardEmbeddable; + } +}); + +test('Executes the replace panel action', async () => { + let core: any; + let SavedObjectFinder: any; + let notifications: any; + const action = new ReplacePanelAction(core, SavedObjectFinder, notifications); + action.execute({ embeddable }); +}); + +test('Is not compatible when embeddable is not in a dashboard container', async () => { + let core: any; + let SavedObjectFinder: any; + let notifications: any; + const action = new ReplacePanelAction(core, SavedObjectFinder, notifications); + expect( + await action.isCompatible({ + embeddable: new ContactCardEmbeddable( + { firstName: 'sue', id: '123' }, + { execAction: (() => null) as any } + ), + }) + ).toBe(false); +}); + +test('Execute throws an error when called with an embeddable not in a parent', async () => { + let core: any; + let SavedObjectFinder: any; + let notifications: any; + const action = new ReplacePanelAction(core, SavedObjectFinder, notifications); + async function check() { + await action.execute({ embeddable: container }); + } + await expect(check()).rejects.toThrow(Error); +}); + +test('Returns title', async () => { + let core: any; + let SavedObjectFinder: any; + let notifications: any; + const action = new ReplacePanelAction(core, SavedObjectFinder, notifications); + expect(action.getDisplayName({ embeddable })).toBeDefined(); +}); + +test('Returns an icon', async () => { + let core: any; + let SavedObjectFinder: any; + let notifications: any; + const action = new ReplacePanelAction(core, SavedObjectFinder, notifications); + expect(action.getIconType({ embeddable })).toBeDefined(); +}); diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.tsx new file mode 100644 index 0000000000000..f36efc498b15f --- /dev/null +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_action.tsx @@ -0,0 +1,94 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { CoreStart } from 'src/core/public'; + +import { IEmbeddable, ViewMode } from '../../../../../../embeddable_api/public/np_ready/public'; +import { DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '../embeddable'; +import { + IAction, + IncompatibleActionError, +} from '../../../../../../../../plugins/ui_actions/public'; +import { NotificationsStart } from '../../../../../../../../core/public'; +import { openReplacePanelFlyout } from './open_replace_panel_flyout'; + +export const REPLACE_PANEL_ACTION = 'replacePanel'; + +function isDashboard(embeddable: IEmbeddable): embeddable is DashboardContainer { + return embeddable.type === DASHBOARD_CONTAINER_TYPE; +} + +interface ActionContext { + embeddable: IEmbeddable; +} + +export class ReplacePanelAction implements IAction { + public readonly type = REPLACE_PANEL_ACTION; + public readonly id = REPLACE_PANEL_ACTION; + public order = 11; + + constructor( + private core: CoreStart, + private savedobjectfinder: React.ComponentType, + private notifications: NotificationsStart + ) {} + + public getDisplayName({ embeddable }: ActionContext) { + if (!embeddable.parent || !isDashboard(embeddable.parent)) { + throw new IncompatibleActionError(); + } + return i18n.translate('dashboardEmbeddableContainer.panel.removePanel.replacePanel', { + defaultMessage: 'Replace panel', + }); + } + + public getIconType({ embeddable }: ActionContext) { + if (!embeddable.parent || !isDashboard(embeddable.parent)) { + throw new IncompatibleActionError(); + } + return 'kqlOperand'; + } + + public async isCompatible({ embeddable }: ActionContext) { + if (embeddable.getInput().viewMode) { + if (embeddable.getInput().viewMode === ViewMode.VIEW) { + return false; + } + } + + return Boolean(embeddable.parent && isDashboard(embeddable.parent)); + } + + public async execute({ embeddable }: ActionContext) { + if (!embeddable.parent || !isDashboard(embeddable.parent)) { + throw new IncompatibleActionError(); + } + + const view = embeddable; + const dash = embeddable.parent; + openReplacePanelFlyout({ + embeddable: dash, + core: this.core, + savedObjectFinder: this.savedobjectfinder, + notifications: this.notifications, + panelToRemove: view, + }); + } +} diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_flyout.tsx b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_flyout.tsx new file mode 100644 index 0000000000000..0e738556372ce --- /dev/null +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/lib/actions/replace_panel_flyout.tsx @@ -0,0 +1,146 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import React from 'react'; + +import { NotificationsStart } from 'src/core/public'; +import { DashboardPanelState } from 'src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public'; + +import { + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutHeader, + EuiTitle, + EuiGlobalToastListToast as Toast, +} from '@elastic/eui'; + +import { IContainer } from '../../../../../../embeddable_api/public/np_ready/public'; +import { + IEmbeddable, + EmbeddableInput, + EmbeddableOutput, +} from '../../../../../../embeddable_api/public/np_ready/public'; + +import { start } from '../../../../../../embeddable_api/public/np_ready/public/legacy'; + +interface Props { + container: IContainer; + savedObjectsFinder: React.ComponentType; + onClose: () => void; + notifications: NotificationsStart; + panelToRemove: IEmbeddable; +} + +export class ReplacePanelFlyout extends React.Component { + private lastToast: Toast = { + id: 'panelReplaceToast', + }; + + constructor(props: Props) { + super(props); + } + + public showToast = (name: string) => { + // To avoid the clutter of having toast messages cover flyout + // close previous toast message before creating a new one + if (this.lastToast) { + this.props.notifications.toasts.remove(this.lastToast); + } + + this.lastToast = this.props.notifications.toasts.addSuccess({ + title: i18n.translate( + 'dashboardEmbeddableContainer.addPanel.savedObjectAddedToContainerSuccessMessageTitle', + { + defaultMessage: '{savedObjectName} was added', + values: { + savedObjectName: name, + }, + } + ), + 'data-test-subj': 'addObjectToContainerSuccess', + }); + }; + + public onReplacePanel = async (id: string, type: string, name: string) => { + const originalPanels = this.props.container.getInput().panels; + const filteredPanels = { ...originalPanels }; + + const nnw = (filteredPanels[this.props.panelToRemove.id] as DashboardPanelState).gridData.w; + const nnh = (filteredPanels[this.props.panelToRemove.id] as DashboardPanelState).gridData.h; + const nnx = (filteredPanels[this.props.panelToRemove.id] as DashboardPanelState).gridData.x; + const nny = (filteredPanels[this.props.panelToRemove.id] as DashboardPanelState).gridData.y; + + // add the new view + const newObj = await this.props.container.addSavedObjectEmbeddable(type, id); + + const finalPanels = this.props.container.getInput().panels; + (finalPanels[newObj.id] as DashboardPanelState).gridData.w = nnw; + (finalPanels[newObj.id] as DashboardPanelState).gridData.h = nnh; + (finalPanels[newObj.id] as DashboardPanelState).gridData.x = nnx; + (finalPanels[newObj.id] as DashboardPanelState).gridData.y = nny; + + // delete the old view + delete finalPanels[this.props.panelToRemove.id]; + + // apply changes + this.props.container.updateInput(finalPanels); + this.props.container.reload(); + + this.showToast(name); + this.props.onClose(); + }; + + public render() { + const SavedObjectFinder = this.props.savedObjectsFinder; + const savedObjectsFinder = ( + + Boolean(embeddableFactory.savedObjectMetaData) && !embeddableFactory.isContainerType + ) + .map(({ savedObjectMetaData }) => savedObjectMetaData as any)} + showFilter={true} + onChoose={this.onReplacePanel} + /> + ); + + const panelToReplace = 'Replace panel ' + this.props.panelToRemove.getTitle() + ' with:'; + + return ( + + + +

+ {panelToReplace} +

+
+
+ {savedObjectsFinder} +
+ ); + } +} diff --git a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts index 3d243ab3aa37a..bb18d109b0de7 100644 --- a/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public/plugin.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { IUiActionsSetup, IUiActionsStart } from '../../../../../../plugins/ui_actions/public'; import { CONTEXT_MENU_TRIGGER, Plugin as EmbeddablePlugin } from './lib/embeddable_api'; -import { ExpandPanelAction, DashboardContainerFactory } from './lib'; +import { ExpandPanelAction, ReplacePanelAction, DashboardContainerFactory } from './lib'; import { Start as InspectorStartContract } from '../../../../../../plugins/inspector/public'; interface SetupDependencies { @@ -55,6 +55,14 @@ export class DashboardEmbeddableContainerPublicPlugin const { application, notifications, overlays } = core; const { embeddable, inspector, __LEGACY, uiActions } = plugins; + const changeViewAction = new ReplacePanelAction( + core, + __LEGACY.SavedObjectFinder, + notifications + ); + uiActions.registerAction(changeViewAction); + uiActions.attachAction(CONTEXT_MENU_TRIGGER, changeViewAction.id); + const factory = new DashboardContainerFactory({ application, notifications, diff --git a/test/functional/apps/dashboard/panel_controls.js b/test/functional/apps/dashboard/panel_controls.js index b67e1dd7b2eb1..063ad1f79efae 100644 --- a/test/functional/apps/dashboard/panel_controls.js +++ b/test/functional/apps/dashboard/panel_controls.js @@ -19,7 +19,7 @@ import expect from '@kbn/expect'; -import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; +import { PIE_CHART_VIS_NAME, AREA_CHART_VIS_NAME, LINE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; import { VisualizeConstants } from '../../../../src/legacy/core_plugins/kibana/public/visualize/visualize_constants'; @@ -28,6 +28,8 @@ export default function ({ getService, getPageObjects }) { const browser = getService('browser'); const dashboardPanelActions = getService('dashboardPanelActions'); const dashboardAddPanel = getService('dashboardAddPanel'); + const dashboardReplacePanel = getService('dashboardReplacePanel'); + const dashboardVisualizations = getService('dashboardVisualizations'); const renderable = getService('renderable'); const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'discover']); const dashboardName = 'Dashboard Panel Controls Test'; @@ -44,6 +46,62 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.gotoDashboardLandingPage(); }); + describe('visualization object replace flyout', () => { + let intialDimensions; + before(async () => { + await PageObjects.dashboard.clickNewDashboard(); + await PageObjects.dashboard.setTimepickerInHistoricalDataRange(); + await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); + await dashboardAddPanel.addVisualization(LINE_CHART_VIS_NAME); + intialDimensions = await PageObjects.dashboard.getPanelDimensions(); + }); + + after(async function () { + await PageObjects.dashboard.gotoDashboardLandingPage(); + }); + + it('replaces old panel with selected panel', async () => { + await dashboardPanelActions.replacePanelByTitle(PIE_CHART_VIS_NAME); + await dashboardReplacePanel.replaceEmbeddable(AREA_CHART_VIS_NAME); + await PageObjects.header.waitUntilLoadingHasFinished(); + const panelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(panelTitles.length).to.be(2); + expect(panelTitles[0]).to.be(AREA_CHART_VIS_NAME); + }); + + it('replaces selected visualization with old dimensions', async () => { + const newDimensions = await PageObjects.dashboard.getPanelDimensions(); + expect(intialDimensions[0]).to.eql(newDimensions[0]); + }); + + it('replaced panel persisted correctly when dashboard is hard refreshed', async () => { + const currentUrl = await browser.getCurrentUrl(); + await browser.get(currentUrl, true); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + const panelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(panelTitles.length).to.be(2); + expect(panelTitles[0]).to.be(AREA_CHART_VIS_NAME); + }); + + it('replaced panel with saved search', async () => { + const replacedSearch = 'replaced saved search'; + await dashboardVisualizations.createSavedSearch({ name: replacedSearch, fields: ['bytes', 'agent'] }); + await PageObjects.header.clickDashboard(); + const inViewMode = await PageObjects.dashboard.getIsInViewMode(); + if (inViewMode) { + await PageObjects.dashboard.switchToEditMode(); + } + await dashboardPanelActions.replacePanelByTitle(AREA_CHART_VIS_NAME); + await dashboardReplacePanel.replaceEmbeddable(replacedSearch, 'search'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.dashboard.waitForRenderComplete(); + const panelTitles = await PageObjects.dashboard.getPanelTitles(); + expect(panelTitles.length).to.be(2); + expect(panelTitles[0]).to.be(replacedSearch); + }); + }); + describe('panel edit controls', function () { before(async () => { await PageObjects.dashboard.clickNewDashboard(); @@ -67,6 +125,7 @@ export default function ({ getService, getPageObjects }) { await dashboardPanelActions.openContextMenu(); await dashboardPanelActions.expectExistsEditPanelAction(); + await dashboardPanelActions.expectExistsReplacePanelAction(); await dashboardPanelActions.expectExistsRemovePanelAction(); }); @@ -80,6 +139,7 @@ export default function ({ getService, getPageObjects }) { await dashboardPanelActions.openContextMenu(); await dashboardPanelActions.expectExistsEditPanelAction(); + await dashboardPanelActions.expectExistsReplacePanelAction(); await dashboardPanelActions.expectExistsRemovePanelAction(); // Get rid of the timestamp in the url. @@ -94,6 +154,7 @@ export default function ({ getService, getPageObjects }) { await dashboardPanelActions.clickExpandPanelToggle(); await dashboardPanelActions.openContextMenu(); await dashboardPanelActions.expectMissingEditPanelAction(); + await dashboardPanelActions.expectMissingReplacePanelAction(); await dashboardPanelActions.expectMissingRemovePanelAction(); }); @@ -101,6 +162,7 @@ export default function ({ getService, getPageObjects }) { await PageObjects.dashboard.switchToEditMode(); await dashboardPanelActions.openContextMenu(); await dashboardPanelActions.expectExistsEditPanelAction(); + await dashboardPanelActions.expectExistsReplacePanelAction(); await dashboardPanelActions.expectMissingRemovePanelAction(); await dashboardPanelActions.clickExpandPanelToggle(); }); @@ -126,13 +188,18 @@ export default function ({ getService, getPageObjects }) { }); describe('saved search object edit menu', () => { + const searchName = 'my search'; before(async () => { await PageObjects.header.clickDiscover(); - await PageObjects.discover.clickFieldListItemAdd('bytes'); - await PageObjects.discover.saveSearch('my search'); + await PageObjects.discover.clickNewSearchButton(); + await dashboardVisualizations.createSavedSearch({ name: searchName, fields: ['bytes'] }); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.header.clickDashboard(); - await dashboardAddPanel.addSavedSearch('my search'); + const inViewMode = await PageObjects.dashboard.getIsInViewMode(); + if (inViewMode) { + await PageObjects.dashboard.switchToEditMode(); + } + await dashboardAddPanel.addSavedSearch(searchName); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be(1); @@ -143,7 +210,7 @@ export default function ({ getService, getPageObjects }) { await dashboardPanelActions.clickEdit(); await PageObjects.header.waitUntilLoadingHasFinished(); const queryName = await PageObjects.discover.getCurrentQueryName(); - expect(queryName).to.be('my search'); + expect(queryName).to.be(searchName); }); it('deletes the saved search when delete link is clicked', async () => { diff --git a/test/functional/page_objects/dashboard_page.js b/test/functional/page_objects/dashboard_page.js index 4f078d4b7a438..ca141114f976d 100644 --- a/test/functional/page_objects/dashboard_page.js +++ b/test/functional/page_objects/dashboard_page.js @@ -22,6 +22,7 @@ import { DashboardConstants } from '../../../src/legacy/core_plugins/kibana/publ export const PIE_CHART_VIS_NAME = 'Visualization PieChart'; export const AREA_CHART_VIS_NAME = 'Visualization漢字 AreaChart'; +export const LINE_CHART_VIS_NAME = 'Visualization漢字 LineChart'; export function DashboardPageProvider({ getService, getPageObjects }) { const log = getService('log'); @@ -499,7 +500,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) { { name: 'Visualization☺ VerticalBarChart', description: 'VerticalBarChart' }, { name: AREA_CHART_VIS_NAME, description: 'AreaChart' }, { name: 'Visualization☺漢字 DataTable', description: 'DataTable' }, - { name: 'Visualization漢字 LineChart', description: 'LineChart' }, + { name: LINE_CHART_VIS_NAME, description: 'LineChart' }, { name: 'Visualization TileMap', description: 'TileMap' }, { name: 'Visualization MetricChart', description: 'MetricChart' } ]; diff --git a/test/functional/services/dashboard/index.js b/test/functional/services/dashboard/index.js index b2de690157535..bb9b861682907 100644 --- a/test/functional/services/dashboard/index.js +++ b/test/functional/services/dashboard/index.js @@ -20,5 +20,6 @@ export { DashboardVisualizationProvider } from './visualizations'; export { DashboardExpectProvider } from './expectations'; export { DashboardAddPanelProvider } from './add_panel'; +export { DashboardReplacePanelProvider } from './replace_panel'; export { DashboardPanelActionsProvider } from './panel_actions'; diff --git a/test/functional/services/dashboard/panel_actions.js b/test/functional/services/dashboard/panel_actions.js index b7327f4af6d17..6826ea1ff1715 100644 --- a/test/functional/services/dashboard/panel_actions.js +++ b/test/functional/services/dashboard/panel_actions.js @@ -19,6 +19,7 @@ const REMOVE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-deletePanel'; const EDIT_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-editPanel'; +const REPLACE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-replacePanel'; const TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-togglePanel'; const CUSTOMIZE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-CUSTOMIZE_PANEL_ACTION_ID'; const OPEN_CONTEXT_MENU_ICON_DATA_TEST_SUBJ = 'embeddablePanelToggleMenuIcon'; @@ -87,6 +88,16 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) { await testSubjects.click(CUSTOMIZE_PANEL_DATA_TEST_SUBJ); } + async replacePanelByTitle(title) { + log.debug(`replacePanel(${title})`); + let panelOptions = null; + if (title) { + panelOptions = await this.getPanelHeading(title); + } + await this.openContextMenu(panelOptions); + await testSubjects.click(REPLACE_PANEL_DATA_TEST_SUBJ); + } + async openInspectorByTitle(title) { const header = await this.getPanelHeading(title); await this.openInspector(header); @@ -112,11 +123,21 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) { await testSubjects.existOrFail(EDIT_PANEL_DATA_TEST_SUBJ); } + async expectExistsReplacePanelAction() { + log.debug('expectExistsEditPanelAction'); + await testSubjects.existOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); + } + async expectMissingEditPanelAction() { log.debug('expectMissingEditPanelAction'); await testSubjects.missingOrFail(EDIT_PANEL_DATA_TEST_SUBJ); } + async expectMissingReplacePanelAction() { + log.debug('expectMissingEditPanelAction'); + await testSubjects.missingOrFail(REPLACE_PANEL_DATA_TEST_SUBJ); + } + async expectExistsToggleExpandAction() { log.debug('expectExistsToggleExpandAction'); await testSubjects.existOrFail(TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ); diff --git a/test/functional/services/dashboard/replace_panel.js b/test/functional/services/dashboard/replace_panel.js new file mode 100644 index 0000000000000..b3ea6f9cf21ed --- /dev/null +++ b/test/functional/services/dashboard/replace_panel.js @@ -0,0 +1,102 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +export function DashboardReplacePanelProvider({ getService }) { + const log = getService('log'); + const testSubjects = getService('testSubjects'); + const flyout = getService('flyout'); + + return new class DashboardReplacePanel { + async toggleFilterPopover() { + log.debug('DashboardReplacePanel.toggleFilter'); + await testSubjects.click('savedObjectFinderFilterButton'); + } + + async toggleFilter(type) { + log.debug(`DashboardReplacePanel.replaceToFilter(${type})`); + await this.waitForListLoading(); + await this.toggleFilterPopover(); + await testSubjects.click(`savedObjectFinderFilter-${type}`); + await this.toggleFilterPopover(); + } + + async isReplacePanelOpen() { + log.debug('DashboardReplacePanel.isReplacePanelOpen'); + return await testSubjects.exists('dashboardReplacePanel'); + } + + async ensureReplacePanelIsShowing() { + log.debug('DashboardReplacePanel.ensureReplacePanelIsShowing'); + const isOpen = await this.isReplacePanelOpen(); + if (!isOpen) { + throw new Error('Replace panel is not open, trying again.'); + } + } + + async waitForListLoading() { + await testSubjects.waitForDeleted('savedObjectFinderLoadingIndicator'); + } + + async closeReplacePanel() { + await flyout.ensureClosed('dashboardReplacePanel'); + } + + async replaceSavedSearch(searchName) { + return this.replaceEmbeddable(searchName, 'search'); + } + + async replaceSavedSearches(searches) { + for (const name of searches) { + await this.replaceSavedSearch(name); + } + } + + async replaceVisualization(vizName) { + return this.replaceEmbeddable(vizName, 'visualization'); + } + + async replaceEmbeddable(embeddableName, embeddableType) { + log.debug(`DashboardReplacePanel.replaceEmbeddable, name: ${embeddableName}, type: ${embeddableType}`); + await this.ensureReplacePanelIsShowing(); + if (embeddableType) { + await this.toggleFilter(embeddableType); + } + await this.filterEmbeddableNames(`"${embeddableName.replace('-', ' ')}"`); + await testSubjects.click(`savedObjectTitle${embeddableName.split(' ').join('-')}`); + await testSubjects.exists('addObjectToDashboardSuccess'); + await this.closeReplacePanel(); + return embeddableName; + } + + async filterEmbeddableNames(name) { + // The search input field may be disabled while the table is loading so wait for it + await this.waitForListLoading(); + await testSubjects.setValue('savedObjectFinderSearchInput', name); + await this.waitForListLoading(); + } + + async panelReplaceLinkExists(name) { + log.debug(`DashboardReplacePanel.panelReplaceLinkExists(${name})`); + await this.ensureReplacePanelIsShowing(); + await this.filterEmbeddableNames(`"${name}"`); + return await testSubjects.exists(`savedObjectTitle${name.split(' ').join('-')}`); + } + }; +} diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index 2566c3c87334c..6098e9931f299 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -24,6 +24,7 @@ import { BrowserProvider } from './browser'; import { ComboBoxProvider } from './combo_box'; import { DashboardAddPanelProvider, + DashboardReplacePanelProvider, DashboardExpectProvider, DashboardPanelActionsProvider, DashboardVisualizationProvider, @@ -66,6 +67,7 @@ export const services = { failureDebugging: FailureDebuggingProvider, visualizeListingTable: VisualizeListingTableProvider, dashboardAddPanel: DashboardAddPanelProvider, + dashboardReplacePanel: DashboardReplacePanelProvider, dashboardPanelActions: DashboardPanelActionsProvider, flyout: FlyoutProvider, comboBox: ComboBoxProvider, From b54c1a1d2be4ab4b91477b13b313cbbbb2ec5796 Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 23 Oct 2019 15:08:57 -0700 Subject: [PATCH 099/191] download node from our proxy-cache (#49081) * download node from our proxy-cache * download node with axios to support redirects * fix test assertion now that we're using axios --- .../build/tasks/nodejs/__tests__/download.js | 2 +- src/dev/build/tasks/nodejs/download.js | 17 ++++++++++------- .../build/tasks/nodejs/node_download_info.js | 2 +- src/dev/build/tasks/nodejs/node_shasums.test.ts | 4 +++- src/dev/build/tasks/nodejs/node_shasums.ts | 2 +- src/dev/ci_setup/setup_env.sh | 4 ++-- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/dev/build/tasks/nodejs/__tests__/download.js b/src/dev/build/tasks/nodejs/__tests__/download.js index 551773a6f6325..c76ff15b89289 100644 --- a/src/dev/build/tasks/nodejs/__tests__/download.js +++ b/src/dev/build/tasks/nodejs/__tests__/download.js @@ -196,7 +196,7 @@ describe('src/dev/build/tasks/nodejs/download', () => { } catch (error) { expect(error) .to.have.property('message') - .contain('Unexpected status code 500'); + .contain('Request failed with status code 500'); expect(reqCount).to.be(6); } }); diff --git a/src/dev/build/tasks/nodejs/download.js b/src/dev/build/tasks/nodejs/download.js index 48313c0911c24..0a030aced0d42 100644 --- a/src/dev/build/tasks/nodejs/download.js +++ b/src/dev/build/tasks/nodejs/download.js @@ -22,7 +22,7 @@ import { dirname } from 'path'; import chalk from 'chalk'; import { createHash } from 'crypto'; -import wreck from '@hapi/wreck'; +import Axios from 'axios'; import { mkdirp } from '../../lib'; @@ -51,21 +51,24 @@ export async function download(options) { try { log.debug(`Attempting download of ${url}`, chalk.dim(sha256)); - const response = await wreck.request('GET', url); + const response = await Axios.request({ + url: url, + responseType: 'stream' + }); - if (response.statusCode !== 200) { - throw new Error(`Unexpected status code ${response.statusCode} when downloading ${url}`); + if (response.status !== 200) { + throw new Error(`Unexpected status code ${response.status} when downloading ${url}`); } const hash = createHash('sha256'); await new Promise((resolve, reject) => { - response.on('data', chunk => { + response.data.on('data', chunk => { hash.update(chunk); writeSync(fileHandle, chunk); }); - response.on('error', reject); - response.on('end', resolve); + response.data.on('error', reject); + response.data.on('end', resolve); }); const downloadedSha256 = hash.digest('hex'); diff --git a/src/dev/build/tasks/nodejs/node_download_info.js b/src/dev/build/tasks/nodejs/node_download_info.js index 7c4fd5fde7bed..33ffd042d85a3 100644 --- a/src/dev/build/tasks/nodejs/node_download_info.js +++ b/src/dev/build/tasks/nodejs/node_download_info.js @@ -27,7 +27,7 @@ export function getNodeDownloadInfo(config, platform) { ? 'win-x64/node.exe' : `node-v${version}-${arch}.tar.gz`; - const url = `https://nodejs.org/dist/v${version}/${downloadName}`; + const url = `https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/dist/v${version}/${downloadName}`; const downloadPath = config.resolveFromRepo('.node_binaries', version, basename(downloadName)); const extractDir = config.resolveFromRepo('.node_binaries', version, arch); diff --git a/src/dev/build/tasks/nodejs/node_shasums.test.ts b/src/dev/build/tasks/nodejs/node_shasums.test.ts index ee91d2a370fb1..08ac823c7ebf0 100644 --- a/src/dev/build/tasks/nodejs/node_shasums.test.ts +++ b/src/dev/build/tasks/nodejs/node_shasums.test.ts @@ -60,7 +60,9 @@ c4edece2c0aa68e816c4e067f397eb12e9d0c81bb37b3d349dbaf47cf246b0b7 win-x86/node.l jest.mock('axios', () => ({ async get(url: string) { - expect(url).toBe('https://nodejs.org/dist/v8.9.4/SHASUMS256.txt'); + expect(url).toBe( + 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/dist/v8.9.4/SHASUMS256.txt' + ); return { status: 200, data: mockResponse, diff --git a/src/dev/build/tasks/nodejs/node_shasums.ts b/src/dev/build/tasks/nodejs/node_shasums.ts index 1b8d01a9b1d94..e0926aa3e49e4 100644 --- a/src/dev/build/tasks/nodejs/node_shasums.ts +++ b/src/dev/build/tasks/nodejs/node_shasums.ts @@ -20,7 +20,7 @@ import axios from 'axios'; export async function getNodeShasums(nodeVersion: string) { - const url = `https://nodejs.org/dist/v${nodeVersion}/SHASUMS256.txt`; + const url = `https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/dist/v${nodeVersion}/SHASUMS256.txt`; const { status, data } = await axios.get(url); diff --git a/src/dev/ci_setup/setup_env.sh b/src/dev/ci_setup/setup_env.sh index b9fe8fe77d122..51c21dc45cdd1 100644 --- a/src/dev/ci_setup/setup_env.sh +++ b/src/dev/ci_setup/setup_env.sh @@ -53,10 +53,10 @@ nodeDir="$cacheDir/node/$nodeVersion" if [[ "$OS" == "win" ]]; then nodeBin="$HOME/node" - nodeUrl="https://nodejs.org/dist/v$nodeVersion/node-v$nodeVersion-win-x64.zip" + nodeUrl="https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/dist/v$nodeVersion/node-v$nodeVersion-win-x64.zip" else nodeBin="$nodeDir/bin" - nodeUrl="https://nodejs.org/dist/v$nodeVersion/node-v$nodeVersion-linux-x64.tar.gz" + nodeUrl="https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/dist/v$nodeVersion/node-v$nodeVersion-linux-x64.tar.gz" fi if [[ "$installNode" == "true" ]]; then From ae2deab4c568d9e88f580b97b31574207813998a Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 23 Oct 2019 17:46:07 -0700 Subject: [PATCH 100/191] skip flaky test (#48910) --- x-pack/test/functional/apps/monitoring/time_filter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/monitoring/time_filter.js b/x-pack/test/functional/apps/monitoring/time_filter.js index e4254b487adfd..0afcada14be5f 100644 --- a/x-pack/test/functional/apps/monitoring/time_filter.js +++ b/x-pack/test/functional/apps/monitoring/time_filter.js @@ -27,7 +27,8 @@ export default function ({ getService, getPageObjects }) { await tearDown(); }); - it('should send another request when clicking Refresh', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/48910 + it.skip('should send another request when clicking Refresh', async () => { await testSubjects.click('querySubmitButton'); const isLoading = await PageObjects.header.isGlobalLoadingIndicatorVisible(); expect(isLoading).to.be(true); From f0e91325351aec1a821b82cf74e3dd854702ec4d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2019 19:23:37 -0700 Subject: [PATCH 101/191] Update dependency execa to v3 (#48975) * Update dependency execa to v3 * update kbn/pm dist * remove old @types/execa package * remove use of removed methods/properties, specify preferLocal when needed * [@kbn/pm] specify preferLocal when running install scripts * update kbn/pm dist * Joi now converts input to matching option from .valid() * fix failed tests * Revert "Joi now converts input to matching option from .valid()" This reverts commit 75531b1d095c20595fe8cf30ba0035ba652e9a35. --- package.json | 3 +- packages/kbn-dev-utils/package.json | 2 +- .../kbn-dev-utils/src/proc_runner/proc.ts | 1 + packages/kbn-es/package.json | 2 +- packages/kbn-plugin-generator/package.json | 2 +- packages/kbn-plugin-helpers/package.json | 2 +- packages/kbn-pm/dist/index.js | 6372 ++++++++--------- packages/kbn-pm/package.json | 3 +- packages/kbn-pm/src/utils/child_process.ts | 2 + renovate.json5 | 8 - .../integration_tests/deep_freeze.test.ts | 16 +- src/dev/build/lib/exec.js | 1 + src/dev/build/lib/version_info.js | 6 +- .../integration_tests/junit_reporter.test.js | 2 +- src/dev/prs/run_update_prs_cli.ts | 2 +- src/dev/run_check_core_api_changes.ts | 10 +- src/dev/typescript/exec_in_projects.ts | 1 + .../typescript/run_check_ts_projects_cli.ts | 2 +- tasks/function_test_groups.js | 5 +- x-pack/package.json | 2 +- yarn.lock | 65 +- 21 files changed, 2994 insertions(+), 3515 deletions(-) diff --git a/package.json b/package.json index 101cee27aa28f..7ad77c4b44aba 100644 --- a/package.json +++ b/package.json @@ -160,7 +160,7 @@ "elasticsearch": "^16.4.0", "elasticsearch-browser": "^16.4.0", "encode-uri-query": "1.0.1", - "execa": "^1.0.0", + "execa": "^3.2.0", "expiry-js": "0.1.7", "file-loader": "4.2.0", "font-awesome": "4.7.0", @@ -303,7 +303,6 @@ "@types/elasticsearch": "^5.0.33", "@types/enzyme": "^3.9.0", "@types/eslint": "^6.1.2", - "@types/execa": "^0.9.0", "@types/fetch-mock": "^7.3.1", "@types/getopts": "^2.0.1", "@types/glob": "^7.1.1", diff --git a/packages/kbn-dev-utils/package.json b/packages/kbn-dev-utils/package.json index 5c64be294f707..c1f632719c486 100644 --- a/packages/kbn-dev-utils/package.json +++ b/packages/kbn-dev-utils/package.json @@ -12,7 +12,7 @@ "dependencies": { "chalk": "^2.4.2", "dedent": "^0.7.0", - "execa": "^1.0.0", + "execa": "^3.2.0", "exit-hook": "^2.2.0", "getopts": "^2.2.5", "moment": "^2.20.1", diff --git a/packages/kbn-dev-utils/src/proc_runner/proc.ts b/packages/kbn-dev-utils/src/proc_runner/proc.ts index f29fb5f4b17f6..dab69de47af61 100644 --- a/packages/kbn-dev-utils/src/proc_runner/proc.ts +++ b/packages/kbn-dev-utils/src/proc_runner/proc.ts @@ -87,6 +87,7 @@ export function startProc(name: string, options: ProcOptions, log: ToolingLog) { cwd, env, stdio: ['pipe', 'pipe', 'pipe'], + preferLocal: true, }); if (stdin) { diff --git a/packages/kbn-es/package.json b/packages/kbn-es/package.json index 5280c671450fa..cf98f6062dddc 100644 --- a/packages/kbn-es/package.json +++ b/packages/kbn-es/package.json @@ -11,7 +11,7 @@ "chalk": "^2.4.2", "dedent": "^0.7.0", "del": "^4.1.1", - "execa": "^1.0.0", + "execa": "^3.2.0", "getopts": "^2.2.4", "glob": "^7.1.2", "node-fetch": "^2.6.0", diff --git a/packages/kbn-plugin-generator/package.json b/packages/kbn-plugin-generator/package.json index 74ccbd8e758b5..ac98a0e675fb1 100644 --- a/packages/kbn-plugin-generator/package.json +++ b/packages/kbn-plugin-generator/package.json @@ -6,7 +6,7 @@ "dependencies": { "chalk": "^2.4.2", "dedent": "^0.7.0", - "execa": "^1.0.0", + "execa": "^3.2.0", "getopts": "^2.2.4", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json index 215963c0769bb..1b8247c3f756c 100644 --- a/packages/kbn-plugin-helpers/package.json +++ b/packages/kbn-plugin-helpers/package.json @@ -17,7 +17,7 @@ "argv-split": "^2.0.1", "commander": "^3.0.0", "del": "^4.1.1", - "execa": "^1.0.0", + "execa": "^3.2.0", "globby": "^8.0.1", "gulp-babel": "^8.0.0", "gulp-rename": "1.4.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 3dd27e7ef3800..3834ad4c92d55 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(404); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(412); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); @@ -105,10 +105,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(54); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return _utils_project__WEBPACK_IMPORTED_MODULE_3__["Project"]; }); -/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(163); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(171); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__["copyWorkspacePackages"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(164); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(172); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -152,7 +152,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(394); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(402); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -2502,9 +2502,9 @@ module.exports = require("path"); __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(165); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(192); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(193); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(173); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(200); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(201); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -4415,7 +4415,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(53); /* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(54); -/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(163); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(171); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -19082,9 +19082,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(122); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(150); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(158); /* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(155); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(163); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } @@ -19124,7 +19124,8 @@ function generateColors() { function spawn(command, args, opts) { return execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({ - stdio: 'inherit' + stdio: 'inherit', + preferLocal: true }, opts)); } const nextColor = generateColors(); @@ -19132,7 +19133,8 @@ function spawnStreaming(command, args, opts, { prefix }) { const spawned = execa__WEBPACK_IMPORTED_MODULE_1___default()(command, args, _objectSpread({ - stdio: ['ignore', 'pipe', 'pipe'] + stdio: ['ignore', 'pipe', 'pipe'], + preferLocal: true }, opts)); const color = nextColor(); const prefixedStdout = strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default()({ @@ -19156,363 +19158,258 @@ function spawnStreaming(command, args, opts, { const path = __webpack_require__(16); const childProcess = __webpack_require__(123); const crossSpawn = __webpack_require__(124); -const stripEof = __webpack_require__(139); -const npmRunPath = __webpack_require__(140); -const isStream = __webpack_require__(142); -const _getStream = __webpack_require__(143); -const pFinally = __webpack_require__(147); -const onExit = __webpack_require__(110); -const errname = __webpack_require__(148); -const stdio = __webpack_require__(149); - -const TEN_MEGABYTES = 1000 * 1000 * 10; +const stripFinalNewline = __webpack_require__(137); +const npmRunPath = __webpack_require__(138); +const onetime = __webpack_require__(139); +const makeError = __webpack_require__(141); +const normalizeStdio = __webpack_require__(146); +const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = __webpack_require__(147); +const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = __webpack_require__(149); +const {mergePromise, getSpawnedPromise} = __webpack_require__(156); +const {joinCommand, parseCommand} = __webpack_require__(157); -function handleArgs(cmd, args, opts) { - let parsed; +const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100; - opts = Object.assign({ - extendEnv: true, - env: {} - }, opts); +const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => { + const env = extendEnv ? {...process.env, ...envOption} : envOption; - if (opts.extendEnv) { - opts.env = Object.assign({}, process.env, opts.env); + if (preferLocal) { + return npmRunPath.env({env, cwd: localDir, execPath}); } - if (opts.__winShell === true) { - delete opts.__winShell; - parsed = { - command: cmd, - args, - options: opts, - file: cmd, - original: { - cmd, - args - } - }; - } else { - parsed = crossSpawn._parse(cmd, args, opts); - } + return env; +}; - opts = Object.assign({ - maxBuffer: TEN_MEGABYTES, +const handleArgs = (file, args, options = {}) => { + const parsed = crossSpawn._parse(file, args, options); + file = parsed.command; + args = parsed.args; + options = parsed.options; + + options = { + maxBuffer: DEFAULT_MAX_BUFFER, buffer: true, - stripEof: true, - preferLocal: true, - localDir: parsed.options.cwd || process.cwd(), + stripFinalNewline: true, + extendEnv: true, + preferLocal: false, + localDir: options.cwd || process.cwd(), + execPath: process.execPath, encoding: 'utf8', reject: true, - cleanup: true - }, parsed.options); - - opts.stdio = stdio(opts); - - if (opts.preferLocal) { - opts.env = npmRunPath.env(Object.assign({}, opts, {cwd: opts.localDir})); - } - - if (opts.detached) { - // #115 - opts.cleanup = false; - } - - if (process.platform === 'win32' && path.basename(parsed.command) === 'cmd.exe') { - // #116 - parsed.args.unshift('/q'); - } - - return { - cmd: parsed.command, - args: parsed.args, - opts, - parsed + cleanup: true, + all: false, + ...options, + windowsHide: true }; -} - -function handleInput(spawned, input) { - if (input === null || input === undefined) { - return; - } - - if (isStream(input)) { - input.pipe(spawned.stdin); - } else { - spawned.stdin.end(input); - } -} - -function handleOutput(opts, val) { - if (val && opts.stripEof) { - val = stripEof(val); - } - - return val; -} - -function handleShell(fn, cmd, opts) { - let file = '/bin/sh'; - let args = ['-c', cmd]; - - opts = Object.assign({}, opts); - - if (process.platform === 'win32') { - opts.__winShell = true; - file = process.env.comspec || 'cmd.exe'; - args = ['/s', '/c', `"${cmd}"`]; - opts.windowsVerbatimArguments = true; - } - - if (opts.shell) { - file = opts.shell; - delete opts.shell; - } - return fn(file, args, opts); -} - -function getStream(process, stream, {encoding, buffer, maxBuffer}) { - if (!process[stream]) { - return null; - } + options.env = getEnv(options); - let ret; + options.stdio = normalizeStdio(options); - if (!buffer) { - // TODO: Use `ret = util.promisify(stream.finished)(process[stream]);` when targeting Node.js 10 - ret = new Promise((resolve, reject) => { - process[stream] - .once('end', resolve) - .once('error', reject); - }); - } else if (encoding) { - ret = _getStream(process[stream], { - encoding, - maxBuffer - }); - } else { - ret = _getStream.buffer(process[stream], {maxBuffer}); + if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') { + // #116 + args.unshift('/q'); } - return ret.catch(err => { - err.stream = stream; - err.message = `${stream} ${err.message}`; - throw err; - }); -} - -function makeError(result, options) { - const {stdout, stderr} = result; - - let err = result.error; - const {code, signal} = result; - - const {parsed, joinedCmd} = options; - const timedOut = options.timedOut || false; - - if (!err) { - let output = ''; - - if (Array.isArray(parsed.opts.stdio)) { - if (parsed.opts.stdio[2] !== 'inherit') { - output += output.length > 0 ? stderr : `\n${stderr}`; - } - - if (parsed.opts.stdio[1] !== 'inherit') { - output += `\n${stdout}`; - } - } else if (parsed.opts.stdio !== 'inherit') { - output = `\n${stderr}${stdout}`; - } + return {file, args, options, parsed}; +}; - err = new Error(`Command failed: ${joinedCmd}${output}`); - err.code = code < 0 ? errname(code) : code; +const handleOutput = (options, value, error) => { + if (typeof value !== 'string' && !Buffer.isBuffer(value)) { + // When `execa.sync()` errors, we normalize it to '' to mimic `execa()` + return error === undefined ? undefined : ''; } - err.stdout = stdout; - err.stderr = stderr; - err.failed = true; - err.signal = signal || null; - err.cmd = joinedCmd; - err.timedOut = timedOut; - - return err; -} - -function joinCmd(cmd, args) { - let joinedCmd = cmd; - - if (Array.isArray(args) && args.length > 0) { - joinedCmd += ' ' + args.join(' '); + if (options.stripFinalNewline) { + return stripFinalNewline(value); } - return joinedCmd; -} + return value; +}; -module.exports = (cmd, args, opts) => { - const parsed = handleArgs(cmd, args, opts); - const {encoding, buffer, maxBuffer} = parsed.opts; - const joinedCmd = joinCmd(cmd, args); +const execa = (file, args, options) => { + const parsed = handleArgs(file, args, options); + const command = joinCommand(file, args); let spawned; try { - spawned = childProcess.spawn(parsed.cmd, parsed.args, parsed.opts); - } catch (err) { - return Promise.reject(err); - } - - let removeExitHandler; - if (parsed.opts.cleanup) { - removeExitHandler = onExit(() => { - spawned.kill(); - }); - } - - let timeoutId = null; - let timedOut = false; - - const cleanup = () => { - if (timeoutId) { - clearTimeout(timeoutId); - timeoutId = null; - } - - if (removeExitHandler) { - removeExitHandler(); - } - }; - - if (parsed.opts.timeout > 0) { - timeoutId = setTimeout(() => { - timeoutId = null; - timedOut = true; - spawned.kill(parsed.opts.killSignal); - }, parsed.opts.timeout); + spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options); + } catch (error) { + // Ensure the returned error is always both a promise and a child process + const dummySpawned = new childProcess.ChildProcess(); + const errorPromise = Promise.reject(makeError({ + error, + stdout: '', + stderr: '', + all: '', + command, + parsed, + timedOut: false, + isCanceled: false, + killed: false + })); + return mergePromise(dummySpawned, errorPromise); } - const processDone = new Promise(resolve => { - spawned.on('exit', (code, signal) => { - cleanup(); - resolve({code, signal}); - }); - - spawned.on('error', err => { - cleanup(); - resolve({error: err}); - }); - - if (spawned.stdin) { - spawned.stdin.on('error', err => { - cleanup(); - resolve({error: err}); - }); - } - }); + const spawnedPromise = getSpawnedPromise(spawned); + const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise); + const processDone = setExitHandler(spawned, parsed.options, timedPromise); - function destroy() { - if (spawned.stdout) { - spawned.stdout.destroy(); - } + const context = {isCanceled: false}; - if (spawned.stderr) { - spawned.stderr.destroy(); - } - } + spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned)); + spawned.cancel = spawnedCancel.bind(null, spawned, context); - const handlePromise = () => pFinally(Promise.all([ - processDone, - getStream(spawned, 'stdout', {encoding, buffer, maxBuffer}), - getStream(spawned, 'stderr', {encoding, buffer, maxBuffer}) - ]).then(arr => { - const result = arr[0]; - result.stdout = arr[1]; - result.stderr = arr[2]; + const handlePromise = async () => { + const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone); + const stdout = handleOutput(parsed.options, stdoutResult); + const stderr = handleOutput(parsed.options, stderrResult); + const all = handleOutput(parsed.options, allResult); - if (result.error || result.code !== 0 || result.signal !== null) { - const err = makeError(result, { - joinedCmd, + if (error || exitCode !== 0 || signal !== null) { + const returnedError = makeError({ + error, + exitCode, + signal, + stdout, + stderr, + all, + command, parsed, - timedOut + timedOut, + isCanceled: context.isCanceled, + killed: spawned.killed }); - // TODO: missing some timeout logic for killed - // https://github.com/nodejs/node/blob/master/lib/child_process.js#L203 - // err.killed = spawned.killed || killed; - err.killed = err.killed || spawned.killed; - - if (!parsed.opts.reject) { - return err; + if (!parsed.options.reject) { + return returnedError; } - throw err; + throw returnedError; } return { - stdout: handleOutput(parsed.opts, result.stdout), - stderr: handleOutput(parsed.opts, result.stderr), - code: 0, + command, + exitCode: 0, + stdout, + stderr, + all, failed: false, - killed: false, - signal: null, - cmd: joinedCmd, - timedOut: false + timedOut: false, + isCanceled: false, + killed: false }; - }), destroy); + }; + + const handlePromiseOnce = onetime(handlePromise); crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed); - handleInput(spawned, parsed.opts.input); + handleInput(spawned, parsed.options.input); - spawned.then = (onfulfilled, onrejected) => handlePromise().then(onfulfilled, onrejected); - spawned.catch = onrejected => handlePromise().catch(onrejected); + spawned.all = makeAllStream(spawned, parsed.options); - return spawned; + return mergePromise(spawned, handlePromiseOnce); }; -// TODO: set `stderr: 'ignore'` when that option is implemented -module.exports.stdout = (...args) => module.exports(...args).then(x => x.stdout); +module.exports = execa; -// TODO: set `stdout: 'ignore'` when that option is implemented -module.exports.stderr = (...args) => module.exports(...args).then(x => x.stderr); +module.exports.sync = (file, args, options) => { + const parsed = handleArgs(file, args, options); + const command = joinCommand(file, args); -module.exports.shell = (cmd, opts) => handleShell(module.exports, cmd, opts); + validateInputSync(parsed.options); -module.exports.sync = (cmd, args, opts) => { - const parsed = handleArgs(cmd, args, opts); - const joinedCmd = joinCmd(cmd, args); - - if (isStream(parsed.opts.input)) { - throw new TypeError('The `input` option cannot be a stream in sync mode'); + let result; + try { + result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options); + } catch (error) { + throw makeError({ + error, + stdout: '', + stderr: '', + all: '', + command, + parsed, + timedOut: false, + isCanceled: false, + killed: false + }); } - const result = childProcess.spawnSync(parsed.cmd, parsed.args, parsed.opts); - result.code = result.status; + const stdout = handleOutput(parsed.options, result.stdout, result.error); + const stderr = handleOutput(parsed.options, result.stderr, result.error); if (result.error || result.status !== 0 || result.signal !== null) { - const err = makeError(result, { - joinedCmd, - parsed + const error = makeError({ + stdout, + stderr, + error: result.error, + signal: result.signal, + exitCode: result.status, + command, + parsed, + timedOut: result.error && result.error.code === 'ETIMEDOUT', + isCanceled: false, + killed: result.signal !== null }); - if (!parsed.opts.reject) { - return err; + if (!parsed.options.reject) { + return error; } - throw err; + throw error; } return { - stdout: handleOutput(parsed.opts, result.stdout), - stderr: handleOutput(parsed.opts, result.stderr), - code: 0, + command, + exitCode: 0, + stdout, + stderr, failed: false, - signal: null, - cmd: joinedCmd, - timedOut: false + timedOut: false, + isCanceled: false, + killed: false }; }; -module.exports.shellSync = (cmd, opts) => handleShell(module.exports.sync, cmd, opts); +module.exports.command = (command, options) => { + const [file, ...args] = parseCommand(command); + return execa(file, args, options); +}; + +module.exports.commandSync = (command, options) => { + const [file, ...args] = parseCommand(command); + return execa.sync(file, args, options); +}; + +module.exports.node = (scriptPath, args, options = {}) => { + if (args && !Array.isArray(args) && typeof args === 'object') { + options = args; + args = []; + } + + const stdio = normalizeStdio.node(options); + + const {nodePath = process.execPath, nodeOptions = process.execArgv} = options; + + return execa( + nodePath, + [ + ...nodeOptions, + scriptPath, + ...(Array.isArray(args) ? args : []) + ], + { + ...options, + stdin: undefined, + stdout: undefined, + stderr: undefined, + stdio, + shell: false + } + ); +}; /***/ }), @@ -19530,7 +19427,7 @@ module.exports = require("child_process"); const cp = __webpack_require__(123); const parse = __webpack_require__(125); -const enoent = __webpack_require__(138); +const enoent = __webpack_require__(136); function spawn(command, args, options) { // Parse the arguments @@ -19575,19 +19472,14 @@ module.exports._enoent = enoent; const path = __webpack_require__(16); -const niceTry = __webpack_require__(126); -const resolveCommand = __webpack_require__(127); -const escape = __webpack_require__(133); -const readShebang = __webpack_require__(134); -const semver = __webpack_require__(137); +const resolveCommand = __webpack_require__(126); +const escape = __webpack_require__(132); +const readShebang = __webpack_require__(133); const isWin = process.platform === 'win32'; const isExecutableRegExp = /\.(?:com|exe)$/i; const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; -// `options.shell` is supported in Node ^4.8.0, ^5.7.0 and >= 6.0.0 -const supportsShellOption = niceTry(() => semver.satisfies(process.version, '^4.8.0 || ^5.7.0 || >= 6.0.0', true)) || false; - function detectShebang(parsed) { parsed.file = resolveCommand(parsed); @@ -19641,35 +19533,6 @@ function parseNonShell(parsed) { return parsed; } -function parseShell(parsed) { - // If node supports the shell option, there's no need to mimic its behavior - if (supportsShellOption) { - return parsed; - } - - // Mimic node shell option - // See https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335 - const shellCommand = [parsed.command].concat(parsed.args).join(' '); - - if (isWin) { - parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe'; - parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; - parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped - } else { - if (typeof parsed.options.shell === 'string') { - parsed.command = parsed.options.shell; - } else if (process.platform === 'android') { - parsed.command = '/system/bin/sh'; - } else { - parsed.command = '/bin/sh'; - } - - parsed.args = ['-c', shellCommand]; - } - - return parsed; -} - function parse(command, args, options) { // Normalize arguments, similar to nodejs if (args && !Array.isArray(args)) { @@ -19693,7 +19556,7 @@ function parse(command, args, options) { }; // Delegate further parsing to shell or non-shell - return options.shell ? parseShell(parsed) : parseNonShell(parsed); + return options.shell ? parsed : parseNonShell(parsed); } module.exports = parse; @@ -19706,36 +19569,19 @@ module.exports = parse; "use strict"; -/** - * Tries to execute a function and discards any error that occurs. - * @param {Function} fn - Function that might or might not throw an error. - * @returns {?*} Return-value of the function when no error occurred. - */ -module.exports = function(fn) { - - try { return fn() } - catch (e) {} - -} - -/***/ }), -/* 127 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - const path = __webpack_require__(16); -const which = __webpack_require__(128); -const pathKey = __webpack_require__(132)(); +const which = __webpack_require__(127); +const pathKey = __webpack_require__(131)(); function resolveCommandAttempt(parsed, withoutPathExt) { const cwd = process.cwd(); const hasCustomCwd = parsed.options.cwd != null; + // Worker threads do not have process.chdir() + const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined; // If a custom `cwd` was specified, we need to change the process cwd // because `which` will do stat calls but does not support a custom cwd - if (hasCustomCwd) { + if (shouldSwitchCwd) { try { process.chdir(parsed.options.cwd); } catch (err) { @@ -19753,7 +19599,9 @@ function resolveCommandAttempt(parsed, withoutPathExt) { } catch (e) { /* Empty */ } finally { - process.chdir(cwd); + if (shouldSwitchCwd) { + process.chdir(cwd); + } } // If we successfully resolved, ensure that an absolute path is returned @@ -19773,126 +19621,113 @@ module.exports = resolveCommand; /***/ }), -/* 128 */ +/* 127 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = which -which.sync = whichSync - -var isWindows = process.platform === 'win32' || +const isWindows = process.platform === 'win32' || process.env.OSTYPE === 'cygwin' || process.env.OSTYPE === 'msys' -var path = __webpack_require__(16) -var COLON = isWindows ? ';' : ':' -var isexe = __webpack_require__(129) - -function getNotFoundError (cmd) { - var er = new Error('not found: ' + cmd) - er.code = 'ENOENT' +const path = __webpack_require__(16) +const COLON = isWindows ? ';' : ':' +const isexe = __webpack_require__(128) - return er -} +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) -function getPathInfo (cmd, opt) { - var colon = opt.colon || COLON - var pathEnv = opt.path || process.env.PATH || '' - var pathExt = [''] +const getPathInfo = (cmd, opt) => { + const colon = opt.colon || COLON - pathEnv = pathEnv.split(colon) + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] + : ( + [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(opt.path || process.env.PATH || + /* istanbul ignore next: very unusual */ '').split(colon), + ] + ) + const pathExtExe = isWindows + ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' + : '' + const pathExt = isWindows ? pathExtExe.split(colon) : [''] - var pathExtExe = '' if (isWindows) { - pathEnv.unshift(process.cwd()) - pathExtExe = (opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM') - pathExt = pathExtExe.split(colon) - - - // Always test the cmd itself first. isexe will check to make sure - // it's found in the pathExt set. if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') pathExt.unshift('') } - // If it has a slash, then we don't bother searching the pathenv. - // just check the file itself, and that's it. - if (cmd.match(/\//) || isWindows && cmd.match(/\\/)) - pathEnv = [''] - return { - env: pathEnv, - ext: pathExt, - extExe: pathExtExe + pathEnv, + pathExt, + pathExtExe, } } -function which (cmd, opt, cb) { +const which = (cmd, opt, cb) => { if (typeof opt === 'function') { cb = opt opt = {} } + if (!opt) + opt = {} - var info = getPathInfo(cmd, opt) - var pathEnv = info.env - var pathExt = info.ext - var pathExtExe = info.extExe - var found = [] + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] - ;(function F (i, l) { - if (i === l) { - if (opt.all && found.length) - return cb(null, found) - else - return cb(getNotFoundError(cmd)) - } + const step = i => new Promise((resolve, reject) => { + if (i === pathEnv.length) + return opt.all && found.length ? resolve(found) + : reject(getNotFoundError(cmd)) - var pathPart = pathEnv[i] - if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') - pathPart = pathPart.slice(1, -1) + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw - var p = path.join(pathPart, cmd) - if (!pathPart && (/^\.[\\\/]/).test(cmd)) { - p = cmd.slice(0, 2) + p - } - ;(function E (ii, ll) { - if (ii === ll) return F(i + 1, l) - var ext = pathExt[ii] - isexe(p + ext, { pathExt: pathExtExe }, function (er, is) { - if (!er && is) { - if (opt.all) - found.push(p + ext) - else - return cb(null, p + ext) - } - return E(ii + 1, ll) - }) - })(0, pathExt.length) - })(0, pathEnv.length) + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + resolve(subStep(p, i, 0)) + }) + + const subStep = (p, i, ii) => new Promise((resolve, reject) => { + if (ii === pathExt.length) + return resolve(step(i + 1)) + const ext = pathExt[ii] + isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { + if (!er && is) { + if (opt.all) + found.push(p + ext) + else + return resolve(p + ext) + } + return resolve(subStep(p, i, ii + 1)) + }) + }) + + return cb ? step(0).then(res => cb(null, res), cb) : step(0) } -function whichSync (cmd, opt) { +const whichSync = (cmd, opt) => { opt = opt || {} - var info = getPathInfo(cmd, opt) - var pathEnv = info.env - var pathExt = info.ext - var pathExtExe = info.extExe - var found = [] + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] - for (var i = 0, l = pathEnv.length; i < l; i ++) { - var pathPart = pathEnv[i] - if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') - pathPart = pathPart.slice(1, -1) + for (let i = 0; i < pathEnv.length; i ++) { + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw - var p = path.join(pathPart, cmd) - if (!pathPart && /^\.[\\\/]/.test(cmd)) { - p = cmd.slice(0, 2) + p - } - for (var j = 0, ll = pathExt.length; j < ll; j ++) { - var cur = p + pathExt[j] - var is + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + for (let j = 0; j < pathExt.length; j ++) { + const cur = p + pathExt[j] try { - is = isexe.sync(cur, { pathExt: pathExtExe }) + const is = isexe.sync(cur, { pathExt: pathExtExe }) if (is) { if (opt.all) found.push(cur) @@ -19912,17 +19747,20 @@ function whichSync (cmd, opt) { throw getNotFoundError(cmd) } +module.exports = which +which.sync = whichSync + /***/ }), -/* 129 */ +/* 128 */ /***/ (function(module, exports, __webpack_require__) { var fs = __webpack_require__(23) var core if (process.platform === 'win32' || global.TESTING_WINDOWS) { - core = __webpack_require__(130) + core = __webpack_require__(129) } else { - core = __webpack_require__(131) + core = __webpack_require__(130) } module.exports = isexe @@ -19977,7 +19815,7 @@ function sync (path, options) { /***/ }), -/* 130 */ +/* 129 */ /***/ (function(module, exports, __webpack_require__) { module.exports = isexe @@ -20025,7 +19863,7 @@ function sync (path, options) { /***/ }), -/* 131 */ +/* 130 */ /***/ (function(module, exports, __webpack_require__) { module.exports = isexe @@ -20072,27 +19910,30 @@ function checkMode (stat, options) { /***/ }), -/* 132 */ +/* 131 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = opts => { - opts = opts || {}; - const env = opts.env || process.env; - const platform = opts.platform || process.platform; +const pathKey = (options = {}) => { + const environment = options.env || process.env; + const platform = options.platform || process.platform; if (platform !== 'win32') { return 'PATH'; } - return Object.keys(env).find(x => x.toUpperCase() === 'PATH') || 'Path'; + return Object.keys(environment).find(key => key.toUpperCase() === 'PATH') || 'Path'; }; +module.exports = pathKey; +// TODO: Remove this for the next major release +module.exports.default = pathKey; + /***/ }), -/* 133 */ +/* 132 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -20144,28 +19985,19 @@ module.exports.argument = escapeArgument; /***/ }), -/* 134 */ +/* 133 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const shebangCommand = __webpack_require__(135); +const shebangCommand = __webpack_require__(134); function readShebang(command) { // Read the first 150 bytes from the file const size = 150; - let buffer; - - if (Buffer.alloc) { - // Node.js v4.5+ / v5.10+ - buffer = Buffer.alloc(size); - } else { - // Old Node.js API - buffer = new Buffer(size); - buffer.fill(0); // zero-fill - } + const buffer = Buffer.alloc(size); let fd; @@ -20183,1560 +20015,1113 @@ module.exports = readShebang; /***/ }), -/* 135 */ +/* 134 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var shebangRegex = __webpack_require__(136); +const shebangRegex = __webpack_require__(135); -module.exports = function (str) { - var match = str.match(shebangRegex); +module.exports = (string = '') => { + const match = string.match(shebangRegex); if (!match) { return null; } - var arr = match[0].replace(/#! ?/, '').split(' '); - var bin = arr[0].split('/').pop(); - var arg = arr[1]; + const [path, argument] = match[0].replace(/#! ?/, '').split(' '); + const binary = path.split('/').pop(); - return (bin === 'env' ? - arg : - bin + (arg ? ' ' + arg : '') - ); + if (binary === 'env') { + return argument; + } + + return argument ? `${binary} ${argument}` : binary; }; /***/ }), -/* 136 */ +/* 135 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = /^#!.*/; +module.exports = /^#!(.*)/; /***/ }), -/* 137 */ -/***/ (function(module, exports) { +/* 136 */ +/***/ (function(module, exports, __webpack_require__) { -exports = module.exports = SemVer; +"use strict"; -// The debug function is excluded entirely from the minified version. -/* nomin */ var debug; -/* nomin */ if (typeof process === 'object' && - /* nomin */ process.env && - /* nomin */ process.env.NODE_DEBUG && - /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) - /* nomin */ debug = function() { - /* nomin */ var args = Array.prototype.slice.call(arguments, 0); - /* nomin */ args.unshift('SEMVER'); - /* nomin */ console.log.apply(console, args); - /* nomin */ }; -/* nomin */ else - /* nomin */ debug = function() {}; -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0'; +const isWin = process.platform === 'win32'; -var MAX_LENGTH = 256; -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; +function notFoundError(original, syscall) { + return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { + code: 'ENOENT', + errno: 'ENOENT', + syscall: `${syscall} ${original.command}`, + path: original.command, + spawnargs: original.args, + }); +} -// Max safe segment length for coercion. -var MAX_SAFE_COMPONENT_LENGTH = 16; +function hookChildProcess(cp, parsed) { + if (!isWin) { + return; + } -// The actual regexps go on exports.re -var re = exports.re = []; -var src = exports.src = []; -var R = 0; + const originalEmit = cp.emit; -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. + cp.emit = function (name, arg1) { + // If emitting "exit" event and exit code is 1, we need to check if + // the command exists and emit an "error" instead + // See https://github.com/IndigoUnited/node-cross-spawn/issues/16 + if (name === 'exit') { + const err = verifyENOENT(arg1, parsed, 'spawn'); -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. + if (err) { + return originalEmit.call(cp, 'error', err); + } + } -var NUMERICIDENTIFIER = R++; -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; -var NUMERICIDENTIFIERLOOSE = R++; -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; + return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params + }; +} +function verifyENOENT(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawn'); + } -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. + return null; +} -var NONNUMERICIDENTIFIER = R++; -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; +function verifyENOENTSync(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawnSync'); + } + return null; +} -// ## Main Version -// Three dot-separated numeric identifiers. +module.exports = { + hookChildProcess, + verifyENOENT, + verifyENOENTSync, + notFoundError, +}; -var MAINVERSION = R++; -src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')'; -var MAINVERSIONLOOSE = R++; -src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; +/***/ }), +/* 137 */ +/***/ (function(module, exports, __webpack_require__) { -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. +"use strict"; -var PRERELEASEIDENTIFIER = R++; -src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; -var PRERELEASEIDENTIFIERLOOSE = R++; -src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; +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); + } -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. + if (input[input.length - 1] === CR) { + input = input.slice(0, input.length - 1); + } -var PRERELEASE = R++; -src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; + return input; +}; -var PRERELEASELOOSE = R++; -src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. +/***/ }), +/* 138 */ +/***/ (function(module, exports, __webpack_require__) { -var BUILDIDENTIFIER = R++; -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; +"use strict"; -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. +const path = __webpack_require__(16); +const pathKey = __webpack_require__(131); -var BUILD = R++; -src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; +const npmRunPath = options => { + options = { + cwd: process.cwd(), + path: process.env[pathKey()], + execPath: process.execPath, + ...options + }; + let previous; + let cwdPath = path.resolve(options.cwd); + const result = []; -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. + while (previous !== cwdPath) { + result.push(path.join(cwdPath, 'node_modules/.bin')); + previous = cwdPath; + cwdPath = path.resolve(cwdPath, '..'); + } -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. + // Ensure the running `node` binary is used + const execPathDir = path.resolve(options.cwd, options.execPath, '..'); + result.unshift(execPathDir); -var FULL = R++; -var FULLPLAIN = 'v?' + src[MAINVERSION] + - src[PRERELEASE] + '?' + - src[BUILD] + '?'; + return result.concat(options.path).join(path.delimiter); +}; -src[FULL] = '^' + FULLPLAIN + '$'; +module.exports = npmRunPath; +// TODO: Remove this for the next major release +module.exports.default = npmRunPath; -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + - src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?'; +module.exports.env = options => { + options = { + env: process.env, + ...options + }; -var LOOSE = R++; -src[LOOSE] = '^' + LOOSEPLAIN + '$'; + const env = {...options.env}; + const path = pathKey({env}); -var GTLT = R++; -src[GTLT] = '((?:<|>)?=?)'; + options.path = env[path]; + env[path] = module.exports(options); -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++; -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; -var XRANGEIDENTIFIER = R++; -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; + return env; +}; -var XRANGEPLAIN = R++; -src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:' + src[PRERELEASE] + ')?' + - src[BUILD] + '?' + - ')?)?'; -var XRANGEPLAINLOOSE = R++; -src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[PRERELEASELOOSE] + ')?' + - src[BUILD] + '?' + - ')?)?'; +/***/ }), +/* 139 */ +/***/ (function(module, exports, __webpack_require__) { -var XRANGE = R++; -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; -var XRANGELOOSE = R++; -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; +"use strict"; -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -var COERCE = R++; -src[COERCE] = '(?:^|[^\\d])' + - '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:$|[^\\d])'; +const mimicFn = __webpack_require__(140); -// Tilde ranges. -// Meaning is "reasonably at or greater than" -var LONETILDE = R++; -src[LONETILDE] = '(?:~>?)'; +const calledFunctions = new WeakMap(); -var TILDETRIM = R++; -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); -var tildeTrimReplace = '$1~'; +const oneTime = (fn, options = {}) => { + if (typeof fn !== 'function') { + throw new TypeError('Expected a function'); + } -var TILDE = R++; -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; -var TILDELOOSE = R++; -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; + let ret; + let isCalled = false; + let callCount = 0; + const functionName = fn.displayName || fn.name || ''; -// Caret ranges. -// Meaning is "at least and backwards compatible with" -var LONECARET = R++; -src[LONECARET] = '(?:\\^)'; + const onetime = function (...args) { + calledFunctions.set(onetime, ++callCount); -var CARETTRIM = R++; -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); -var caretTrimReplace = '$1^'; + if (isCalled) { + if (options.throw === true) { + throw new Error(`Function \`${functionName}\` can only be called once`); + } -var CARET = R++; -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; -var CARETLOOSE = R++; -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; + return ret; + } -// A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++; -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; -var COMPARATOR = R++; -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; + isCalled = true; + ret = fn.apply(this, args); + fn = null; + return ret; + }; -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++; -src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + mimicFn(onetime, fn); + calledFunctions.set(onetime, callCount); -// this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); -var comparatorTrimReplace = '$1$2$3'; + return onetime; +}; +module.exports = oneTime; +// TODO: Remove this for the next major release +module.exports.default = oneTime; -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -var HYPHENRANGE = R++; -src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAIN] + ')' + - '\\s*$'; +module.exports.callCount = fn => { + if (!calledFunctions.has(fn)) { + throw new Error(`The given function \`${fn.name}\` is not wrapped by the \`onetime\` package`); + } -var HYPHENRANGELOOSE = R++; -src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$'; + return calledFunctions.get(fn); +}; -// Star ranges basically just allow anything at all. -var STAR = R++; -src[STAR] = '(<|>)?=?\\s*\\*'; -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]); - if (!re[i]) - re[i] = new RegExp(src[i]); -} +/***/ }), +/* 140 */ +/***/ (function(module, exports, __webpack_require__) { -exports.parse = parse; -function parse(version, loose) { - if (version instanceof SemVer) - return version; - - if (typeof version !== 'string') - return null; - - if (version.length > MAX_LENGTH) - return null; - - var r = loose ? re[LOOSE] : re[FULL]; - if (!r.test(version)) - return null; - - try { - return new SemVer(version, loose); - } catch (er) { - return null; - } -} - -exports.valid = valid; -function valid(version, loose) { - var v = parse(version, loose); - return v ? v.version : null; -} - - -exports.clean = clean; -function clean(version, loose) { - var s = parse(version.trim().replace(/^[=v]+/, ''), loose); - return s ? s.version : null; -} - -exports.SemVer = SemVer; - -function SemVer(version, loose) { - if (version instanceof SemVer) { - if (version.loose === loose) - return version; - else - version = version.version; - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version); - } - - if (version.length > MAX_LENGTH) - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') - - if (!(this instanceof SemVer)) - return new SemVer(version, loose); - - debug('SemVer', version, loose); - this.loose = loose; - var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); - - if (!m) - throw new TypeError('Invalid Version: ' + version); - - this.raw = version; - - // these are actually numbers - this.major = +m[1]; - this.minor = +m[2]; - this.patch = +m[3]; - - if (this.major > MAX_SAFE_INTEGER || this.major < 0) - throw new TypeError('Invalid major version') - - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) - throw new TypeError('Invalid minor version') - - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) - throw new TypeError('Invalid patch version') - - // numberify any prerelease numeric ids - if (!m[4]) - this.prerelease = []; - else - this.prerelease = m[4].split('.').map(function(id) { - if (/^[0-9]+$/.test(id)) { - var num = +id; - if (num >= 0 && num < MAX_SAFE_INTEGER) - return num; - } - return id; - }); - - this.build = m[5] ? m[5].split('.') : []; - this.format(); -} - -SemVer.prototype.format = function() { - this.version = this.major + '.' + this.minor + '.' + this.patch; - if (this.prerelease.length) - this.version += '-' + this.prerelease.join('.'); - return this.version; -}; - -SemVer.prototype.toString = function() { - return this.version; -}; - -SemVer.prototype.compare = function(other) { - debug('SemVer.compare', this.version, this.loose, other); - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); - - return this.compareMain(other) || this.comparePre(other); -}; - -SemVer.prototype.compareMain = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); - - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch); -}; - -SemVer.prototype.comparePre = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); - - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) - return -1; - else if (!this.prerelease.length && other.prerelease.length) - return 1; - else if (!this.prerelease.length && !other.prerelease.length) - return 0; - - var i = 0; - do { - var a = this.prerelease[i]; - var b = other.prerelease[i]; - debug('prerelease compare', i, a, b); - if (a === undefined && b === undefined) - return 0; - else if (b === undefined) - return 1; - else if (a === undefined) - return -1; - else if (a === b) - continue; - else - return compareIdentifiers(a, b); - } while (++i); -}; - -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function(release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0; - this.patch = 0; - this.minor = 0; - this.major++; - this.inc('pre', identifier); - break; - case 'preminor': - this.prerelease.length = 0; - this.patch = 0; - this.minor++; - this.inc('pre', identifier); - break; - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0; - this.inc('patch', identifier); - this.inc('pre', identifier); - break; - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) - this.inc('patch', identifier); - this.inc('pre', identifier); - break; - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) - this.major++; - this.minor = 0; - this.patch = 0; - this.prerelease = []; - break; - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) - this.minor++; - this.patch = 0; - this.prerelease = []; - break; - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) - this.patch++; - this.prerelease = []; - break; - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) - this.prerelease = [0]; - else { - var i = this.prerelease.length; - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++; - i = -2; - } - } - if (i === -1) // didn't increment anything - this.prerelease.push(0); - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) - this.prerelease = [identifier, 0]; - } else - this.prerelease = [identifier, 0]; - } - break; - - default: - throw new Error('invalid increment argument: ' + release); - } - this.format(); - this.raw = this.version; - return this; -}; - -exports.inc = inc; -function inc(version, release, loose, identifier) { - if (typeof(loose) === 'string') { - identifier = loose; - loose = undefined; - } - - try { - return new SemVer(version, loose).inc(release, identifier).version; - } catch (er) { - return null; - } -} - -exports.diff = diff; -function diff(version1, version2) { - if (eq(version1, version2)) { - return null; - } else { - var v1 = parse(version1); - var v2 = parse(version2); - if (v1.prerelease.length || v2.prerelease.length) { - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return 'pre'+key; - } - } - } - return 'prerelease'; - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return key; - } - } - } - } -} - -exports.compareIdentifiers = compareIdentifiers; - -var numeric = /^[0-9]+$/; -function compareIdentifiers(a, b) { - var anum = numeric.test(a); - var bnum = numeric.test(b); - - if (anum && bnum) { - a = +a; - b = +b; - } - - return (anum && !bnum) ? -1 : - (bnum && !anum) ? 1 : - a < b ? -1 : - a > b ? 1 : - 0; -} - -exports.rcompareIdentifiers = rcompareIdentifiers; -function rcompareIdentifiers(a, b) { - return compareIdentifiers(b, a); -} - -exports.major = major; -function major(a, loose) { - return new SemVer(a, loose).major; -} - -exports.minor = minor; -function minor(a, loose) { - return new SemVer(a, loose).minor; -} - -exports.patch = patch; -function patch(a, loose) { - return new SemVer(a, loose).patch; -} - -exports.compare = compare; -function compare(a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)); -} - -exports.compareLoose = compareLoose; -function compareLoose(a, b) { - return compare(a, b, true); -} - -exports.rcompare = rcompare; -function rcompare(a, b, loose) { - return compare(b, a, loose); -} - -exports.sort = sort; -function sort(list, loose) { - return list.sort(function(a, b) { - return exports.compare(a, b, loose); - }); -} - -exports.rsort = rsort; -function rsort(list, loose) { - return list.sort(function(a, b) { - return exports.rcompare(a, b, loose); - }); -} - -exports.gt = gt; -function gt(a, b, loose) { - return compare(a, b, loose) > 0; -} - -exports.lt = lt; -function lt(a, b, loose) { - return compare(a, b, loose) < 0; -} - -exports.eq = eq; -function eq(a, b, loose) { - return compare(a, b, loose) === 0; -} - -exports.neq = neq; -function neq(a, b, loose) { - return compare(a, b, loose) !== 0; -} - -exports.gte = gte; -function gte(a, b, loose) { - return compare(a, b, loose) >= 0; -} - -exports.lte = lte; -function lte(a, b, loose) { - return compare(a, b, loose) <= 0; -} - -exports.cmp = cmp; -function cmp(a, op, b, loose) { - var ret; - switch (op) { - case '===': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a === b; - break; - case '!==': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a !== b; - break; - case '': case '=': case '==': ret = eq(a, b, loose); break; - case '!=': ret = neq(a, b, loose); break; - case '>': ret = gt(a, b, loose); break; - case '>=': ret = gte(a, b, loose); break; - case '<': ret = lt(a, b, loose); break; - case '<=': ret = lte(a, b, loose); break; - default: throw new TypeError('Invalid operator: ' + op); - } - return ret; -} - -exports.Comparator = Comparator; -function Comparator(comp, loose) { - if (comp instanceof Comparator) { - if (comp.loose === loose) - return comp; - else - comp = comp.value; - } - - if (!(this instanceof Comparator)) - return new Comparator(comp, loose); - - debug('comparator', comp, loose); - this.loose = loose; - this.parse(comp); - - if (this.semver === ANY) - this.value = ''; - else - this.value = this.operator + this.semver.version; - - debug('comp', this); -} - -var ANY = {}; -Comparator.prototype.parse = function(comp) { - var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var m = comp.match(r); - - if (!m) - throw new TypeError('Invalid comparator: ' + comp); - - this.operator = m[1]; - if (this.operator === '=') - this.operator = ''; - - // if it literally is just '>' or '' then allow anything. - if (!m[2]) - this.semver = ANY; - else - this.semver = new SemVer(m[2], this.loose); -}; - -Comparator.prototype.toString = function() { - return this.value; -}; - -Comparator.prototype.test = function(version) { - debug('Comparator.test', version, this.loose); - - if (this.semver === ANY) - return true; - - if (typeof version === 'string') - version = new SemVer(version, this.loose); - - return cmp(version, this.operator, this.semver, this.loose); -}; - -Comparator.prototype.intersects = function(comp, loose) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required'); - } +"use strict"; - var rangeTmp; - if (this.operator === '') { - rangeTmp = new Range(comp.value, loose); - return satisfies(this.value, rangeTmp, loose); - } else if (comp.operator === '') { - rangeTmp = new Range(this.value, loose); - return satisfies(comp.semver, rangeTmp, loose); - } - - var sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>'); - var sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<'); - var sameSemVer = this.semver.version === comp.semver.version; - var differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<='); - var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, loose) && - ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')); - var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, loose) && - ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')); +const mimicFn = (to, from) => { + for (const prop of Reflect.ownKeys(from)) { + Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop)); + } - return sameDirectionIncreasing || sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; + return to; }; +module.exports = mimicFn; +// TODO: Remove this for the next major release +module.exports.default = mimicFn; -exports.Range = Range; -function Range(range, loose) { - if (range instanceof Range) { - if (range.loose === loose) { - return range; - } else { - return new Range(range.raw, loose); - } - } - - if (range instanceof Comparator) { - return new Range(range.value, loose); - } - - if (!(this instanceof Range)) - return new Range(range, loose); - - this.loose = loose; - - // First, split based on boolean or || - this.raw = range; - this.set = range.split(/\s*\|\|\s*/).map(function(range) { - return this.parseRange(range.trim()); - }, this).filter(function(c) { - // throw out any that are not relevant for whatever reason - return c.length; - }); - - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range); - } - - this.format(); -} - -Range.prototype.format = function() { - this.range = this.set.map(function(comps) { - return comps.join(' ').trim(); - }).join('||').trim(); - return this.range; -}; - -Range.prototype.toString = function() { - return this.range; -}; -Range.prototype.parseRange = function(range) { - var loose = this.loose; - range = range.trim(); - debug('range', range, loose); - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; - range = range.replace(hr, hyphenReplace); - debug('hyphen replace', range); - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); - debug('comparator trim', range, re[COMPARATORTRIM]); +/***/ }), +/* 141 */ +/***/ (function(module, exports, __webpack_require__) { - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace); +"use strict"; - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace); +const {signalsByName} = __webpack_require__(142); - // normalize spaces - range = range.split(/\s+/).join(' '); +const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => { + if (timedOut) { + return `timed out after ${timeout} milliseconds`; + } - // At this point, the range is completely trimmed and - // ready to be split into comparators. + if (isCanceled) { + return 'was canceled'; + } - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var set = range.split(' ').map(function(comp) { - return parseComparator(comp, loose); - }).join(' ').split(/\s+/); - if (this.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function(comp) { - return !!comp.match(compRe); - }); - } - set = set.map(function(comp) { - return new Comparator(comp, loose); - }); + if (errorCode !== undefined) { + return `failed with ${errorCode}`; + } - return set; -}; + if (signal !== undefined) { + return `was killed with ${signal} (${signalDescription})`; + } -Range.prototype.intersects = function(range, loose) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required'); - } + if (exitCode !== undefined) { + return `failed with exit code ${exitCode}`; + } - return this.set.some(function(thisComparators) { - return thisComparators.every(function(thisComparator) { - return range.set.some(function(rangeComparators) { - return rangeComparators.every(function(rangeComparator) { - return thisComparator.intersects(rangeComparator, loose); - }); - }); - }); - }); + return 'failed'; }; -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators; -function toComparators(range, loose) { - return new Range(range, loose).set.map(function(comp) { - return comp.map(function(c) { - return c.value; - }).join(' ').trim().split(' '); - }); -} - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator(comp, loose) { - debug('comp', comp); - comp = replaceCarets(comp, loose); - debug('caret', comp); - comp = replaceTildes(comp, loose); - debug('tildes', comp); - comp = replaceXRanges(comp, loose); - debug('xrange', comp); - comp = replaceStars(comp, loose); - debug('stars', comp); - return comp; -} - -function isX(id) { - return !id || id.toLowerCase() === 'x' || id === '*'; -} - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceTilde(comp, loose); - }).join(' '); -} - -function replaceTilde(comp, loose) { - var r = loose ? re[TILDELOOSE] : re[TILDE]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr); - var ret; - - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else if (pr) { - debug('replaceTilde pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; - - debug('tilde return', ret); - return ret; - }); -} - -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceCaret(comp, loose); - }).join(' '); -} - -function replaceCaret(comp, loose) { - debug('caret', comp, loose); - var r = loose ? re[CARETLOOSE] : re[CARET]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr); - var ret; - - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) { - if (M === '0') - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; - } else if (pr) { - debug('replaceCaret pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + (+M + 1) + '.0.0'; - } else { - debug('no pr'); - if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0'; - } - - debug('caret return', ret); - return ret; - }); -} - -function replaceXRanges(comp, loose) { - debug('replaceXRanges', comp, loose); - return comp.split(/\s+/).map(function(comp) { - return replaceXRange(comp, loose); - }).join(' '); -} - -function replaceXRange(comp, loose) { - comp = comp.trim(); - var r = loose ? re[XRANGELOOSE] : re[XRANGE]; - return comp.replace(r, function(ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr); - var xM = isX(M); - var xm = xM || isX(m); - var xp = xm || isX(p); - var anyX = xp; +const makeError = ({ + stdout, + stderr, + all, + error, + signal, + exitCode, + command, + timedOut, + isCanceled, + killed, + parsed: {options: {timeout}} +}) => { + // `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`. + // We normalize them to `undefined` + exitCode = exitCode === null ? undefined : exitCode; + signal = signal === null ? undefined : signal; + const signalDescription = signal === undefined ? undefined : signalsByName[signal].description; - if (gtlt === '=' && anyX) - gtlt = ''; + const errorCode = error && error.code; - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0'; - } else { - // nothing is forbidden - ret = '*'; - } - } else if (gtlt && anyX) { - // replace X with 0 - if (xm) - m = 0; - if (xp) - p = 0; + const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}); + const message = `Command ${prefix}: ${command}`; - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>='; - if (xm) { - M = +M + 1; - m = 0; - p = 0; - } else if (xp) { - m = +m + 1; - p = 0; - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<'; - if (xm) - M = +M + 1; - else - m = +m + 1; - } - - ret = gtlt + M + '.' + m + '.' + p; - } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - } - - debug('xRange return', ret); - - return ret; - }); -} - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars(comp, loose) { - debug('replaceStars', comp, loose); - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], ''); -} - -// This function is passed to string.replace(re[HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - - if (isX(fM)) - from = ''; - else if (isX(fm)) - from = '>=' + fM + '.0.0'; - else if (isX(fp)) - from = '>=' + fM + '.' + fm + '.0'; - else - from = '>=' + from; - - if (isX(tM)) - to = ''; - else if (isX(tm)) - to = '<' + (+tM + 1) + '.0.0'; - else if (isX(tp)) - to = '<' + tM + '.' + (+tm + 1) + '.0'; - else if (tpr) - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; - else - to = '<=' + to; + if (error instanceof Error) { + error.originalMessage = error.message; + error.message = `${message}\n${error.message}`; + } else { + error = new Error(message); + } - return (from + ' ' + to).trim(); -} + error.command = command; + error.exitCode = exitCode; + error.signal = signal; + error.signalDescription = signalDescription; + error.stdout = stdout; + error.stderr = stderr; + if (all !== undefined) { + error.all = all; + } -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function(version) { - if (!version) - return false; + if ('bufferedData' in error) { + delete error.bufferedData; + } - if (typeof version === 'string') - version = new SemVer(version, this.loose); + error.failed = true; + error.timedOut = Boolean(timedOut); + error.isCanceled = isCanceled; + error.killed = killed && !timedOut; - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version)) - return true; - } - return false; + return error; }; -function testSet(set, version) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) - return false; - } +module.exports = makeError; - if (version.prerelease.length) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (var i = 0; i < set.length; i++) { - debug(set[i].semver); - if (set[i].semver === ANY) - continue; - - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver; - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) - return true; - } - } - - // Version has a -pre, but it's not one of the ones we like. - return false; - } - - return true; -} - -exports.satisfies = satisfies; -function satisfies(version, range, loose) { - try { - range = new Range(range, loose); - } catch (er) { - return false; - } - return range.test(version); -} - -exports.maxSatisfying = maxSatisfying; -function maxSatisfying(versions, range, loose) { - var max = null; - var maxSV = null; - try { - var rangeObj = new Range(range, loose); - } catch (er) { - return null; - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!max || maxSV.compare(v) === -1) { // compare(max, v, true) - max = v; - maxSV = new SemVer(max, loose); - } - } - }) - return max; -} - -exports.minSatisfying = minSatisfying; -function minSatisfying(versions, range, loose) { - var min = null; - var minSV = null; - try { - var rangeObj = new Range(range, loose); - } catch (er) { - return null; - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!min || minSV.compare(v) === 1) { // compare(min, v, true) - min = v; - minSV = new SemVer(min, loose); - } - } - }) - return min; -} - -exports.validRange = validRange; -function validRange(range, loose) { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, loose).range || '*'; - } catch (er) { - return null; - } -} - -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr; -function ltr(version, range, loose) { - return outside(version, range, '<', loose); -} - -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr; -function gtr(version, range, loose) { - return outside(version, range, '>', loose); -} - -exports.outside = outside; -function outside(version, range, hilo, loose) { - version = new SemVer(version, loose); - range = new Range(range, loose); - var gtfn, ltefn, ltfn, comp, ecomp; - switch (hilo) { - case '>': - gtfn = gt; - ltefn = lte; - ltfn = lt; - comp = '>'; - ecomp = '>='; - break; - case '<': - gtfn = lt; - ltefn = gte; - ltfn = gt; - comp = '<'; - ecomp = '<='; - break; - default: - throw new TypeError('Must provide a hilo val of "<" or ">"'); - } +/***/ }), +/* 142 */ +/***/ (function(module, exports, __webpack_require__) { - // If it satisifes the range it is not outside - if (satisfies(version, range, loose)) { - return false; - } +"use strict"; +Object.defineProperty(exports,"__esModule",{value:true});exports.signalsByNumber=exports.signalsByName=void 0;var _os=__webpack_require__(11); - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. +var _signals=__webpack_require__(143); +var _realtime=__webpack_require__(145); - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i]; - var high = null; - var low = null; - comparators.forEach(function(comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator; - low = low || comparator; - if (gtfn(comparator.semver, high.semver, loose)) { - high = comparator; - } else if (ltfn(comparator.semver, low.semver, loose)) { - low = comparator; - } - }); +const getSignalsByName=function(){ +const signals=(0,_signals.getSignals)(); +return signals.reduce(getSignalByName,{}); +}; - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false; - } +const getSignalByName=function( +signalByNameMemo, +{name,number,description,supported,action,forced,standard}) +{ +return{ +...signalByNameMemo, +[name]:{name,number,description,supported,action,forced,standard}}; - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false; - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false; - } - } - return true; -} +}; -exports.prerelease = prerelease; -function prerelease(version, loose) { - var parsed = parse(version, loose); - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; -} +const signalsByName=getSignalsByName();exports.signalsByName=signalsByName; -exports.intersects = intersects; -function intersects(r1, r2, loose) { - r1 = new Range(r1, loose) - r2 = new Range(r2, loose) - return r1.intersects(r2) + + + +const getSignalsByNumber=function(){ +const signals=(0,_signals.getSignals)(); +const length=_realtime.SIGRTMAX+1; +const signalsA=Array.from({length},(value,number)=> +getSignalByNumber(number,signals)); + +return Object.assign({},...signalsA); +}; + +const getSignalByNumber=function(number,signals){ +const signal=findSignalByNumber(number,signals); + +if(signal===undefined){ +return{}; } -exports.coerce = coerce; -function coerce(version) { - if (version instanceof SemVer) - return version; +const{name,description,supported,action,forced,standard}=signal; +return{ +[number]:{ +name, +number, +description, +supported, +action, +forced, +standard}}; - if (typeof version !== 'string') - return null; - var match = version.match(re[COERCE]); +}; - if (match == null) - return null; - return parse((match[1] || '0') + '.' + (match[2] || '0') + '.' + (match[3] || '0')); + +const findSignalByNumber=function(number,signals){ +const signal=signals.find(({name})=>_os.constants.signals[name]===number); + +if(signal!==undefined){ +return signal; } +return signals.find(signalA=>signalA.number===number); +}; + +const signalsByNumber=getSignalsByNumber();exports.signalsByNumber=signalsByNumber; +//# sourceMappingURL=main.js.map /***/ }), -/* 138 */ +/* 143 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +Object.defineProperty(exports,"__esModule",{value:true});exports.getSignals=void 0;var _os=__webpack_require__(11); +var _core=__webpack_require__(144); +var _realtime=__webpack_require__(145); -const isWin = process.platform === 'win32'; -function notFoundError(original, syscall) { - return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { - code: 'ENOENT', - errno: 'ENOENT', - syscall: `${syscall} ${original.command}`, - path: original.command, - spawnargs: original.args, - }); -} -function hookChildProcess(cp, parsed) { - if (!isWin) { - return; - } +const getSignals=function(){ +const realtimeSignals=(0,_realtime.getRealtimeSignals)(); +const signals=[..._core.SIGNALS,...realtimeSignals].map(normalizeSignal); +return signals; +};exports.getSignals=getSignals; - const originalEmit = cp.emit; - cp.emit = function (name, arg1) { - // If emitting "exit" event and exit code is 1, we need to check if - // the command exists and emit an "error" instead - // See https://github.com/IndigoUnited/node-cross-spawn/issues/16 - if (name === 'exit') { - const err = verifyENOENT(arg1, parsed, 'spawn'); - if (err) { - return originalEmit.call(cp, 'error', err); - } - } - return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params - }; -} -function verifyENOENT(status, parsed) { - if (isWin && status === 1 && !parsed.file) { - return notFoundError(parsed.original, 'spawn'); - } - return null; -} -function verifyENOENTSync(status, parsed) { - if (isWin && status === 1 && !parsed.file) { - return notFoundError(parsed.original, 'spawnSync'); - } +const normalizeSignal=function({ +name, +number:defaultNumber, +description, +action, +forced=false, +standard}) +{ +const{ +signals:{[name]:constantSignal}}= +_os.constants; +const supported=constantSignal!==undefined; +const number=supported?constantSignal:defaultNumber; +return{name,number,description,supported,action,forced,standard}; +}; +//# sourceMappingURL=signals.js.map - return null; -} +/***/ }), +/* 144 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +Object.defineProperty(exports,"__esModule",{value:true});exports.SIGNALS=void 0; + +const SIGNALS=[ +{ +name:"SIGHUP", +number:1, +action:"terminate", +description:"Terminal closed", +standard:"posix"}, + +{ +name:"SIGINT", +number:2, +action:"terminate", +description:"User interruption with CTRL-C", +standard:"ansi"}, + +{ +name:"SIGQUIT", +number:3, +action:"core", +description:"User interruption with CTRL-\\", +standard:"posix"}, + +{ +name:"SIGILL", +number:4, +action:"core", +description:"Invalid machine instruction", +standard:"ansi"}, + +{ +name:"SIGTRAP", +number:5, +action:"core", +description:"Debugger breakpoint", +standard:"posix"}, + +{ +name:"SIGABRT", +number:6, +action:"core", +description:"Aborted", +standard:"ansi"}, + +{ +name:"SIGIOT", +number:6, +action:"core", +description:"Aborted", +standard:"bsd"}, + +{ +name:"SIGBUS", +number:7, +action:"core", +description: +"Bus error due to misaligned, non-existing address or paging error", +standard:"bsd"}, + +{ +name:"SIGEMT", +number:7, +action:"terminate", +description:"Command should be emulated but is not implemented", +standard:"other"}, + +{ +name:"SIGFPE", +number:8, +action:"core", +description:"Floating point arithmetic error", +standard:"ansi"}, + +{ +name:"SIGKILL", +number:9, +action:"terminate", +description:"Forced termination", +standard:"posix", +forced:true}, + +{ +name:"SIGUSR1", +number:10, +action:"terminate", +description:"Application-specific signal", +standard:"posix"}, + +{ +name:"SIGSEGV", +number:11, +action:"core", +description:"Segmentation fault", +standard:"ansi"}, + +{ +name:"SIGUSR2", +number:12, +action:"terminate", +description:"Application-specific signal", +standard:"posix"}, + +{ +name:"SIGPIPE", +number:13, +action:"terminate", +description:"Broken pipe or socket", +standard:"posix"}, + +{ +name:"SIGALRM", +number:14, +action:"terminate", +description:"Timeout or timer", +standard:"posix"}, + +{ +name:"SIGTERM", +number:15, +action:"terminate", +description:"Termination", +standard:"ansi"}, + +{ +name:"SIGSTKFLT", +number:16, +action:"terminate", +description:"Stack is empty or overflowed", +standard:"other"}, + +{ +name:"SIGCHLD", +number:17, +action:"ignore", +description:"Child process terminated, paused or unpaused", +standard:"posix"}, + +{ +name:"SIGCLD", +number:17, +action:"ignore", +description:"Child process terminated, paused or unpaused", +standard:"other"}, + +{ +name:"SIGCONT", +number:18, +action:"unpause", +description:"Unpaused", +standard:"posix", +forced:true}, + +{ +name:"SIGSTOP", +number:19, +action:"pause", +description:"Paused", +standard:"posix", +forced:true}, + +{ +name:"SIGTSTP", +number:20, +action:"pause", +description:"Paused using CTRL-Z or \"suspend\"", +standard:"posix"}, + +{ +name:"SIGTTIN", +number:21, +action:"pause", +description:"Background process cannot read terminal input", +standard:"posix"}, + +{ +name:"SIGBREAK", +number:21, +action:"terminate", +description:"User interruption with CTRL-BREAK", +standard:"other"}, + +{ +name:"SIGTTOU", +number:22, +action:"pause", +description:"Background process cannot write to terminal output", +standard:"posix"}, + +{ +name:"SIGURG", +number:23, +action:"ignore", +description:"Socket received out-of-band data", +standard:"bsd"}, + +{ +name:"SIGXCPU", +number:24, +action:"core", +description:"Process timed out", +standard:"bsd"}, + +{ +name:"SIGXFSZ", +number:25, +action:"core", +description:"File too big", +standard:"bsd"}, + +{ +name:"SIGVTALRM", +number:26, +action:"terminate", +description:"Timeout or timer", +standard:"bsd"}, + +{ +name:"SIGPROF", +number:27, +action:"terminate", +description:"Timeout or timer", +standard:"bsd"}, + +{ +name:"SIGWINCH", +number:28, +action:"ignore", +description:"Terminal window size changed", +standard:"bsd"}, + +{ +name:"SIGIO", +number:29, +action:"terminate", +description:"I/O is available", +standard:"other"}, + +{ +name:"SIGPOLL", +number:29, +action:"terminate", +description:"Watched event", +standard:"other"}, + +{ +name:"SIGINFO", +number:29, +action:"ignore", +description:"Request for process information", +standard:"other"}, + +{ +name:"SIGPWR", +number:30, +action:"terminate", +description:"Device running out of power", +standard:"systemv"}, + +{ +name:"SIGSYS", +number:31, +action:"core", +description:"Invalid system call", +standard:"other"}, + +{ +name:"SIGUNUSED", +number:31, +action:"terminate", +description:"Invalid system call", +standard:"other"}];exports.SIGNALS=SIGNALS; +//# sourceMappingURL=core.js.map + +/***/ }), +/* 145 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +Object.defineProperty(exports,"__esModule",{value:true});exports.SIGRTMAX=exports.getRealtimeSignals=void 0; +const getRealtimeSignals=function(){ +const length=SIGRTMAX-SIGRTMIN+1; +return Array.from({length},getRealtimeSignal); +};exports.getRealtimeSignals=getRealtimeSignals; + +const getRealtimeSignal=function(value,index){ +return{ +name:`SIGRT${index+1}`, +number:SIGRTMIN+index, +action:"terminate", +description:"Application-specific signal (realtime)", +standard:"posix"}; -module.exports = { - hookChildProcess, - verifyENOENT, - verifyENOENTSync, - notFoundError, }; +const SIGRTMIN=34; +const SIGRTMAX=64;exports.SIGRTMAX=SIGRTMAX; +//# sourceMappingURL=realtime.js.map /***/ }), -/* 139 */ +/* 146 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = function (x) { - var lf = typeof x === 'string' ? '\n' : '\n'.charCodeAt(); - var cr = typeof x === 'string' ? '\r' : '\r'.charCodeAt(); +const aliases = ['stdin', 'stdout', 'stderr']; + +const hasAlias = opts => aliases.some(alias => opts[alias] !== undefined); + +const normalizeStdio = opts => { + if (!opts) { + return; + } + + const {stdio} = opts; + + if (stdio === undefined) { + return aliases.map(alias => opts[alias]); + } + + if (hasAlias(opts)) { + throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`); + } + + if (typeof stdio === 'string') { + return stdio; + } + + if (!Array.isArray(stdio)) { + throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); + } + + const length = Math.max(stdio.length, aliases.length); + return Array.from({length}, (value, index) => stdio[index]); +}; + +module.exports = normalizeStdio; - if (x[x.length - 1] === lf) { - x = x.slice(0, x.length - 1); +// `ipc` is pushed unless it is already present +module.exports.node = opts => { + const stdio = normalizeStdio(opts); + + if (stdio === 'ipc') { + return 'ipc'; + } + + if (stdio === undefined || typeof stdio === 'string') { + return [stdio, stdio, stdio, 'ipc']; } - if (x[x.length - 1] === cr) { - x = x.slice(0, x.length - 1); + if (stdio.includes('ipc')) { + return stdio; } - return x; + return [...stdio, 'ipc']; }; /***/ }), -/* 140 */ +/* 147 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const path = __webpack_require__(16); -const pathKey = __webpack_require__(141); +const os = __webpack_require__(11); +const onExit = __webpack_require__(110); +const pFinally = __webpack_require__(148); -module.exports = opts => { - opts = Object.assign({ - cwd: process.cwd(), - path: process.env[pathKey()] - }, opts); +const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5; - let prev; - let pth = path.resolve(opts.cwd); - const ret = []; +// Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior +const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => { + const killResult = kill(signal); + setKillTimeout(kill, signal, options, killResult); + return killResult; +}; - while (prev !== pth) { - ret.push(path.join(pth, 'node_modules/.bin')); - prev = pth; - pth = path.resolve(pth, '..'); +const setKillTimeout = (kill, signal, options, killResult) => { + if (!shouldForceKill(signal, options, killResult)) { + return; } - // ensure the running `node` binary is used - ret.push(path.dirname(process.execPath)); + const timeout = getForceKillAfterTimeout(options); + setTimeout(() => { + kill('SIGKILL'); + }, timeout).unref(); +}; - return ret.concat(opts.path).join(path.delimiter); +const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => { + return isSigterm(signal) && forceKillAfterTimeout !== false && killResult; }; -module.exports.env = opts => { - opts = Object.assign({ - env: process.env - }, opts); +const isSigterm = signal => { + return signal === os.constants.signals.SIGTERM || + (typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM'); +}; - const env = Object.assign({}, opts.env); - const path = pathKey({env}); +const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => { + if (forceKillAfterTimeout === true) { + return DEFAULT_FORCE_KILL_TIMEOUT; + } - opts.path = env[path]; - env[path] = module.exports(opts); + if (!Number.isInteger(forceKillAfterTimeout) || forceKillAfterTimeout < 0) { + throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`); + } - return env; + return forceKillAfterTimeout; +}; + +// `childProcess.cancel()` +const spawnedCancel = (spawned, context) => { + const killResult = spawned.kill(); + + if (killResult) { + context.isCanceled = true; + } +}; + +const timeoutKill = (spawned, signal, reject) => { + spawned.kill(signal); + reject(Object.assign(new Error('Timed out'), {timedOut: true, signal})); +}; + +// `timeout` option handling +const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => { + if (timeout === 0 || timeout === undefined) { + return spawnedPromise; + } + + if (!Number.isInteger(timeout) || timeout < 0) { + throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`); + } + + let timeoutId; + const timeoutPromise = new Promise((resolve, reject) => { + timeoutId = setTimeout(() => { + timeoutKill(spawned, killSignal, reject); + }, timeout); + }); + + const safeSpawnedPromise = pFinally(spawnedPromise, () => { + clearTimeout(timeoutId); + }); + + return Promise.race([timeoutPromise, safeSpawnedPromise]); +}; + +// `cleanup` option handling +const setExitHandler = (spawned, {cleanup, detached}, timedPromise) => { + if (!cleanup || detached) { + return timedPromise; + } + + const removeExitHandler = onExit(() => { + spawned.kill(); + }); + + // TODO: Use native "finally" syntax when targeting Node.js 10 + return pFinally(timedPromise, removeExitHandler); +}; + +module.exports = { + spawnedKill, + spawnedCancel, + setupTimeout, + setExitHandler }; /***/ }), -/* 141 */ +/* 148 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = opts => { - opts = opts || {}; - - const env = opts.env || process.env; - const platform = opts.platform || process.platform; - if (platform !== 'win32') { - return 'PATH'; +module.exports = async ( + promise, + onFinally = (() => {}) +) => { + let value; + try { + value = await promise; + } catch (error) { + await onFinally(); + throw error; } - return Object.keys(env).find(x => x.toUpperCase() === 'PATH') || 'Path'; + await onFinally(); + return value; }; /***/ }), -/* 142 */ +/* 149 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const isStream = __webpack_require__(150); +const getStream = __webpack_require__(151); +const mergeStream = __webpack_require__(155); + +// `input` option +const handleInput = (spawned, input) => { + // Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852 + // TODO: Remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0 + if (input === undefined || spawned.stdin === undefined) { + return; + } + + if (isStream(input)) { + input.pipe(spawned.stdin); + } else { + spawned.stdin.end(input); + } +}; + +// `all` interleaves `stdout` and `stderr` +const makeAllStream = (spawned, {all}) => { + if (!all || (!spawned.stdout && !spawned.stderr)) { + return; + } + + const mixed = mergeStream(); + + if (spawned.stdout) { + mixed.add(spawned.stdout); + } + + if (spawned.stderr) { + mixed.add(spawned.stderr); + } + + return mixed; +}; + +// On failure, `result.stdout|stderr|all` should contain the currently buffered stream +const getBufferedData = async (stream, streamPromise) => { + if (!stream) { + return; + } -var isStream = module.exports = function (stream) { - return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function'; + stream.destroy(); + + try { + return await streamPromise; + } catch (error) { + return error.bufferedData; + } }; -isStream.writable = function (stream) { - return isStream(stream) && stream.writable !== false && typeof stream._write === 'function' && typeof stream._writableState === 'object'; +const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => { + if (!stream || !buffer) { + return; + } + + if (encoding) { + return getStream(stream, {encoding, maxBuffer}); + } + + return getStream.buffer(stream, {maxBuffer}); }; -isStream.readable = function (stream) { - return isStream(stream) && stream.readable !== false && typeof stream._read === 'function' && typeof stream._readableState === 'object'; +// Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all) +const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => { + const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer}); + const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer}); + const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2}); + + try { + return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]); + } catch (error) { + return Promise.all([ + {error, signal: error.signal, timedOut: error.timedOut}, + getBufferedData(stdout, stdoutPromise), + getBufferedData(stderr, stderrPromise), + getBufferedData(all, allPromise) + ]); + } }; -isStream.duplex = function (stream) { - return isStream.writable(stream) && isStream.readable(stream); +const validateInputSync = ({input}) => { + if (isStream(input)) { + throw new TypeError('The `input` option cannot be a stream in sync mode'); + } }; -isStream.transform = function (stream) { - return isStream.duplex(stream) && typeof stream._transform === 'function' && typeof stream._transformState === 'object'; +module.exports = { + handleInput, + makeAllStream, + getSpawnedResult, + validateInputSync }; + /***/ }), -/* 143 */ +/* 150 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const isStream = stream => + stream !== null && + typeof stream === 'object' && + typeof stream.pipe === 'function'; + +isStream.writable = stream => + isStream(stream) && + stream.writable !== false && + typeof stream._write === 'function' && + typeof stream._writableState === 'object'; + +isStream.readable = stream => + isStream(stream) && + stream.readable !== false && + typeof stream._read === 'function' && + typeof stream._readableState === 'object'; + +isStream.duplex = stream => + isStream.writable(stream) && + isStream.readable(stream); + +isStream.transform = stream => + isStream.duplex(stream) && + typeof stream._transform === 'function' && + typeof stream._transformState === 'object'; + +module.exports = isStream; + + +/***/ }), +/* 151 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pump = __webpack_require__(144); -const bufferStream = __webpack_require__(146); +const pump = __webpack_require__(152); +const bufferStream = __webpack_require__(154); class MaxBufferError extends Error { constructor() { @@ -21745,21 +21130,25 @@ class MaxBufferError extends Error { } } -function getStream(inputStream, options) { +async function getStream(inputStream, options) { if (!inputStream) { return Promise.reject(new Error('Expected a stream')); } - options = Object.assign({maxBuffer: Infinity}, options); + options = { + maxBuffer: Infinity, + ...options + }; const {maxBuffer} = options; let stream; - return new Promise((resolve, reject) => { + await new Promise((resolve, reject) => { const rejectPromise = error => { if (error) { // A null check error.bufferedData = stream.getBufferedValue(); } + reject(error); }; @@ -21777,21 +21166,25 @@ function getStream(inputStream, options) { rejectPromise(new MaxBufferError()); } }); - }).then(() => stream.getBufferedValue()); + }); + + return stream.getBufferedValue(); } module.exports = getStream; -module.exports.buffer = (stream, options) => getStream(stream, Object.assign({}, options, {encoding: 'buffer'})); -module.exports.array = (stream, options) => getStream(stream, Object.assign({}, options, {array: true})); +// TODO: Remove this for the next major release +module.exports.default = getStream; +module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); +module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); module.exports.MaxBufferError = MaxBufferError; /***/ }), -/* 144 */ +/* 152 */ /***/ (function(module, exports, __webpack_require__) { var once = __webpack_require__(52) -var eos = __webpack_require__(145) +var eos = __webpack_require__(153) var fs = __webpack_require__(23) // we only need fs to get the ReadStream and WriteStream prototypes var noop = function () {} @@ -21875,7 +21268,7 @@ module.exports = pump /***/ }), -/* 145 */ +/* 153 */ /***/ (function(module, exports, __webpack_require__) { var once = __webpack_require__(52); @@ -21968,186 +21361,223 @@ module.exports = eos; /***/ }), -/* 146 */ +/* 154 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const {PassThrough} = __webpack_require__(28); +const {PassThrough: PassThroughStream} = __webpack_require__(28); module.exports = options => { - options = Object.assign({}, options); + options = {...options}; const {array} = options; let {encoding} = options; - const buffer = encoding === 'buffer'; + const isBuffer = encoding === 'buffer'; let objectMode = false; if (array) { - objectMode = !(encoding || buffer); + objectMode = !(encoding || isBuffer); } else { encoding = encoding || 'utf8'; } - if (buffer) { + if (isBuffer) { encoding = null; } - let len = 0; - const ret = []; - const stream = new PassThrough({objectMode}); + const stream = new PassThroughStream({objectMode}); if (encoding) { stream.setEncoding(encoding); } + let length = 0; + const chunks = []; + stream.on('data', chunk => { - ret.push(chunk); + chunks.push(chunk); if (objectMode) { - len = ret.length; + length = chunks.length; } else { - len += chunk.length; + length += chunk.length; } }); stream.getBufferedValue = () => { if (array) { - return ret; + return chunks; } - return buffer ? Buffer.concat(ret, len) : ret.join(''); + return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); }; - stream.getBufferedLength = () => len; + stream.getBufferedLength = () => length; return stream; }; /***/ }), -/* 147 */ +/* 155 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = (promise, onFinally) => { - onFinally = onFinally || (() => {}); - return promise.then( - val => new Promise(resolve => { - resolve(onFinally()); - }).then(() => val), - err => new Promise(resolve => { - resolve(onFinally()); - }).then(() => { - throw err; - }) - ); -}; +const { PassThrough } = __webpack_require__(28); + +module.exports = function (/*streams...*/) { + var sources = [] + var output = new PassThrough({objectMode: true}) + + output.setMaxListeners(0) + + output.add = add + output.isEmpty = isEmpty + + output.on('unpipe', remove) + + Array.prototype.slice.call(arguments).forEach(add) + + return output + + function add (source) { + if (Array.isArray(source)) { + source.forEach(add) + return this + } + + sources.push(source); + source.once('end', remove.bind(null, source)) + source.once('error', output.emit.bind(output, 'error')) + source.pipe(output, {end: false}) + return this + } + + function isEmpty () { + return sources.length == 0; + } + + function remove (source) { + sources = sources.filter(function (it) { return it !== source }) + if (!sources.length && output.readable) { output.end() } + } +} /***/ }), -/* 148 */ +/* 156 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -// Older verions of Node.js might not have `util.getSystemErrorName()`. -// In that case, fall back to a deprecated internal. -const util = __webpack_require__(29); +const mergePromiseProperty = (spawned, promise, property) => { + // Starting the main `promise` is deferred to avoid consuming streams + const value = typeof promise === 'function' ? + (...args) => promise()[property](...args) : + promise[property].bind(promise); -let uv; + Object.defineProperty(spawned, property, { + value, + writable: true, + enumerable: false, + configurable: true + }); +}; -if (typeof util.getSystemErrorName === 'function') { - module.exports = util.getSystemErrorName; -} else { - try { - uv = process.binding('uv'); +// The return value is a mixin of `childProcess` and `Promise` +const mergePromise = (spawned, promise) => { + mergePromiseProperty(spawned, promise, 'then'); + mergePromiseProperty(spawned, promise, 'catch'); - if (typeof uv.errname !== 'function') { - throw new TypeError('uv.errname is not a function'); - } - } catch (err) { - console.error('execa/lib/errname: unable to establish process.binding(\'uv\')', err); - uv = null; + // TODO: Remove the `if`-guard when targeting Node.js 10 + if (Promise.prototype.finally) { + mergePromiseProperty(spawned, promise, 'finally'); } - module.exports = code => errname(uv, code); -} + return spawned; +}; -// Used for testing the fallback behavior -module.exports.__test__ = errname; +// Use promises instead of `child_process` events +const getSpawnedPromise = spawned => { + return new Promise((resolve, reject) => { + spawned.on('exit', (exitCode, signal) => { + resolve({exitCode, signal}); + }); -function errname(uv, code) { - if (uv) { - return uv.errname(code); - } + spawned.on('error', error => { + reject(error); + }); - if (!(code < 0)) { - throw new Error('err >= 0'); - } + if (spawned.stdin) { + spawned.stdin.on('error', error => { + reject(error); + }); + } + }); +}; - return `Unknown system error ${code}`; -} +module.exports = { + mergePromise, + getSpawnedPromise +}; /***/ }), -/* 149 */ +/* 157 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const alias = ['stdin', 'stdout', 'stderr']; - -const hasAlias = opts => alias.some(x => Boolean(opts[x])); +const SPACES_REGEXP = / +/g; -module.exports = opts => { - if (!opts) { - return null; +const joinCommand = (file, args = []) => { + if (!Array.isArray(args)) { + return file; } - if (opts.stdio && hasAlias(opts)) { - throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${alias.map(x => `\`${x}\``).join(', ')}`); - } + return [file, ...args].join(' '); +}; - if (typeof opts.stdio === 'string') { - return opts.stdio; +// Allow spaces to be escaped by a backslash if not meant as a delimiter +const handleEscaping = (tokens, token, index) => { + if (index === 0) { + return [token]; } - const stdio = opts.stdio || []; + const previousToken = tokens[tokens.length - 1]; - if (!Array.isArray(stdio)) { - throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); + if (previousToken.endsWith('\\')) { + return [...tokens.slice(0, -1), `${previousToken.slice(0, -1)} ${token}`]; } - const result = []; - const len = Math.max(stdio.length, alias.length); - - for (let i = 0; i < len; i++) { - let value = null; - - if (stdio[i] !== undefined) { - value = stdio[i]; - } else if (opts[alias[i]] !== undefined) { - value = opts[alias[i]]; - } + return [...tokens, token]; +}; - result[i] = value; - } +// Handle `execa.command()` +const parseCommand = command => { + return command + .trim() + .split(SPACES_REGEXP) + .reduce(handleEscaping, []); +}; - return result; +module.exports = { + joinCommand, + parseCommand }; /***/ }), -/* 150 */ +/* 158 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(151); +const chalk = __webpack_require__(159); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -22169,16 +21599,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 151 */ +/* 159 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(152); -const stdoutColor = __webpack_require__(153).stdout; +const ansiStyles = __webpack_require__(160); +const stdoutColor = __webpack_require__(161).stdout; -const template = __webpack_require__(154); +const template = __webpack_require__(162); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -22404,7 +21834,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 152 */ +/* 160 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -22577,7 +22007,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 153 */ +/* 161 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -22719,7 +22149,7 @@ module.exports = { /***/ }), -/* 154 */ +/* 162 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -22854,7 +22284,7 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 155 */ +/* 163 */ /***/ (function(module, exports, __webpack_require__) { // Copyright IBM Corp. 2014,2018. All Rights Reserved. @@ -22862,12 +22292,12 @@ module.exports = (chalk, tmp) => { // This file is licensed under the Apache License 2.0. // License text available at https://opensource.org/licenses/Apache-2.0 -module.exports = __webpack_require__(156); -module.exports.cli = __webpack_require__(160); +module.exports = __webpack_require__(164); +module.exports.cli = __webpack_require__(168); /***/ }), -/* 156 */ +/* 164 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -22882,9 +22312,9 @@ var stream = __webpack_require__(28); var util = __webpack_require__(29); var fs = __webpack_require__(23); -var through = __webpack_require__(157); -var duplexer = __webpack_require__(158); -var StringDecoder = __webpack_require__(159).StringDecoder; +var through = __webpack_require__(165); +var duplexer = __webpack_require__(166); +var StringDecoder = __webpack_require__(167).StringDecoder; module.exports = Logger; @@ -23073,7 +22503,7 @@ function lineMerger(host) { /***/ }), -/* 157 */ +/* 165 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(28) @@ -23187,7 +22617,7 @@ function through (write, end, opts) { /***/ }), -/* 158 */ +/* 166 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(28) @@ -23280,13 +22710,13 @@ function duplex(writer, reader) { /***/ }), -/* 159 */ +/* 167 */ /***/ (function(module, exports) { module.exports = require("string_decoder"); /***/ }), -/* 160 */ +/* 168 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -23297,11 +22727,11 @@ module.exports = require("string_decoder"); -var minimist = __webpack_require__(161); +var minimist = __webpack_require__(169); var path = __webpack_require__(16); -var Logger = __webpack_require__(156); -var pkg = __webpack_require__(162); +var Logger = __webpack_require__(164); +var pkg = __webpack_require__(170); module.exports = cli; @@ -23355,7 +22785,7 @@ function usage($0, p) { /***/ }), -/* 161 */ +/* 169 */ /***/ (function(module, exports) { module.exports = function (args, opts) { @@ -23597,13 +23027,13 @@ function isNumber (x) { /***/ }), -/* 162 */ +/* 170 */ /***/ (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\"}}"); /***/ }), -/* 163 */ +/* 171 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23616,7 +23046,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(164); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(172); /* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(55); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(36); @@ -23709,7 +23139,7 @@ function packagesFromGlobPattern({ } /***/ }), -/* 164 */ +/* 172 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23774,7 +23204,7 @@ function getProjectPaths(rootPath, options = {}) { } /***/ }), -/* 165 */ +/* 173 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -23782,9 +23212,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(166); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(174); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(181); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(189); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); @@ -23884,18 +23314,18 @@ const CleanCommand = { }; /***/ }), -/* 166 */ +/* 174 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globby = __webpack_require__(167); -const isPathCwd = __webpack_require__(174); -const isPathInCwd = __webpack_require__(175); -const pify = __webpack_require__(178); -const rimraf = __webpack_require__(179); -const pMap = __webpack_require__(180); +const globby = __webpack_require__(175); +const isPathCwd = __webpack_require__(182); +const isPathInCwd = __webpack_require__(183); +const pify = __webpack_require__(186); +const rimraf = __webpack_require__(187); +const pMap = __webpack_require__(188); const rimrafP = pify(rimraf); @@ -23961,16 +23391,16 @@ module.exports.sync = (patterns, options) => { /***/ }), -/* 167 */ +/* 175 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Promise = __webpack_require__(168); -var arrayUnion = __webpack_require__(170); -var objectAssign = __webpack_require__(172); +var Promise = __webpack_require__(176); +var arrayUnion = __webpack_require__(178); +var objectAssign = __webpack_require__(180); var glob = __webpack_require__(37); -var pify = __webpack_require__(173); +var pify = __webpack_require__(181); var globP = pify(glob, Promise).bind(glob); @@ -24056,17 +23486,17 @@ module.exports.hasMagic = function (patterns, opts) { /***/ }), -/* 168 */ +/* 176 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = typeof Promise === 'function' ? Promise : __webpack_require__(169); +module.exports = typeof Promise === 'function' ? Promise : __webpack_require__(177); /***/ }), -/* 169 */ +/* 177 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24365,12 +23795,12 @@ module.exports = Promise; /***/ }), -/* 170 */ +/* 178 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(171); +var arrayUniq = __webpack_require__(179); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -24378,7 +23808,7 @@ module.exports = function () { /***/ }), -/* 171 */ +/* 179 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24447,7 +23877,7 @@ if ('Set' in global) { /***/ }), -/* 172 */ +/* 180 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24544,7 +23974,7 @@ module.exports = shouldUseNative() ? Object.assign : function (target, source) { /***/ }), -/* 173 */ +/* 181 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24619,7 +24049,7 @@ pify.all = pify; /***/ }), -/* 174 */ +/* 182 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24630,24 +24060,24 @@ module.exports = path_ => path.resolve(path_) === process.cwd(); /***/ }), -/* 175 */ +/* 183 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const isPathInside = __webpack_require__(176); +const isPathInside = __webpack_require__(184); module.exports = path => isPathInside(path, process.cwd()); /***/ }), -/* 176 */ +/* 184 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathIsInside = __webpack_require__(177); +const pathIsInside = __webpack_require__(185); module.exports = (childPath, parentPath) => { childPath = path.resolve(childPath); @@ -24662,7 +24092,7 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 177 */ +/* 185 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24697,7 +24127,7 @@ function stripTrailingSep(thePath) { /***/ }), -/* 178 */ +/* 186 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -24772,7 +24202,7 @@ module.exports = (input, options) => { /***/ }), -/* 179 */ +/* 187 */ /***/ (function(module, exports, __webpack_require__) { module.exports = rimraf @@ -25142,7 +24572,7 @@ function rmkidsSync (p, options) { /***/ }), -/* 180 */ +/* 188 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -25221,15 +24651,15 @@ module.exports.default = pMap; /***/ }), -/* 181 */ +/* 189 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(182); -const cliCursor = __webpack_require__(186); -const cliSpinners = __webpack_require__(190); -const logSymbols = __webpack_require__(150); +const chalk = __webpack_require__(190); +const cliCursor = __webpack_require__(194); +const cliSpinners = __webpack_require__(198); +const logSymbols = __webpack_require__(158); class Ora { constructor(options) { @@ -25376,16 +24806,16 @@ module.exports.promise = (action, options) => { /***/ }), -/* 182 */ +/* 190 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(183); -const stdoutColor = __webpack_require__(184).stdout; +const ansiStyles = __webpack_require__(191); +const stdoutColor = __webpack_require__(192).stdout; -const template = __webpack_require__(185); +const template = __webpack_require__(193); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -25611,7 +25041,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 183 */ +/* 191 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -25784,7 +25214,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 184 */ +/* 192 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -25926,7 +25356,7 @@ module.exports = { /***/ }), -/* 185 */ +/* 193 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -26061,12 +25491,12 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 186 */ +/* 194 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(187); +const restoreCursor = __webpack_require__(195); let hidden = false; @@ -26107,12 +25537,12 @@ exports.toggle = (force, stream) => { /***/ }), -/* 187 */ +/* 195 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(188); +const onetime = __webpack_require__(196); const signalExit = __webpack_require__(110); module.exports = onetime(() => { @@ -26123,12 +25553,12 @@ module.exports = onetime(() => { /***/ }), -/* 188 */ +/* 196 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(189); +const mimicFn = __webpack_require__(197); module.exports = (fn, opts) => { // TODO: Remove this in v3 @@ -26169,7 +25599,7 @@ module.exports = (fn, opts) => { /***/ }), -/* 189 */ +/* 197 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -26185,22 +25615,22 @@ module.exports = (to, from) => { /***/ }), -/* 190 */ +/* 198 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(191); +module.exports = __webpack_require__(199); /***/ }), -/* 191 */ +/* 199 */ /***/ (function(module) { module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]}}"); /***/ }), -/* 192 */ +/* 200 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26260,7 +25690,7 @@ const RunCommand = { }; /***/ }), -/* 193 */ +/* 201 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26271,7 +25701,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(35); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(36); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(194); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(202); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -26355,14 +25785,14 @@ const WatchCommand = { }; /***/ }), -/* 194 */ +/* 202 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; }); -/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(195); -/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(203); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(302); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -26429,168 +25859,168 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 195 */ +/* 203 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); +/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return _internal_Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]; }); -/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(222); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__["ConnectableObservable"]; }); -/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(219); +/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(227); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__["GroupedObservable"]; }); -/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(211); +/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(219); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observable", function() { return _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__["observable"]; }); -/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(215); +/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(223); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return _internal_Subject__WEBPACK_IMPORTED_MODULE_4__["Subject"]; }); -/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(220); +/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(228); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__["BehaviorSubject"]; }); -/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(221); +/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(229); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__["ReplaySubject"]; }); -/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(238); +/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(246); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__["AsyncSubject"]; }); -/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(239); +/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(247); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asap"]; }); -/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(243); +/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(251); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["async"]; }); -/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(222); +/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(230); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queue"]; }); -/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(244); +/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(252); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrame"]; }); -/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(247); +/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(255); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualTimeScheduler"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualAction"]; }); -/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(228); +/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(236); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Scheduler", function() { return _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__["Scheduler"]; }); -/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(204); +/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(212); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__["Subscription"]; }); -/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(198); +/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(206); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__["Subscriber"]; }); -/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(230); +/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(238); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return _internal_Notification__WEBPACK_IMPORTED_MODULE_16__["Notification"]; }); -/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(212); +/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(220); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__["pipe"]; }); -/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(213); +/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(221); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "noop", function() { return _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__["noop"]; }); -/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(248); +/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(256); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "identity", function() { return _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__["identity"]; }); -/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(249); +/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(257); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__["isObservable"]; }); -/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(250); +/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(258); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__["ArgumentOutOfRangeError"]; }); -/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(251); +/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(259); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__["EmptyError"]; }); -/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(216); +/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(224); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__["ObjectUnsubscribedError"]; }); -/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(209); +/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(217); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__["UnsubscriptionError"]; }); -/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(252); +/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(260); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__["TimeoutError"]; }); -/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(253); +/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(261); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__["bindCallback"]; }); -/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(255); +/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(263); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__["bindNodeCallback"]; }); -/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(256); +/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(264); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__["combineLatest"]; }); -/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(267); +/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(275); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__["concat"]; }); -/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(277); +/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(285); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__["defer"]; }); -/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(231); +/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(239); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["empty"]; }); -/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(278); +/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(286); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__["forkJoin"]; }); -/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(268); +/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(276); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "from", function() { return _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__["from"]; }); -/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(279); +/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(287); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__["fromEvent"]; }); -/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(280); +/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(288); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__["fromEventPattern"]; }); -/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(281); +/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(289); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__["generate"]; }); -/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(282); +/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(290); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__["iif"]; }); -/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(283); +/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(291); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__["interval"]; }); -/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(285); +/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(293); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__["merge"]; }); -/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(286); +/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(294); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "never", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["never"]; }); -/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(232); +/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(240); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "of", function() { return _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__["of"]; }); -/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(287); +/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(295); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(288); +/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(296); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__["pairs"]; }); -/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(289); +/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(297); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__["race"]; }); -/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(290); +/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(298); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "range", function() { return _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__["range"]; }); -/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(237); +/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(245); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__["throwError"]; }); -/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(291); +/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(299); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__["timer"]; }); -/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(292); +/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(300); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "using", function() { return _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__["using"]; }); -/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(293); +/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(301); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__["zip"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["EMPTY"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["NEVER"]; }); -/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(202); +/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(210); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "config", function() { return _internal_config__WEBPACK_IMPORTED_MODULE_50__["config"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -26651,16 +26081,16 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 196 */ +/* 204 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return Observable; }); -/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(197); -/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(211); -/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(202); +/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(205); +/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(219); +/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(220); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(210); /** PURE_IMPORTS_START _util_toSubscriber,_internal_symbol_observable,_util_pipe,_config PURE_IMPORTS_END */ @@ -26774,15 +26204,15 @@ function getPromiseCtor(promiseCtor) { /***/ }), -/* 197 */ +/* 205 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toSubscriber", function() { return toSubscriber; }); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(198); -/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(210); -/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(201); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(206); +/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(218); +/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(209); /** PURE_IMPORTS_START _Subscriber,_symbol_rxSubscriber,_Observer PURE_IMPORTS_END */ @@ -26805,19 +26235,19 @@ function toSubscriber(nextOrObserver, error, complete) { /***/ }), -/* 198 */ +/* 206 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return Subscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(200); -/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(201); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(204); -/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(210); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(202); -/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(203); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(208); +/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(209); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(212); +/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(218); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(210); +/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(211); /** PURE_IMPORTS_START tslib,_util_isFunction,_Observer,_Subscription,_internal_symbol_rxSubscriber,_config,_util_hostReportError PURE_IMPORTS_END */ @@ -27059,7 +26489,7 @@ function isTrustedSubscriber(obj) { /***/ }), -/* 199 */ +/* 207 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27272,7 +26702,7 @@ function __importDefault(mod) { /***/ }), -/* 200 */ +/* 208 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27286,14 +26716,14 @@ function isFunction(x) { /***/ }), -/* 201 */ +/* 209 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(202); -/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(203); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(210); +/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(211); /** PURE_IMPORTS_START _config,_util_hostReportError PURE_IMPORTS_END */ @@ -27314,7 +26744,7 @@ var empty = { /***/ }), -/* 202 */ +/* 210 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27342,7 +26772,7 @@ var config = { /***/ }), -/* 203 */ +/* 211 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27356,18 +26786,18 @@ function hostReportError(err) { /***/ }), -/* 204 */ +/* 212 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return Subscription; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(205); -/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(200); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(208); -/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(209); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); +/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(216); +/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(217); /** PURE_IMPORTS_START _util_isArray,_util_isObject,_util_isFunction,_util_tryCatch,_util_errorObject,_util_UnsubscriptionError PURE_IMPORTS_END */ @@ -27503,7 +26933,7 @@ function flattenUnsubscriptionErrors(errors) { /***/ }), -/* 205 */ +/* 213 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27515,7 +26945,7 @@ var isArray = Array.isArray || (function (x) { return x && typeof x.length === ' /***/ }), -/* 206 */ +/* 214 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27529,13 +26959,13 @@ function isObject(x) { /***/ }), -/* 207 */ +/* 215 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tryCatch", function() { return tryCatch; }); -/* harmony import */ var _errorObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(208); +/* harmony import */ var _errorObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(216); /** PURE_IMPORTS_START _errorObject PURE_IMPORTS_END */ var tryCatchTarget; @@ -27556,7 +26986,7 @@ function tryCatch(fn) { /***/ }), -/* 208 */ +/* 216 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27568,13 +26998,13 @@ var errorObject = { e: {} }; /***/ }), -/* 209 */ +/* 217 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return UnsubscriptionError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var UnsubscriptionError = /*@__PURE__*/ (function (_super) { @@ -27594,7 +27024,7 @@ var UnsubscriptionError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 210 */ +/* 218 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27610,7 +27040,7 @@ var $$rxSubscriber = rxSubscriber; /***/ }), -/* 211 */ +/* 219 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27622,14 +27052,14 @@ var observable = typeof Symbol === 'function' && Symbol.observable || '@@observa /***/ }), -/* 212 */ +/* 220 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return pipe; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipeFromArray", function() { return pipeFromArray; }); -/* harmony import */ var _noop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); +/* harmony import */ var _noop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(221); /** PURE_IMPORTS_START _noop PURE_IMPORTS_END */ function pipe() { @@ -27654,7 +27084,7 @@ function pipeFromArray(fns) { /***/ }), -/* 213 */ +/* 221 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27666,19 +27096,19 @@ function noop() { } /***/ }), -/* 214 */ +/* 222 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return ConnectableObservable; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "connectableObservableDescriptor", function() { return connectableObservableDescriptor; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(196); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(198); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(204); -/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(218); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(212); +/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(226); /** PURE_IMPORTS_START tslib,_Subject,_Observable,_Subscriber,_Subscription,_operators_refCount PURE_IMPORTS_END */ @@ -27825,7 +27255,7 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 215 */ +/* 223 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27833,13 +27263,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubjectSubscriber", function() { return SubjectSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return Subject; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnonymousSubject", function() { return AnonymousSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(196); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(198); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(204); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(216); -/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(217); -/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(210); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(212); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(224); +/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(225); +/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(218); /** PURE_IMPORTS_START tslib,_Observable,_Subscriber,_Subscription,_util_ObjectUnsubscribedError,_SubjectSubscription,_internal_symbol_rxSubscriber PURE_IMPORTS_END */ @@ -28001,13 +27431,13 @@ var AnonymousSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 216 */ +/* 224 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return ObjectUnsubscribedError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var ObjectUnsubscribedError = /*@__PURE__*/ (function (_super) { @@ -28025,14 +27455,14 @@ var ObjectUnsubscribedError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 217 */ +/* 225 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubjectSubscription", function() { return SubjectSubscription; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */ @@ -28068,14 +27498,14 @@ var SubjectSubscription = /*@__PURE__*/ (function (_super) { /***/ }), -/* 218 */ +/* 226 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return refCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -28137,18 +27567,18 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 219 */ +/* 227 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return groupBy; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return GroupedObservable; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(196); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(215); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(204); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(223); /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription,_Observable,_Subject PURE_IMPORTS_END */ @@ -28334,15 +27764,15 @@ var InnerRefCountSubscription = /*@__PURE__*/ (function (_super) { /***/ }), -/* 220 */ +/* 228 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return BehaviorSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(216); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(224); /** PURE_IMPORTS_START tslib,_Subject,_util_ObjectUnsubscribedError PURE_IMPORTS_END */ @@ -28389,19 +27819,19 @@ var BehaviorSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 221 */ +/* 229 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return ReplaySubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(222); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(204); -/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(229); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(216); -/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(217); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(212); +/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(237); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(224); +/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(225); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_queue,_Subscription,_operators_observeOn,_util_ObjectUnsubscribedError,_SubjectSubscription PURE_IMPORTS_END */ @@ -28522,14 +27952,14 @@ var ReplayEvent = /*@__PURE__*/ (function () { /***/ }), -/* 222 */ +/* 230 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "queue", function() { return queue; }); -/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(223); -/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(226); +/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(231); +/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(234); /** PURE_IMPORTS_START _QueueAction,_QueueScheduler PURE_IMPORTS_END */ @@ -28538,14 +27968,14 @@ var queue = /*@__PURE__*/ new _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__["Queu /***/ }), -/* 223 */ +/* 231 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueAction", function() { return QueueAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */ @@ -28590,14 +28020,14 @@ var QueueAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 224 */ +/* 232 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncAction", function() { return AsyncAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); /** PURE_IMPORTS_START tslib,_Action PURE_IMPORTS_END */ @@ -28695,14 +28125,14 @@ var AsyncAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 225 */ +/* 233 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Action", function() { return Action; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */ @@ -28724,14 +28154,14 @@ var Action = /*@__PURE__*/ (function (_super) { /***/ }), -/* 226 */ +/* 234 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueScheduler", function() { return QueueScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(227); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -28747,14 +28177,14 @@ var QueueScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 227 */ +/* 235 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncScheduler", function() { return AsyncScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(228); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(236); /** PURE_IMPORTS_START tslib,_Scheduler PURE_IMPORTS_END */ @@ -28816,7 +28246,7 @@ var AsyncScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 228 */ +/* 236 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28844,7 +28274,7 @@ var Scheduler = /*@__PURE__*/ (function () { /***/ }), -/* 229 */ +/* 237 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28853,9 +28283,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnOperator", function() { return ObserveOnOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnSubscriber", function() { return ObserveOnSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnMessage", function() { return ObserveOnMessage; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(238); /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -28925,15 +28355,15 @@ var ObserveOnMessage = /*@__PURE__*/ (function () { /***/ }), -/* 230 */ +/* 238 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return Notification; }); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(231); -/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); -/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(237); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(239); +/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); +/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(245); /** PURE_IMPORTS_START _observable_empty,_observable_of,_observable_throwError PURE_IMPORTS_END */ @@ -29007,7 +28437,7 @@ var Notification = /*@__PURE__*/ (function () { /***/ }), -/* 231 */ +/* 239 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29015,7 +28445,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return EMPTY; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "emptyScheduled", function() { return emptyScheduled; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ var EMPTY = /*@__PURE__*/ new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) { return subscriber.complete(); }); @@ -29029,16 +28459,16 @@ function emptyScheduled(scheduler) { /***/ }), -/* 232 */ +/* 240 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "of", function() { return of; }); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(233); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(234); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(231); -/* harmony import */ var _scalar__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(236); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(241); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); +/* harmony import */ var _scalar__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(244); /** PURE_IMPORTS_START _util_isScheduler,_fromArray,_empty,_scalar PURE_IMPORTS_END */ @@ -29069,7 +28499,7 @@ function of() { /***/ }), -/* 233 */ +/* 241 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29083,15 +28513,15 @@ function isScheduler(value) { /***/ }), -/* 234 */ +/* 242 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromArray", function() { return fromArray; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(235); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(243); /** PURE_IMPORTS_START _Observable,_Subscription,_util_subscribeToArray PURE_IMPORTS_END */ @@ -29122,7 +28552,7 @@ function fromArray(input, scheduler) { /***/ }), -/* 235 */ +/* 243 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29143,13 +28573,13 @@ var subscribeToArray = function (array) { /***/ }), -/* 236 */ +/* 244 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scalar", function() { return scalar; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function scalar(value) { @@ -29165,13 +28595,13 @@ function scalar(value) { /***/ }), -/* 237 */ +/* 245 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return throwError; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function throwError(error, scheduler) { @@ -29190,15 +28620,15 @@ function dispatch(_a) { /***/ }), -/* 238 */ +/* 246 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return AsyncSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); /** PURE_IMPORTS_START tslib,_Subject,_Subscription PURE_IMPORTS_END */ @@ -29249,14 +28679,14 @@ var AsyncSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 239 */ +/* 247 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asap", function() { return asap; }); -/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(240); -/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(248); +/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(250); /** PURE_IMPORTS_START _AsapAction,_AsapScheduler PURE_IMPORTS_END */ @@ -29265,15 +28695,15 @@ var asap = /*@__PURE__*/ new _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__["AsapSc /***/ }), -/* 240 */ +/* 248 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapAction", function() { return AsapAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(241); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(224); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(249); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(232); /** PURE_IMPORTS_START tslib,_util_Immediate,_AsyncAction PURE_IMPORTS_END */ @@ -29316,7 +28746,7 @@ var AsapAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 241 */ +/* 249 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29346,14 +28776,14 @@ var Immediate = { /***/ }), -/* 242 */ +/* 250 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapScheduler", function() { return AsapScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(227); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -29390,14 +28820,14 @@ var AsapScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 243 */ +/* 251 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "async", function() { return async; }); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(224); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(227); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(232); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); /** PURE_IMPORTS_START _AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ @@ -29406,14 +28836,14 @@ var async = /*@__PURE__*/ new _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__["Asyn /***/ }), -/* 244 */ +/* 252 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return animationFrame; }); -/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(245); -/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); +/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(253); +/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(254); /** PURE_IMPORTS_START _AnimationFrameAction,_AnimationFrameScheduler PURE_IMPORTS_END */ @@ -29422,14 +28852,14 @@ var animationFrame = /*@__PURE__*/ new _AnimationFrameScheduler__WEBPACK_IMPORTE /***/ }), -/* 245 */ +/* 253 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameAction", function() { return AnimationFrameAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */ @@ -29471,14 +28901,14 @@ var AnimationFrameAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 246 */ +/* 254 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameScheduler", function() { return AnimationFrameScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(227); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -29515,16 +28945,16 @@ var AnimationFrameScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 247 */ +/* 255 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return VirtualTimeScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return VirtualAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(224); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(227); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(235); /** PURE_IMPORTS_START tslib,_AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ @@ -29636,7 +29066,7 @@ var VirtualAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 248 */ +/* 256 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29650,13 +29080,13 @@ function identity(x) { /***/ }), -/* 249 */ +/* 257 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return isObservable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function isObservable(obj) { @@ -29666,13 +29096,13 @@ function isObservable(obj) { /***/ }), -/* 250 */ +/* 258 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return ArgumentOutOfRangeError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var ArgumentOutOfRangeError = /*@__PURE__*/ (function (_super) { @@ -29690,13 +29120,13 @@ var ArgumentOutOfRangeError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 251 */ +/* 259 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return EmptyError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var EmptyError = /*@__PURE__*/ (function (_super) { @@ -29714,13 +29144,13 @@ var EmptyError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 252 */ +/* 260 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return TimeoutError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var TimeoutError = /*@__PURE__*/ (function (_super) { @@ -29738,17 +29168,17 @@ var TimeoutError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 253 */ +/* 261 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return bindCallback; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(238); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(254); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(205); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(233); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(262); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(213); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(241); /** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_isArray,_util_isScheduler PURE_IMPORTS_END */ @@ -29851,15 +29281,15 @@ function dispatchError(state) { /***/ }), -/* 254 */ +/* 262 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "map", function() { return map; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MapOperator", function() { return MapOperator; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -29908,17 +29338,17 @@ var MapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 255 */ +/* 263 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return bindNodeCallback; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(238); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(254); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(233); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(205); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(262); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(241); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(213); /** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_isScheduler,_util_isArray PURE_IMPORTS_END */ @@ -30029,7 +29459,7 @@ function dispatchError(arg) { /***/ }), -/* 256 */ +/* 264 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30037,12 +29467,12 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestOperator", function() { return CombineLatestOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestSubscriber", function() { return CombineLatestSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(205); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(258); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(234); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(241); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(242); /** PURE_IMPORTS_START tslib,_util_isScheduler,_util_isArray,_OuterSubscriber,_util_subscribeToResult,_fromArray PURE_IMPORTS_END */ @@ -30147,14 +29577,14 @@ var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 257 */ +/* 265 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OuterSubscriber", function() { return OuterSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -30179,14 +29609,14 @@ var OuterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 258 */ +/* 266 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToResult", function() { return subscribeToResult; }); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(259); -/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(260); +/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(267); +/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(268); /** PURE_IMPORTS_START _InnerSubscriber,_subscribeTo PURE_IMPORTS_END */ @@ -30198,14 +29628,14 @@ function subscribeToResult(outerSubscriber, result, outerValue, outerIndex) { /***/ }), -/* 259 */ +/* 267 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InnerSubscriber", function() { return InnerSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -30237,22 +29667,22 @@ var InnerSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 260 */ +/* 268 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeTo", function() { return subscribeTo; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); -/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(261); -/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); -/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(264); -/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(265); -/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(266); -/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(206); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(263); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(211); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(243); +/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(269); +/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(270); +/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(272); +/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(273); +/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(274); +/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(214); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(271); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(219); /** PURE_IMPORTS_START _Observable,_subscribeToArray,_subscribeToPromise,_subscribeToIterable,_subscribeToObservable,_isArrayLike,_isPromise,_isObject,_symbol_iterator,_symbol_observable PURE_IMPORTS_END */ @@ -30300,13 +29730,13 @@ var subscribeTo = function (result) { /***/ }), -/* 261 */ +/* 269 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToPromise", function() { return subscribeToPromise; }); -/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(203); +/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(211); /** PURE_IMPORTS_START _hostReportError PURE_IMPORTS_END */ var subscribeToPromise = function (promise) { @@ -30325,13 +29755,13 @@ var subscribeToPromise = function (promise) { /***/ }), -/* 262 */ +/* 270 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToIterable", function() { return subscribeToIterable; }); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(263); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(271); /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */ var subscribeToIterable = function (iterable) { @@ -30362,7 +29792,7 @@ var subscribeToIterable = function (iterable) { /***/ }), -/* 263 */ +/* 271 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30383,13 +29813,13 @@ var $$iterator = iterator; /***/ }), -/* 264 */ +/* 272 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToObservable", function() { return subscribeToObservable; }); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(211); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(219); /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */ var subscribeToObservable = function (obj) { @@ -30407,7 +29837,7 @@ var subscribeToObservable = function (obj) { /***/ }), -/* 265 */ +/* 273 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30419,7 +29849,7 @@ var isArrayLike = (function (x) { return x && typeof x.length === 'number' && ty /***/ }), -/* 266 */ +/* 274 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30433,16 +29863,16 @@ function isPromise(value) { /***/ }), -/* 267 */ +/* 275 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; }); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(233); -/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(268); -/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(274); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(241); +/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276); +/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(282); /** PURE_IMPORTS_START _util_isScheduler,_of,_from,_operators_concatAll PURE_IMPORTS_END */ @@ -30462,22 +29892,22 @@ function concat() { /***/ }), -/* 268 */ +/* 276 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "from", function() { return from; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(266); -/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(265); -/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(269); -/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(270); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(234); -/* harmony import */ var _fromPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(271); -/* harmony import */ var _fromIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(272); -/* harmony import */ var _fromObservable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(273); -/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(260); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(274); +/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(273); +/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(277); +/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(278); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(242); +/* harmony import */ var _fromPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(279); +/* harmony import */ var _fromIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(280); +/* harmony import */ var _fromObservable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(281); +/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(268); /** PURE_IMPORTS_START _Observable,_util_isPromise,_util_isArrayLike,_util_isInteropObservable,_util_isIterable,_fromArray,_fromPromise,_fromIterable,_fromObservable,_util_subscribeTo PURE_IMPORTS_END */ @@ -30516,13 +29946,13 @@ function from(input, scheduler) { /***/ }), -/* 269 */ +/* 277 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isInteropObservable", function() { return isInteropObservable; }); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(211); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(219); /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */ function isInteropObservable(input) { @@ -30532,13 +29962,13 @@ function isInteropObservable(input) { /***/ }), -/* 270 */ +/* 278 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isIterable", function() { return isIterable; }); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(263); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(271); /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */ function isIterable(input) { @@ -30548,15 +29978,15 @@ function isIterable(input) { /***/ }), -/* 271 */ +/* 279 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromPromise", function() { return fromPromise; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _util_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(261); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var _util_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(269); /** PURE_IMPORTS_START _Observable,_Subscription,_util_subscribeToPromise PURE_IMPORTS_END */ @@ -30586,16 +30016,16 @@ function fromPromise(input, scheduler) { /***/ }), -/* 272 */ +/* 280 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromIterable", function() { return fromIterable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(263); -/* harmony import */ var _util_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(271); +/* harmony import */ var _util_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(270); /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_iterator,_util_subscribeToIterable PURE_IMPORTS_END */ @@ -30651,16 +30081,16 @@ function fromIterable(input, scheduler) { /***/ }), -/* 273 */ +/* 281 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromObservable", function() { return fromObservable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(211); -/* harmony import */ var _util_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(264); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(219); +/* harmony import */ var _util_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(272); /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_observable,_util_subscribeToObservable PURE_IMPORTS_END */ @@ -30689,13 +30119,13 @@ function fromObservable(input, scheduler) { /***/ }), -/* 274 */ +/* 282 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return concatAll; }); -/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(275); +/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(283); /** PURE_IMPORTS_START _mergeAll PURE_IMPORTS_END */ function concatAll() { @@ -30705,14 +30135,14 @@ function concatAll() { /***/ }), -/* 275 */ +/* 283 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return mergeAll; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(248); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(284); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); /** PURE_IMPORTS_START _mergeMap,_util_identity PURE_IMPORTS_END */ @@ -30726,7 +30156,7 @@ function mergeAll(concurrent) { /***/ }), -/* 276 */ +/* 284 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30734,11 +30164,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeMap", function() { return mergeMap; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapOperator", function() { return MergeMapOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapSubscriber", function() { return MergeMapSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(258); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(254); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(268); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(266); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(265); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(276); /** PURE_IMPORTS_START tslib,_util_subscribeToResult,_OuterSubscriber,_map,_observable_from PURE_IMPORTS_END */ @@ -30837,15 +30267,15 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 277 */ +/* 285 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return defer; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(268); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(231); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); /** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */ @@ -30868,19 +30298,19 @@ function defer(observableFactory) { /***/ }), -/* 278 */ +/* 286 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return forkJoin; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(196); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(205); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(231); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(258); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(257); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(254); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(265); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(262); /** PURE_IMPORTS_START tslib,_Observable,_util_isArray,_empty,_util_subscribeToResult,_OuterSubscriber,_operators_map PURE_IMPORTS_END */ @@ -30958,16 +30388,16 @@ var ForkJoinSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 279 */ +/* 287 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return fromEvent; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(205); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(200); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(254); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */ @@ -31034,16 +30464,16 @@ function isEventTarget(sourceObj) { /***/ }), -/* 280 */ +/* 288 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return fromEventPattern; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(205); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(200); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(254); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */ @@ -31079,15 +30509,15 @@ function fromEventPattern(addHandler, removeHandler, resultSelector) { /***/ }), -/* 281 */ +/* 289 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return generate; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(248); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(233); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(241); /** PURE_IMPORTS_START _Observable,_util_identity,_util_isScheduler PURE_IMPORTS_END */ @@ -31216,14 +30646,14 @@ function dispatch(state) { /***/ }), -/* 282 */ +/* 290 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return iif; }); -/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(277); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(231); +/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(239); /** PURE_IMPORTS_START _defer,_empty PURE_IMPORTS_END */ @@ -31240,15 +30670,15 @@ function iif(condition, trueResult, falseResult) { /***/ }), -/* 283 */ +/* 291 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return interval; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(243); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(292); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric PURE_IMPORTS_END */ @@ -31280,13 +30710,13 @@ function dispatch(state) { /***/ }), -/* 284 */ +/* 292 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNumeric", function() { return isNumeric; }); -/* harmony import */ var _isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(205); +/* harmony import */ var _isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); /** PURE_IMPORTS_START _isArray PURE_IMPORTS_END */ function isNumeric(val) { @@ -31296,16 +30726,16 @@ function isNumeric(val) { /***/ }), -/* 285 */ +/* 293 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); -/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(275); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(234); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(241); +/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(283); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(242); /** PURE_IMPORTS_START _Observable,_util_isScheduler,_operators_mergeAll,_fromArray PURE_IMPORTS_END */ @@ -31337,15 +30767,15 @@ function merge() { /***/ }), -/* 286 */ +/* 294 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return NEVER; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "never", function() { return never; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(221); /** PURE_IMPORTS_START _Observable,_util_noop PURE_IMPORTS_END */ @@ -31357,16 +30787,16 @@ function never() { /***/ }), -/* 287 */ +/* 295 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(268); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(205); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(231); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239); /** PURE_IMPORTS_START _Observable,_from,_util_isArray,_empty PURE_IMPORTS_END */ @@ -31397,15 +30827,15 @@ function onErrorResumeNext() { /***/ }), -/* 288 */ +/* 296 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return pairs; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dispatch", function() { return dispatch; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); /** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */ @@ -31448,7 +30878,7 @@ function dispatch(state) { /***/ }), -/* 289 */ +/* 297 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -31456,11 +30886,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceOperator", function() { return RaceOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceSubscriber", function() { return RaceSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(205); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(234); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(242); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_util_isArray,_fromArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -31542,14 +30972,14 @@ var RaceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 290 */ +/* 298 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "range", function() { return range; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dispatch", function() { return dispatch; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function range(start, count, scheduler) { @@ -31600,16 +31030,16 @@ function dispatch(state) { /***/ }), -/* 291 */ +/* 299 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return timer; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(243); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(233); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(292); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(241); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -31654,15 +31084,15 @@ function dispatch(state) { /***/ }), -/* 292 */ +/* 300 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "using", function() { return using; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(196); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(268); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(231); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); /** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */ @@ -31699,7 +31129,7 @@ function using(resourceFactory, observableFactory) { /***/ }), -/* 293 */ +/* 301 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -31707,13 +31137,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipOperator", function() { return ZipOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipSubscriber", function() { return ZipSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(234); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(205); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(198); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(258); -/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(263); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); +/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(271); /** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_OuterSubscriber,_util_subscribeToResult,_.._internal_symbol_iterator PURE_IMPORTS_END */ @@ -31933,320 +31363,320 @@ var ZipBufferIterator = /*@__PURE__*/ (function (_super) { /***/ }), -/* 294 */ +/* 302 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(295); +/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(303); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__["audit"]; }); -/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(296); +/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__["auditTime"]; }); -/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(297); +/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(305); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__["buffer"]; }); -/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(298); +/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(306); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__["bufferCount"]; }); -/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(299); +/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(307); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__["bufferTime"]; }); -/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(300); +/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(308); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__["bufferToggle"]; }); -/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(301); +/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(309); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__["bufferWhen"]; }); -/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(302); +/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(310); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__["catchError"]; }); -/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(303); +/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(311); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__["combineAll"]; }); -/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(304); +/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(312); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__["combineLatest"]; }); -/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(305); +/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(313); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__["concat"]; }); -/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(274); +/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(282); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__["concatAll"]; }); -/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(306); +/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(314); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__["concatMap"]; }); -/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(307); +/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(315); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__["concatMapTo"]; }); -/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(308); +/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(316); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "count", function() { return _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__["count"]; }); -/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(309); +/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(317); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__["debounce"]; }); -/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(310); +/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(318); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__["debounceTime"]; }); -/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(311); +/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(319); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__["defaultIfEmpty"]; }); -/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(312); +/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(320); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__["delay"]; }); -/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(314); +/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(322); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__["delayWhen"]; }); -/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(315); +/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(323); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__["dematerialize"]; }); -/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(316); +/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(324); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__["distinct"]; }); -/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(317); +/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(325); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__["distinctUntilChanged"]; }); -/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(318); +/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(326); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__["distinctUntilKeyChanged"]; }); -/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(319); +/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(327); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__["elementAt"]; }); -/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(324); +/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(332); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__["endWith"]; }); -/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(325); +/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(333); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "every", function() { return _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__["every"]; }); -/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(326); +/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(334); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__["exhaust"]; }); -/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(327); +/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(335); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__["exhaustMap"]; }); -/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(328); +/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(336); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__["expand"]; }); -/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(320); +/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(328); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__["filter"]; }); -/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(329); +/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(337); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__["finalize"]; }); -/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(330); +/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(338); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "find", function() { return _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__["find"]; }); -/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(331); +/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(339); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__["findIndex"]; }); -/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(332); +/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(340); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "first", function() { return _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__["first"]; }); -/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(219); +/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(227); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__["groupBy"]; }); -/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(333); +/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(341); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__["ignoreElements"]; }); -/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(334); +/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(342); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__["isEmpty"]; }); -/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(335); +/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(343); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "last", function() { return _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__["last"]; }); -/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(254); +/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(262); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "map", function() { return _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__["map"]; }); -/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(337); +/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(345); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__["mapTo"]; }); -/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(338); +/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(346); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__["materialize"]; }); -/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(339); +/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(347); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "max", function() { return _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__["max"]; }); -/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(342); +/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(350); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__["merge"]; }); -/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(275); +/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(283); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__["mergeAll"]; }); -/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(276); +/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(284); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; }); -/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(343); +/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(351); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__["mergeMapTo"]; }); -/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(344); +/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(352); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__["mergeScan"]; }); -/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(345); +/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(353); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "min", function() { return _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__["min"]; }); -/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(346); +/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(354); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__["multicast"]; }); -/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(229); +/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(237); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observeOn", function() { return _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__["observeOn"]; }); -/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(347); +/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(355); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(348); +/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(356); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__["pairwise"]; }); -/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(349); +/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(357); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__["partition"]; }); -/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(351); +/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(359); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__["pluck"]; }); -/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(352); +/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(360); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__["publish"]; }); -/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(353); +/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(361); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__["publishBehavior"]; }); -/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(354); +/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(362); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__["publishLast"]; }); -/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(355); +/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(363); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__["publishReplay"]; }); -/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(356); +/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(364); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__["race"]; }); -/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(340); +/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(348); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__["reduce"]; }); -/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(357); +/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(365); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__["repeat"]; }); -/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(358); +/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(366); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__["repeatWhen"]; }); -/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(359); +/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(367); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__["retry"]; }); -/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(360); +/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(368); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__["retryWhen"]; }); -/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(218); +/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(226); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__["refCount"]; }); -/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(361); +/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(369); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__["sample"]; }); -/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(362); +/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(370); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__["sampleTime"]; }); -/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(341); +/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(349); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__["scan"]; }); -/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(363); +/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(371); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__["sequenceEqual"]; }); -/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(364); +/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(372); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "share", function() { return _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__["share"]; }); -/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(365); +/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(373); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__["shareReplay"]; }); -/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(366); +/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(374); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "single", function() { return _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__["single"]; }); -/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(367); +/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(375); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__["skip"]; }); -/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(368); +/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(376); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__["skipLast"]; }); -/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(369); +/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(377); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__["skipUntil"]; }); -/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(370); +/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(378); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__["skipWhile"]; }); -/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(371); +/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(379); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__["startWith"]; }); -/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(372); +/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(380); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__["subscribeOn"]; }); -/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(374); +/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(382); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__["switchAll"]; }); -/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(375); +/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(383); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__["switchMap"]; }); -/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(376); +/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(384); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__["switchMapTo"]; }); -/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(323); +/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(331); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "take", function() { return _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__["take"]; }); -/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(336); +/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(344); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__["takeLast"]; }); -/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(377); +/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(385); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__["takeUntil"]; }); -/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(378); +/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(386); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__["takeWhile"]; }); -/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(322); +/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(330); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__["tap"]; }); -/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(379); +/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(387); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__["throttle"]; }); -/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(380); +/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(388); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__["throttleTime"]; }); -/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(321); +/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(329); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__["throwIfEmpty"]; }); -/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(381); +/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(389); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__["timeInterval"]; }); -/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(382); +/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(390); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__["timeout"]; }); -/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(383); +/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(391); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__["timeoutWith"]; }); -/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(384); +/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(392); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__["timestamp"]; }); -/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(385); +/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(393); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__["toArray"]; }); -/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(386); +/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(394); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "window", function() { return _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__["window"]; }); -/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(387); +/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(395); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__["windowCount"]; }); -/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(388); +/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(396); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__["windowTime"]; }); -/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(389); +/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(397); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__["windowToggle"]; }); -/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(390); +/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(398); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__["windowWhen"]; }); -/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(391); +/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(399); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__["withLatestFrom"]; }); -/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(392); +/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(400); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__["zip"]; }); -/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(393); +/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(401); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__["zipAll"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -32358,17 +31788,17 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 295 */ +/* 303 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return audit; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(216); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -32441,15 +31871,15 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 296 */ +/* 304 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return auditTime; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(243); -/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); -/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(291); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); +/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(303); +/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(299); /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */ @@ -32464,15 +31894,15 @@ function auditTime(duration, scheduler) { /***/ }), -/* 297 */ +/* 305 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return buffer; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -32513,14 +31943,14 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 298 */ +/* 306 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return bufferCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -32614,16 +32044,16 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 299 */ +/* 307 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return bufferTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(243); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(198); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(233); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(241); /** PURE_IMPORTS_START tslib,_scheduler_async,_Subscriber,_util_isScheduler PURE_IMPORTS_END */ @@ -32775,16 +32205,16 @@ function dispatchBufferClose(arg) { /***/ }), -/* 300 */ +/* 308 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return bufferToggle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); /** PURE_IMPORTS_START tslib,_Subscription,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */ @@ -32895,18 +32325,18 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 301 */ +/* 309 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return bufferWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_Subscription,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -32992,15 +32422,15 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 302 */ +/* 310 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return catchError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -33049,13 +32479,13 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 303 */ +/* 311 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return combineAll; }); -/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(256); +/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(264); /** PURE_IMPORTS_START _observable_combineLatest PURE_IMPORTS_END */ function combineAll(project) { @@ -33065,15 +32495,15 @@ function combineAll(project) { /***/ }), -/* 304 */ +/* 312 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(205); -/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(268); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); +/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(264); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276); /** PURE_IMPORTS_START _util_isArray,_observable_combineLatest,_observable_from PURE_IMPORTS_END */ @@ -33097,13 +32527,13 @@ function combineLatest() { /***/ }), -/* 305 */ +/* 313 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; }); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(267); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(275); /** PURE_IMPORTS_START _observable_concat PURE_IMPORTS_END */ function concat() { @@ -33117,13 +32547,13 @@ function concat() { /***/ }), -/* 306 */ +/* 314 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return concatMap; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(284); /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */ function concatMap(project, resultSelector) { @@ -33133,13 +32563,13 @@ function concatMap(project, resultSelector) { /***/ }), -/* 307 */ +/* 315 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return concatMapTo; }); -/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(306); +/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(314); /** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */ function concatMapTo(innerObservable, resultSelector) { @@ -33149,14 +32579,14 @@ function concatMapTo(innerObservable, resultSelector) { /***/ }), -/* 308 */ +/* 316 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "count", function() { return count; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -33214,15 +32644,15 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 309 */ +/* 317 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return debounce; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -33302,15 +32732,15 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 310 */ +/* 318 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return debounceTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(243); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */ @@ -33378,14 +32808,14 @@ function dispatchNext(subscriber) { /***/ }), -/* 311 */ +/* 319 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return defaultIfEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -33428,17 +32858,17 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 312 */ +/* 320 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return delay; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(243); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(313); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(198); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(230); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(321); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(238); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -33532,7 +32962,7 @@ var DelayMessage = /*@__PURE__*/ (function () { /***/ }), -/* 313 */ +/* 321 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -33546,17 +32976,17 @@ function isDate(value) { /***/ }), -/* 314 */ +/* 322 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return delayWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(196); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -33687,14 +33117,14 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 315 */ +/* 323 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return dematerialize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -33725,16 +33155,16 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 316 */ +/* 324 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return distinct; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DistinctSubscriber", function() { return DistinctSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -33803,16 +33233,16 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 317 */ +/* 325 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return distinctUntilChanged; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); /** PURE_IMPORTS_START tslib,_Subscriber,_util_tryCatch,_util_errorObject PURE_IMPORTS_END */ @@ -33875,13 +33305,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 318 */ +/* 326 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return distinctUntilKeyChanged; }); -/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(317); +/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(325); /** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */ function distinctUntilKeyChanged(key, compare) { @@ -33891,17 +33321,17 @@ function distinctUntilKeyChanged(key, compare) { /***/ }), -/* 319 */ +/* 327 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return elementAt; }); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(250); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(320); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(321); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(323); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(258); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(329); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(319); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(331); /** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */ @@ -33923,14 +33353,14 @@ function elementAt(index, defaultValue) { /***/ }), -/* 320 */ +/* 328 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return filter; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -33977,14 +33407,14 @@ var FilterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 321 */ +/* 329 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return throwIfEmpty; }); -/* harmony import */ var _tap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(322); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); +/* harmony import */ var _tap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(330); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(259); /** PURE_IMPORTS_START _tap,_util_EmptyError PURE_IMPORTS_END */ @@ -34009,16 +33439,16 @@ function defaultErrorFactory() { /***/ }), -/* 322 */ +/* 330 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return tap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(200); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(221); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208); /** PURE_IMPORTS_START tslib,_Subscriber,_util_noop,_util_isFunction PURE_IMPORTS_END */ @@ -34097,16 +33527,16 @@ var TapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 323 */ +/* 331 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "take", function() { return take; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(250); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(231); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */ @@ -34159,17 +33589,17 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 324 */ +/* 332 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return endWith; }); -/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(234); -/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(236); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(231); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(267); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(233); +/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); +/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(244); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(275); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(241); /** PURE_IMPORTS_START _observable_fromArray,_observable_scalar,_observable_empty,_observable_concat,_util_isScheduler PURE_IMPORTS_END */ @@ -34205,14 +33635,14 @@ function endWith() { /***/ }), -/* 325 */ +/* 333 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "every", function() { return every; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34267,15 +33697,15 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 326 */ +/* 334 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return exhaust; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -34324,17 +33754,17 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 327 */ +/* 335 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return exhaustMap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(254); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(268); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(276); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */ @@ -34410,7 +33840,7 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 328 */ +/* 336 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -34418,11 +33848,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return expand; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandOperator", function() { return ExpandOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandSubscriber", function() { return ExpandSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(216); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -34526,15 +33956,15 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 329 */ +/* 337 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return finalize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription PURE_IMPORTS_END */ @@ -34564,7 +33994,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 330 */ +/* 338 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -34572,8 +34002,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "find", function() { return find; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FindValueOperator", function() { return FindValueOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FindValueSubscriber", function() { return FindValueSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34635,13 +34065,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 331 */ +/* 339 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return findIndex; }); -/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(330); +/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(338); /** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */ function findIndex(predicate, thisArg) { @@ -34651,18 +34081,18 @@ function findIndex(predicate, thisArg) { /***/ }), -/* 332 */ +/* 340 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "first", function() { return first; }); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(320); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(321); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(248); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(259); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(331); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(319); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(329); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(256); /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -34678,14 +34108,14 @@ function first(predicate, defaultValue) { /***/ }), -/* 333 */ +/* 341 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return ignoreElements; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34715,14 +34145,14 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 334 */ +/* 342 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return isEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34759,18 +34189,18 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 335 */ +/* 343 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "last", function() { return last; }); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(320); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(336); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(321); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(311); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(248); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(259); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(344); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(329); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(319); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(256); /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -34786,16 +34216,16 @@ function last(predicate, defaultValue) { /***/ }), -/* 336 */ +/* 344 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return takeLast; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(250); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(231); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */ @@ -34863,14 +34293,14 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 337 */ +/* 345 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return mapTo; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34902,15 +34332,15 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 338 */ +/* 346 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return materialize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(238); /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -34952,13 +34382,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 339 */ +/* 347 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "max", function() { return max; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(340); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(348); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function max(comparer) { @@ -34971,16 +34401,16 @@ function max(comparer) { /***/ }), -/* 340 */ +/* 348 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return reduce; }); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(341); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311); -/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(212); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(349); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(344); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(319); +/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(220); /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */ @@ -35002,14 +34432,14 @@ function reduce(accumulator, seed) { /***/ }), -/* 341 */ +/* 349 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return scan; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -35084,13 +34514,13 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 342 */ +/* 350 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; }); -/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285); +/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(293); /** PURE_IMPORTS_START _observable_merge PURE_IMPORTS_END */ function merge() { @@ -35104,13 +34534,13 @@ function merge() { /***/ }), -/* 343 */ +/* 351 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return mergeMapTo; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(284); /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */ function mergeMapTo(innerObservable, resultSelector, concurrent) { @@ -35129,7 +34559,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) { /***/ }), -/* 344 */ +/* 352 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -35137,11 +34567,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return mergeScan; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanOperator", function() { return MergeScanOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanSubscriber", function() { return MergeScanSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(258); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(216); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(266); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */ @@ -35236,13 +34666,13 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 345 */ +/* 353 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "min", function() { return min; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(340); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(348); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function min(comparer) { @@ -35255,14 +34685,14 @@ function min(comparer) { /***/ }), -/* 346 */ +/* 354 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return multicast; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MulticastOperator", function() { return MulticastOperator; }); -/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(214); +/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(222); /** PURE_IMPORTS_START _observable_ConnectableObservable PURE_IMPORTS_END */ function multicast(subjectOrSubjectFactory, selector) { @@ -35304,18 +34734,18 @@ var MulticastOperator = /*@__PURE__*/ (function () { /***/ }), -/* 347 */ +/* 355 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNextStatic", function() { return onErrorResumeNextStatic; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(268); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(205); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_observable_from,_util_isArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -35388,14 +34818,14 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 348 */ +/* 356 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return pairwise; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -35432,14 +34862,14 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 349 */ +/* 357 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return partition; }); -/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(350); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(320); +/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(358); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); /** PURE_IMPORTS_START _util_not,_filter PURE_IMPORTS_END */ @@ -35455,7 +34885,7 @@ function partition(predicate, thisArg) { /***/ }), -/* 350 */ +/* 358 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -35474,13 +34904,13 @@ function not(pred, thisArg) { /***/ }), -/* 351 */ +/* 359 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return pluck; }); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(254); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(262); /** PURE_IMPORTS_START _map PURE_IMPORTS_END */ function pluck() { @@ -35514,14 +34944,14 @@ function plucker(props, length) { /***/ }), -/* 352 */ +/* 360 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return publish; }); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(215); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(346); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(223); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(354); /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */ @@ -35534,14 +34964,14 @@ function publish(selector) { /***/ }), -/* 353 */ +/* 361 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return publishBehavior; }); -/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(220); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(346); +/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(228); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(354); /** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */ @@ -35552,14 +34982,14 @@ function publishBehavior(value) { /***/ }), -/* 354 */ +/* 362 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return publishLast; }); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(238); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(346); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(246); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(354); /** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */ @@ -35570,14 +35000,14 @@ function publishLast() { /***/ }), -/* 355 */ +/* 363 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return publishReplay; }); -/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(221); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(346); +/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(229); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(354); /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */ @@ -35593,14 +35023,14 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) { /***/ }), -/* 356 */ +/* 364 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(205); -/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(289); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); +/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(297); /** PURE_IMPORTS_START _util_isArray,_observable_race PURE_IMPORTS_END */ @@ -35620,15 +35050,15 @@ function race() { /***/ }), -/* 357 */ +/* 365 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return repeat; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(231); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); /** PURE_IMPORTS_START tslib,_Subscriber,_observable_empty PURE_IMPORTS_END */ @@ -35685,18 +35115,18 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 358 */ +/* 366 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return repeatWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -35781,14 +35211,14 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 359 */ +/* 367 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return retry; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -35834,18 +35264,18 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 360 */ +/* 368 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return retryWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -35923,15 +35353,15 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 361 */ +/* 369 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return sample; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -35980,15 +35410,15 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 362 */ +/* 370 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return sampleTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(243); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */ @@ -36040,7 +35470,7 @@ function dispatchNotification(state) { /***/ }), -/* 363 */ +/* 371 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -36048,10 +35478,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return sequenceEqual; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualOperator", function() { return SequenceEqualOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualSubscriber", function() { return SequenceEqualSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); /** PURE_IMPORTS_START tslib,_Subscriber,_util_tryCatch,_util_errorObject PURE_IMPORTS_END */ @@ -36159,15 +35589,15 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 364 */ +/* 372 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "share", function() { return share; }); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(346); -/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(218); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(354); +/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(226); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(223); /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */ @@ -36182,13 +35612,13 @@ function share() { /***/ }), -/* 365 */ +/* 373 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return shareReplay; }); -/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(221); +/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(229); /** PURE_IMPORTS_START _ReplaySubject PURE_IMPORTS_END */ function shareReplay(bufferSize, windowTime, scheduler) { @@ -36231,15 +35661,15 @@ function shareReplayOperator(bufferSize, windowTime, scheduler) { /***/ }), -/* 366 */ +/* 374 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "single", function() { return single; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(259); /** PURE_IMPORTS_START tslib,_Subscriber,_util_EmptyError PURE_IMPORTS_END */ @@ -36311,14 +35741,14 @@ var SingleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 367 */ +/* 375 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return skip; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -36353,15 +35783,15 @@ var SkipSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 368 */ +/* 376 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return skipLast; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(250); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError PURE_IMPORTS_END */ @@ -36415,15 +35845,15 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 369 */ +/* 377 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return skipUntil; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -36467,14 +35897,14 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 370 */ +/* 378 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return skipWhile; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -36523,17 +35953,17 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 371 */ +/* 379 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return startWith; }); -/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(234); -/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(236); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(231); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(267); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(233); +/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); +/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(244); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(275); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(241); /** PURE_IMPORTS_START _observable_fromArray,_observable_scalar,_observable_empty,_observable_concat,_util_isScheduler PURE_IMPORTS_END */ @@ -36569,13 +35999,13 @@ function startWith() { /***/ }), -/* 372 */ +/* 380 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return subscribeOn; }); -/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(373); +/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(381); /** PURE_IMPORTS_START _observable_SubscribeOnObservable PURE_IMPORTS_END */ function subscribeOn(scheduler, delay) { @@ -36600,16 +36030,16 @@ var SubscribeOnOperator = /*@__PURE__*/ (function () { /***/ }), -/* 373 */ +/* 381 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubscribeOnObservable", function() { return SubscribeOnObservable; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(196); -/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(284); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); +/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(247); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(292); /** PURE_IMPORTS_START tslib,_Observable,_scheduler_asap,_util_isNumeric PURE_IMPORTS_END */ @@ -36664,14 +36094,14 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) { /***/ }), -/* 374 */ +/* 382 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return switchAll; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(375); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(248); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(383); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); /** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */ @@ -36682,17 +36112,17 @@ function switchAll() { /***/ }), -/* 375 */ +/* 383 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return switchMap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(254); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(268); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(276); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */ @@ -36766,13 +36196,13 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 376 */ +/* 384 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return switchMapTo; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(375); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(383); /** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */ function switchMapTo(innerObservable, resultSelector) { @@ -36782,15 +36212,15 @@ function switchMapTo(innerObservable, resultSelector) { /***/ }), -/* 377 */ +/* 385 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return takeUntil; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -36829,14 +36259,14 @@ var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 378 */ +/* 386 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return takeWhile; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -36887,16 +36317,16 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 379 */ +/* 387 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultThrottleConfig", function() { return defaultThrottleConfig; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return throttle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -36991,16 +36421,16 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 380 */ +/* 388 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return throttleTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(243); -/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(379); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); +/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(387); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */ @@ -37085,17 +36515,17 @@ function dispatchNext(arg) { /***/ }), -/* 381 */ +/* 389 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return timeInterval; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeInterval", function() { return TimeInterval; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(243); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(341); -/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(277); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(254); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(349); +/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); /** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */ @@ -37129,16 +36559,16 @@ var TimeInterval = /*@__PURE__*/ (function () { /***/ }), -/* 382 */ +/* 390 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return timeout; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(243); -/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(252); -/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(383); -/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(237); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); +/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(260); +/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(391); +/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(245); /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */ @@ -37154,17 +36584,17 @@ function timeout(due, scheduler) { /***/ }), -/* 383 */ +/* 391 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return timeoutWith; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(243); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(313); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(321); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -37236,15 +36666,15 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 384 */ +/* 392 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return timestamp; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Timestamp", function() { return Timestamp; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(243); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(254); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(262); /** PURE_IMPORTS_START _scheduler_async,_map PURE_IMPORTS_END */ @@ -37266,13 +36696,13 @@ var Timestamp = /*@__PURE__*/ (function () { /***/ }), -/* 385 */ +/* 393 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return toArray; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(340); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(348); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function toArrayReducer(arr, item, index) { @@ -37289,16 +36719,16 @@ function toArray() { /***/ }), -/* 386 */ +/* 394 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "window", function() { return window; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -37369,15 +36799,15 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 387 */ +/* 395 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return windowCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(198); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(223); /** PURE_IMPORTS_START tslib,_Subscriber,_Subject PURE_IMPORTS_END */ @@ -37459,18 +36889,18 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 388 */ +/* 396 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return windowTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(243); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(198); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(284); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(233); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(292); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(241); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_async,_Subscriber,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -37629,19 +37059,19 @@ function dispatchWindowClose(state) { /***/ }), -/* 389 */ +/* 397 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return windowToggle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(208); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(216); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_Subject,_Subscription,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -37775,18 +37205,18 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 390 */ +/* 398 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return windowWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(207); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -37874,15 +37304,15 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 391 */ +/* 399 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return withLatestFrom; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(199); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(257); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -37969,13 +37399,13 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 392 */ +/* 400 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; }); -/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(293); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(301); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zip() { @@ -37991,13 +37421,13 @@ function zip() { /***/ }), -/* 393 */ +/* 401 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return zipAll; }); -/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(293); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(301); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zipAll(project) { @@ -38007,7 +37437,7 @@ function zipAll(project) { /***/ }), -/* 394 */ +/* 402 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -38015,15 +37445,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(395); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(403); /* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(396); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(404); /* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(164); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(172); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(53); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(36); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(403); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(411); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -38101,7 +37531,7 @@ function toArray(value) { } /***/ }), -/* 395 */ +/* 403 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38135,13 +37565,13 @@ module.exports = (str, count, opts) => { /***/ }), -/* 396 */ +/* 404 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringWidth = __webpack_require__(397); -const stripAnsi = __webpack_require__(401); +const stringWidth = __webpack_require__(405); +const stripAnsi = __webpack_require__(409); const ESCAPES = new Set([ '\u001B', @@ -38335,13 +37765,13 @@ module.exports = (str, cols, opts) => { /***/ }), -/* 397 */ +/* 405 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stripAnsi = __webpack_require__(398); -const isFullwidthCodePoint = __webpack_require__(400); +const stripAnsi = __webpack_require__(406); +const isFullwidthCodePoint = __webpack_require__(408); module.exports = str => { if (typeof str !== 'string' || str.length === 0) { @@ -38378,18 +37808,18 @@ module.exports = str => { /***/ }), -/* 398 */ +/* 406 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(399); +const ansiRegex = __webpack_require__(407); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 399 */ +/* 407 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38406,7 +37836,7 @@ module.exports = () => { /***/ }), -/* 400 */ +/* 408 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38459,18 +37889,18 @@ module.exports = x => { /***/ }), -/* 401 */ +/* 409 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(402); +const ansiRegex = __webpack_require__(410); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 402 */ +/* 410 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38487,7 +37917,7 @@ module.exports = () => { /***/ }), -/* 403 */ +/* 411 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -38640,15 +38070,15 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 404 */ +/* 412 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(405); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(413); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(612); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(620); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -38673,19 +38103,19 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 405 */ +/* 413 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(406); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(414); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(166); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(174); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(164); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(172); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(55); @@ -38819,17 +38249,17 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 406 */ +/* 414 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const EventEmitter = __webpack_require__(46); const path = __webpack_require__(16); -const arrify = __webpack_require__(407); -const globby = __webpack_require__(408); -const cpFile = __webpack_require__(602); -const CpyError = __webpack_require__(610); +const arrify = __webpack_require__(415); +const globby = __webpack_require__(416); +const cpFile = __webpack_require__(610); +const CpyError = __webpack_require__(618); const preprocessSrcPath = (srcPath, options) => options.cwd ? path.resolve(options.cwd, srcPath) : srcPath; @@ -38934,7 +38364,7 @@ module.exports.default = cpy; /***/ }), -/* 407 */ +/* 415 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38949,17 +38379,17 @@ module.exports = function (val) { /***/ }), -/* 408 */ +/* 416 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(170); +const arrayUnion = __webpack_require__(178); const glob = __webpack_require__(37); -const fastGlob = __webpack_require__(409); -const dirGlob = __webpack_require__(595); -const gitignore = __webpack_require__(598); +const fastGlob = __webpack_require__(417); +const dirGlob = __webpack_require__(603); +const gitignore = __webpack_require__(606); const DEFAULT_FILTER = () => false; @@ -39104,10 +38534,10 @@ module.exports.gitignore = gitignore; /***/ }), -/* 409 */ +/* 417 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(410); +const pkg = __webpack_require__(418); module.exports = pkg.async; module.exports.default = pkg.async; @@ -39120,19 +38550,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 410 */ +/* 418 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(411); -var taskManager = __webpack_require__(412); -var reader_async_1 = __webpack_require__(565); -var reader_stream_1 = __webpack_require__(589); -var reader_sync_1 = __webpack_require__(590); -var arrayUtils = __webpack_require__(592); -var streamUtils = __webpack_require__(593); +var optionsManager = __webpack_require__(419); +var taskManager = __webpack_require__(420); +var reader_async_1 = __webpack_require__(573); +var reader_stream_1 = __webpack_require__(597); +var reader_sync_1 = __webpack_require__(598); +var arrayUtils = __webpack_require__(600); +var streamUtils = __webpack_require__(601); /** * Synchronous API. */ @@ -39198,7 +38628,7 @@ function isString(source) { /***/ }), -/* 411 */ +/* 419 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39236,13 +38666,13 @@ exports.prepare = prepare; /***/ }), -/* 412 */ +/* 420 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(413); +var patternUtils = __webpack_require__(421); /** * Generate tasks based on parent directory of each pattern. */ @@ -39333,16 +38763,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 413 */ +/* 421 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var globParent = __webpack_require__(414); -var isGlob = __webpack_require__(418); -var micromatch = __webpack_require__(419); +var globParent = __webpack_require__(422); +var isGlob = __webpack_require__(426); +var micromatch = __webpack_require__(427); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -39488,15 +38918,15 @@ exports.matchAny = matchAny; /***/ }), -/* 414 */ +/* 422 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(16); -var isglob = __webpack_require__(415); -var pathDirname = __webpack_require__(417); +var isglob = __webpack_require__(423); +var pathDirname = __webpack_require__(425); var isWin32 = __webpack_require__(11).platform() === 'win32'; module.exports = function globParent(str) { @@ -39519,7 +38949,7 @@ module.exports = function globParent(str) { /***/ }), -/* 415 */ +/* 423 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -39529,7 +38959,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(416); +var isExtglob = __webpack_require__(424); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -39550,7 +38980,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 416 */ +/* 424 */ /***/ (function(module, exports) { /*! @@ -39576,7 +39006,7 @@ module.exports = function isExtglob(str) { /***/ }), -/* 417 */ +/* 425 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39726,7 +39156,7 @@ module.exports.win32 = win32; /***/ }), -/* 418 */ +/* 426 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -39736,7 +39166,7 @@ module.exports.win32 = win32; * Released under the MIT License. */ -var isExtglob = __webpack_require__(416); +var isExtglob = __webpack_require__(424); var chars = { '{': '}', '(': ')', '[': ']'}; module.exports = function isGlob(str, options) { @@ -39778,7 +39208,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 419 */ +/* 427 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39789,18 +39219,18 @@ module.exports = function isGlob(str, options) { */ var util = __webpack_require__(29); -var braces = __webpack_require__(420); -var toRegex = __webpack_require__(523); -var extend = __webpack_require__(531); +var braces = __webpack_require__(428); +var toRegex = __webpack_require__(531); +var extend = __webpack_require__(539); /** * Local dependencies */ -var compilers = __webpack_require__(534); -var parsers = __webpack_require__(561); -var cache = __webpack_require__(562); -var utils = __webpack_require__(563); +var compilers = __webpack_require__(542); +var parsers = __webpack_require__(569); +var cache = __webpack_require__(570); +var utils = __webpack_require__(571); var MAX_LENGTH = 1024 * 64; /** @@ -40662,7 +40092,7 @@ module.exports = micromatch; /***/ }), -/* 420 */ +/* 428 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40672,18 +40102,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(421); -var unique = __webpack_require__(433); -var extend = __webpack_require__(430); +var toRegex = __webpack_require__(429); +var unique = __webpack_require__(441); +var extend = __webpack_require__(438); /** * Local dependencies */ -var compilers = __webpack_require__(434); -var parsers = __webpack_require__(449); -var Braces = __webpack_require__(459); -var utils = __webpack_require__(435); +var compilers = __webpack_require__(442); +var parsers = __webpack_require__(457); +var Braces = __webpack_require__(467); +var utils = __webpack_require__(443); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -40987,15 +40417,15 @@ module.exports = braces; /***/ }), -/* 421 */ +/* 429 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(422); -var extend = __webpack_require__(430); -var not = __webpack_require__(432); +var define = __webpack_require__(430); +var extend = __webpack_require__(438); +var not = __webpack_require__(440); var MAX_LENGTH = 1024 * 64; /** @@ -41142,7 +40572,7 @@ module.exports.makeRe = makeRe; /***/ }), -/* 422 */ +/* 430 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41155,7 +40585,7 @@ module.exports.makeRe = makeRe; -var isDescriptor = __webpack_require__(423); +var isDescriptor = __webpack_require__(431); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -41180,7 +40610,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 423 */ +/* 431 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41193,9 +40623,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(424); -var isAccessor = __webpack_require__(425); -var isData = __webpack_require__(428); +var typeOf = __webpack_require__(432); +var isAccessor = __webpack_require__(433); +var isData = __webpack_require__(436); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -41209,7 +40639,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 424 */ +/* 432 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -41362,7 +40792,7 @@ function isBuffer(val) { /***/ }), -/* 425 */ +/* 433 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41375,7 +40805,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(426); +var typeOf = __webpack_require__(434); // accessor descriptor properties var accessor = { @@ -41438,10 +40868,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 426 */ +/* 434 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(427); +var isBuffer = __webpack_require__(435); var toString = Object.prototype.toString; /** @@ -41560,7 +40990,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 427 */ +/* 435 */ /***/ (function(module, exports) { /*! @@ -41587,7 +41017,7 @@ function isSlowBuffer (obj) { /***/ }), -/* 428 */ +/* 436 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41600,7 +41030,7 @@ function isSlowBuffer (obj) { -var typeOf = __webpack_require__(429); +var typeOf = __webpack_require__(437); // data descriptor properties var data = { @@ -41649,10 +41079,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 429 */ +/* 437 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(427); +var isBuffer = __webpack_require__(435); var toString = Object.prototype.toString; /** @@ -41771,13 +41201,13 @@ module.exports = function kindOf(val) { /***/ }), -/* 430 */ +/* 438 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(431); +var isObject = __webpack_require__(439); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -41811,7 +41241,7 @@ function hasOwn(obj, key) { /***/ }), -/* 431 */ +/* 439 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41831,13 +41261,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 432 */ +/* 440 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(430); +var extend = __webpack_require__(438); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -41904,7 +41334,7 @@ module.exports = toRegex; /***/ }), -/* 433 */ +/* 441 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41954,13 +41384,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 434 */ +/* 442 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(435); +var utils = __webpack_require__(443); module.exports = function(braces, options) { braces.compiler @@ -42243,25 +41673,25 @@ function hasQueue(node) { /***/ }), -/* 435 */ +/* 443 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(436); +var splitString = __webpack_require__(444); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(430); -utils.flatten = __webpack_require__(442); -utils.isObject = __webpack_require__(440); -utils.fillRange = __webpack_require__(443); -utils.repeat = __webpack_require__(448); -utils.unique = __webpack_require__(433); +utils.extend = __webpack_require__(438); +utils.flatten = __webpack_require__(450); +utils.isObject = __webpack_require__(448); +utils.fillRange = __webpack_require__(451); +utils.repeat = __webpack_require__(456); +utils.unique = __webpack_require__(441); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -42593,7 +42023,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 436 */ +/* 444 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42606,7 +42036,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(437); +var extend = __webpack_require__(445); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -42771,14 +42201,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 437 */ +/* 445 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(438); -var assignSymbols = __webpack_require__(441); +var isExtendable = __webpack_require__(446); +var assignSymbols = __webpack_require__(449); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -42838,7 +42268,7 @@ function isEnum(obj, key) { /***/ }), -/* 438 */ +/* 446 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42851,7 +42281,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(439); +var isPlainObject = __webpack_require__(447); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -42859,7 +42289,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 439 */ +/* 447 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42872,7 +42302,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(440); +var isObject = __webpack_require__(448); function isObjectObject(o) { return isObject(o) === true @@ -42903,7 +42333,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 440 */ +/* 448 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42922,7 +42352,7 @@ module.exports = function isObject(val) { /***/ }), -/* 441 */ +/* 449 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42969,7 +42399,7 @@ module.exports = function(receiver, objects) { /***/ }), -/* 442 */ +/* 450 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42998,7 +42428,7 @@ function flat(arr, res) { /***/ }), -/* 443 */ +/* 451 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43012,10 +42442,10 @@ function flat(arr, res) { var util = __webpack_require__(29); -var isNumber = __webpack_require__(444); -var extend = __webpack_require__(430); -var repeat = __webpack_require__(446); -var toRegex = __webpack_require__(447); +var isNumber = __webpack_require__(452); +var extend = __webpack_require__(438); +var repeat = __webpack_require__(454); +var toRegex = __webpack_require__(455); /** * Return a range of numbers or letters. @@ -43213,7 +42643,7 @@ module.exports = fillRange; /***/ }), -/* 444 */ +/* 452 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43226,7 +42656,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(445); +var typeOf = __webpack_require__(453); module.exports = function isNumber(num) { var type = typeOf(num); @@ -43242,10 +42672,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 445 */ +/* 453 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(427); +var isBuffer = __webpack_require__(435); var toString = Object.prototype.toString; /** @@ -43364,7 +42794,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 446 */ +/* 454 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43441,7 +42871,7 @@ function repeat(str, num) { /***/ }), -/* 447 */ +/* 455 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43454,8 +42884,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(446); -var isNumber = __webpack_require__(444); +var repeat = __webpack_require__(454); +var isNumber = __webpack_require__(452); var cache = {}; function toRegexRange(min, max, options) { @@ -43742,7 +43172,7 @@ module.exports = toRegexRange; /***/ }), -/* 448 */ +/* 456 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43767,14 +43197,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 449 */ +/* 457 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(450); -var utils = __webpack_require__(435); +var Node = __webpack_require__(458); +var utils = __webpack_require__(443); /** * Braces parsers @@ -44134,15 +43564,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 450 */ +/* 458 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(440); -var define = __webpack_require__(451); -var utils = __webpack_require__(458); +var isObject = __webpack_require__(448); +var define = __webpack_require__(459); +var utils = __webpack_require__(466); var ownNames; /** @@ -44633,7 +44063,7 @@ exports = module.exports = Node; /***/ }), -/* 451 */ +/* 459 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -44646,7 +44076,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(452); +var isDescriptor = __webpack_require__(460); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -44671,7 +44101,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 452 */ +/* 460 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -44684,9 +44114,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(453); -var isAccessor = __webpack_require__(454); -var isData = __webpack_require__(456); +var typeOf = __webpack_require__(461); +var isAccessor = __webpack_require__(462); +var isData = __webpack_require__(464); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -44700,7 +44130,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 453 */ +/* 461 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -44835,7 +44265,7 @@ function isBuffer(val) { /***/ }), -/* 454 */ +/* 462 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -44848,7 +44278,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(455); +var typeOf = __webpack_require__(463); // accessor descriptor properties var accessor = { @@ -44911,7 +44341,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 455 */ +/* 463 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -45046,7 +44476,7 @@ function isBuffer(val) { /***/ }), -/* 456 */ +/* 464 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -45059,7 +44489,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(457); +var typeOf = __webpack_require__(465); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -45102,7 +44532,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 457 */ +/* 465 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -45237,13 +44667,13 @@ function isBuffer(val) { /***/ }), -/* 458 */ +/* 466 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(445); +var typeOf = __webpack_require__(453); var utils = module.exports; /** @@ -46263,17 +45693,17 @@ function assert(val, message) { /***/ }), -/* 459 */ +/* 467 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(430); -var Snapdragon = __webpack_require__(460); -var compilers = __webpack_require__(434); -var parsers = __webpack_require__(449); -var utils = __webpack_require__(435); +var extend = __webpack_require__(438); +var Snapdragon = __webpack_require__(468); +var compilers = __webpack_require__(442); +var parsers = __webpack_require__(457); +var utils = __webpack_require__(443); /** * Customize Snapdragon parser and renderer @@ -46374,17 +45804,17 @@ module.exports = Braces; /***/ }), -/* 460 */ +/* 468 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(461); -var define = __webpack_require__(422); -var Compiler = __webpack_require__(490); -var Parser = __webpack_require__(520); -var utils = __webpack_require__(500); +var Base = __webpack_require__(469); +var define = __webpack_require__(430); +var Compiler = __webpack_require__(498); +var Parser = __webpack_require__(528); +var utils = __webpack_require__(508); var regexCache = {}; var cache = {}; @@ -46555,20 +45985,20 @@ module.exports.Parser = Parser; /***/ }), -/* 461 */ +/* 469 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var define = __webpack_require__(462); -var CacheBase = __webpack_require__(463); -var Emitter = __webpack_require__(464); -var isObject = __webpack_require__(440); -var merge = __webpack_require__(481); -var pascal = __webpack_require__(484); -var cu = __webpack_require__(485); +var define = __webpack_require__(470); +var CacheBase = __webpack_require__(471); +var Emitter = __webpack_require__(472); +var isObject = __webpack_require__(448); +var merge = __webpack_require__(489); +var pascal = __webpack_require__(492); +var cu = __webpack_require__(493); /** * Optionally define a custom `cache` namespace to use. @@ -46997,7 +46427,7 @@ module.exports.namespace = namespace; /***/ }), -/* 462 */ +/* 470 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47010,7 +46440,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(452); +var isDescriptor = __webpack_require__(460); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -47035,21 +46465,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 463 */ +/* 471 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(440); -var Emitter = __webpack_require__(464); -var visit = __webpack_require__(465); -var toPath = __webpack_require__(468); -var union = __webpack_require__(469); -var del = __webpack_require__(473); -var get = __webpack_require__(471); -var has = __webpack_require__(478); -var set = __webpack_require__(472); +var isObject = __webpack_require__(448); +var Emitter = __webpack_require__(472); +var visit = __webpack_require__(473); +var toPath = __webpack_require__(476); +var union = __webpack_require__(477); +var del = __webpack_require__(481); +var get = __webpack_require__(479); +var has = __webpack_require__(486); +var set = __webpack_require__(480); /** * Create a `Cache` constructor that when instantiated will @@ -47303,7 +46733,7 @@ module.exports.namespace = namespace; /***/ }), -/* 464 */ +/* 472 */ /***/ (function(module, exports, __webpack_require__) { @@ -47472,7 +46902,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 465 */ +/* 473 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47485,8 +46915,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(466); -var mapVisit = __webpack_require__(467); +var visit = __webpack_require__(474); +var mapVisit = __webpack_require__(475); module.exports = function(collection, method, val) { var result; @@ -47509,7 +46939,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 466 */ +/* 474 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47522,7 +46952,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(440); +var isObject = __webpack_require__(448); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -47549,14 +46979,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 467 */ +/* 475 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var visit = __webpack_require__(466); +var visit = __webpack_require__(474); /** * Map `visit` over an array of objects. @@ -47593,7 +47023,7 @@ function isObject(val) { /***/ }), -/* 468 */ +/* 476 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47606,7 +47036,7 @@ function isObject(val) { -var typeOf = __webpack_require__(445); +var typeOf = __webpack_require__(453); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -47633,16 +47063,16 @@ function filter(arr) { /***/ }), -/* 469 */ +/* 477 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(431); -var union = __webpack_require__(470); -var get = __webpack_require__(471); -var set = __webpack_require__(472); +var isObject = __webpack_require__(439); +var union = __webpack_require__(478); +var get = __webpack_require__(479); +var set = __webpack_require__(480); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -47670,7 +47100,7 @@ function arrayify(val) { /***/ }), -/* 470 */ +/* 478 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47706,7 +47136,7 @@ module.exports = function union(init) { /***/ }), -/* 471 */ +/* 479 */ /***/ (function(module, exports) { /*! @@ -47762,7 +47192,7 @@ function toString(val) { /***/ }), -/* 472 */ +/* 480 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47775,10 +47205,10 @@ function toString(val) { -var split = __webpack_require__(436); -var extend = __webpack_require__(430); -var isPlainObject = __webpack_require__(439); -var isObject = __webpack_require__(431); +var split = __webpack_require__(444); +var extend = __webpack_require__(438); +var isPlainObject = __webpack_require__(447); +var isObject = __webpack_require__(439); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -47824,7 +47254,7 @@ function isValidKey(key) { /***/ }), -/* 473 */ +/* 481 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47837,8 +47267,8 @@ function isValidKey(key) { -var isObject = __webpack_require__(440); -var has = __webpack_require__(474); +var isObject = __webpack_require__(448); +var has = __webpack_require__(482); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -47863,7 +47293,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 474 */ +/* 482 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47876,9 +47306,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(475); -var hasValues = __webpack_require__(477); -var get = __webpack_require__(471); +var isObject = __webpack_require__(483); +var hasValues = __webpack_require__(485); +var get = __webpack_require__(479); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -47889,7 +47319,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 475 */ +/* 483 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47902,7 +47332,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(476); +var isArray = __webpack_require__(484); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -47910,7 +47340,7 @@ module.exports = function isObject(val) { /***/ }), -/* 476 */ +/* 484 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -47921,7 +47351,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 477 */ +/* 485 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47964,7 +47394,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 478 */ +/* 486 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47977,9 +47407,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(440); -var hasValues = __webpack_require__(479); -var get = __webpack_require__(471); +var isObject = __webpack_require__(448); +var hasValues = __webpack_require__(487); +var get = __webpack_require__(479); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -47987,7 +47417,7 @@ module.exports = function(val, prop) { /***/ }), -/* 479 */ +/* 487 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48000,8 +47430,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(480); -var isNumber = __webpack_require__(444); +var typeOf = __webpack_require__(488); +var isNumber = __webpack_require__(452); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -48054,10 +47484,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 480 */ +/* 488 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(427); +var isBuffer = __webpack_require__(435); var toString = Object.prototype.toString; /** @@ -48179,14 +47609,14 @@ module.exports = function kindOf(val) { /***/ }), -/* 481 */ +/* 489 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(482); -var forIn = __webpack_require__(483); +var isExtendable = __webpack_require__(490); +var forIn = __webpack_require__(491); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -48250,7 +47680,7 @@ module.exports = mixinDeep; /***/ }), -/* 482 */ +/* 490 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48263,7 +47693,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(439); +var isPlainObject = __webpack_require__(447); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -48271,7 +47701,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 483 */ +/* 491 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48294,7 +47724,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 484 */ +/* 492 */ /***/ (function(module, exports) { /*! @@ -48321,14 +47751,14 @@ module.exports = pascalcase; /***/ }), -/* 485 */ +/* 493 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var utils = __webpack_require__(486); +var utils = __webpack_require__(494); /** * Expose class utils @@ -48693,7 +48123,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 486 */ +/* 494 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48707,10 +48137,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(470); -utils.define = __webpack_require__(422); -utils.isObj = __webpack_require__(440); -utils.staticExtend = __webpack_require__(487); +utils.union = __webpack_require__(478); +utils.define = __webpack_require__(430); +utils.isObj = __webpack_require__(448); +utils.staticExtend = __webpack_require__(495); /** @@ -48721,7 +48151,7 @@ module.exports = utils; /***/ }), -/* 487 */ +/* 495 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48734,8 +48164,8 @@ module.exports = utils; -var copy = __webpack_require__(488); -var define = __webpack_require__(422); +var copy = __webpack_require__(496); +var define = __webpack_require__(430); var util = __webpack_require__(29); /** @@ -48818,15 +48248,15 @@ module.exports = extend; /***/ }), -/* 488 */ +/* 496 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(445); -var copyDescriptor = __webpack_require__(489); -var define = __webpack_require__(422); +var typeOf = __webpack_require__(453); +var copyDescriptor = __webpack_require__(497); +var define = __webpack_require__(430); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -48999,7 +48429,7 @@ module.exports.has = has; /***/ }), -/* 489 */ +/* 497 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49087,16 +48517,16 @@ function isObject(val) { /***/ }), -/* 490 */ +/* 498 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(491); -var define = __webpack_require__(422); -var debug = __webpack_require__(493)('snapdragon:compiler'); -var utils = __webpack_require__(500); +var use = __webpack_require__(499); +var define = __webpack_require__(430); +var debug = __webpack_require__(501)('snapdragon:compiler'); +var utils = __webpack_require__(508); /** * Create a new `Compiler` with the given `options`. @@ -49250,7 +48680,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(519); + var sourcemaps = __webpack_require__(527); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -49271,7 +48701,7 @@ module.exports = Compiler; /***/ }), -/* 491 */ +/* 499 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49284,7 +48714,7 @@ module.exports = Compiler; -var utils = __webpack_require__(492); +var utils = __webpack_require__(500); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -49399,7 +48829,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 492 */ +/* 500 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49413,8 +48843,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(422); -utils.isObject = __webpack_require__(440); +utils.define = __webpack_require__(430); +utils.isObject = __webpack_require__(448); utils.isString = function(val) { @@ -49429,7 +48859,7 @@ module.exports = utils; /***/ }), -/* 493 */ +/* 501 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -49438,14 +48868,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(494); + module.exports = __webpack_require__(502); } else { - module.exports = __webpack_require__(497); + module.exports = __webpack_require__(505); } /***/ }), -/* 494 */ +/* 502 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -49454,7 +48884,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(495); +exports = module.exports = __webpack_require__(503); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -49636,7 +49066,7 @@ function localstorage() { /***/ }), -/* 495 */ +/* 503 */ /***/ (function(module, exports, __webpack_require__) { @@ -49652,7 +49082,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(496); +exports.humanize = __webpack_require__(504); /** * The currently active debug mode names, and names to skip. @@ -49844,7 +49274,7 @@ function coerce(val) { /***/ }), -/* 496 */ +/* 504 */ /***/ (function(module, exports) { /** @@ -50002,14 +49432,14 @@ function plural(ms, n, name) { /***/ }), -/* 497 */ +/* 505 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(498); +var tty = __webpack_require__(506); var util = __webpack_require__(29); /** @@ -50018,7 +49448,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(495); +exports = module.exports = __webpack_require__(503); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -50197,7 +49627,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(499); + var net = __webpack_require__(507); stream = new net.Socket({ fd: fd, readable: false, @@ -50256,19 +49686,19 @@ exports.enable(load()); /***/ }), -/* 498 */ +/* 506 */ /***/ (function(module, exports) { module.exports = require("tty"); /***/ }), -/* 499 */ +/* 507 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 500 */ +/* 508 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -50278,9 +49708,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(430); -exports.SourceMap = __webpack_require__(501); -exports.sourceMapResolve = __webpack_require__(512); +exports.extend = __webpack_require__(438); +exports.SourceMap = __webpack_require__(509); +exports.sourceMapResolve = __webpack_require__(520); /** * Convert backslash in the given string to forward slashes @@ -50323,7 +49753,7 @@ exports.last = function(arr, n) { /***/ }), -/* 501 */ +/* 509 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -50331,13 +49761,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(502).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(508).SourceMapConsumer; -exports.SourceNode = __webpack_require__(511).SourceNode; +exports.SourceMapGenerator = __webpack_require__(510).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(516).SourceMapConsumer; +exports.SourceNode = __webpack_require__(519).SourceNode; /***/ }), -/* 502 */ +/* 510 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50347,10 +49777,10 @@ exports.SourceNode = __webpack_require__(511).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(503); -var util = __webpack_require__(505); -var ArraySet = __webpack_require__(506).ArraySet; -var MappingList = __webpack_require__(507).MappingList; +var base64VLQ = __webpack_require__(511); +var util = __webpack_require__(513); +var ArraySet = __webpack_require__(514).ArraySet; +var MappingList = __webpack_require__(515).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -50759,7 +50189,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 503 */ +/* 511 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50799,7 +50229,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(504); +var base64 = __webpack_require__(512); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -50905,7 +50335,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 504 */ +/* 512 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50978,7 +50408,7 @@ exports.decode = function (charCode) { /***/ }), -/* 505 */ +/* 513 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51401,7 +50831,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 506 */ +/* 514 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51411,7 +50841,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(505); +var util = __webpack_require__(513); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -51528,7 +50958,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 507 */ +/* 515 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51538,7 +50968,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(505); +var util = __webpack_require__(513); /** * Determine whether mappingB is after mappingA with respect to generated @@ -51613,7 +51043,7 @@ exports.MappingList = MappingList; /***/ }), -/* 508 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51623,11 +51053,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(505); -var binarySearch = __webpack_require__(509); -var ArraySet = __webpack_require__(506).ArraySet; -var base64VLQ = __webpack_require__(503); -var quickSort = __webpack_require__(510).quickSort; +var util = __webpack_require__(513); +var binarySearch = __webpack_require__(517); +var ArraySet = __webpack_require__(514).ArraySet; +var base64VLQ = __webpack_require__(511); +var quickSort = __webpack_require__(518).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -52701,7 +52131,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 509 */ +/* 517 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -52818,7 +52248,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 510 */ +/* 518 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -52938,7 +52368,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 511 */ +/* 519 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -52948,8 +52378,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(502).SourceMapGenerator; -var util = __webpack_require__(505); +var SourceMapGenerator = __webpack_require__(510).SourceMapGenerator; +var util = __webpack_require__(513); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -53357,17 +52787,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 512 */ +/* 520 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(513) -var resolveUrl = __webpack_require__(514) -var decodeUriComponent = __webpack_require__(515) -var urix = __webpack_require__(517) -var atob = __webpack_require__(518) +var sourceMappingURL = __webpack_require__(521) +var resolveUrl = __webpack_require__(522) +var decodeUriComponent = __webpack_require__(523) +var urix = __webpack_require__(525) +var atob = __webpack_require__(526) @@ -53665,7 +53095,7 @@ module.exports = { /***/ }), -/* 513 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -53728,7 +53158,7 @@ void (function(root, factory) { /***/ }), -/* 514 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -53746,13 +53176,13 @@ module.exports = resolveUrl /***/ }), -/* 515 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(516) +var decodeUriComponent = __webpack_require__(524) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -53763,7 +53193,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 516 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53864,7 +53294,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 517 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -53887,7 +53317,7 @@ module.exports = urix /***/ }), -/* 518 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53901,7 +53331,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 519 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53909,8 +53339,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); -var define = __webpack_require__(422); -var utils = __webpack_require__(500); +var define = __webpack_require__(430); +var utils = __webpack_require__(508); /** * Expose `mixin()`. @@ -54053,19 +53483,19 @@ exports.comment = function(node) { /***/ }), -/* 520 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(491); +var use = __webpack_require__(499); var util = __webpack_require__(29); -var Cache = __webpack_require__(521); -var define = __webpack_require__(422); -var debug = __webpack_require__(493)('snapdragon:parser'); -var Position = __webpack_require__(522); -var utils = __webpack_require__(500); +var Cache = __webpack_require__(529); +var define = __webpack_require__(430); +var debug = __webpack_require__(501)('snapdragon:parser'); +var Position = __webpack_require__(530); +var utils = __webpack_require__(508); /** * Create a new `Parser` with the given `input` and `options`. @@ -54593,7 +54023,7 @@ module.exports = Parser; /***/ }), -/* 521 */ +/* 529 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54700,13 +54130,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 522 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(422); +var define = __webpack_require__(430); /** * Store position for a node @@ -54721,16 +54151,16 @@ module.exports = function Position(start, parser) { /***/ }), -/* 523 */ +/* 531 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(524); -var define = __webpack_require__(530); -var extend = __webpack_require__(531); -var not = __webpack_require__(533); +var safe = __webpack_require__(532); +var define = __webpack_require__(538); +var extend = __webpack_require__(539); +var not = __webpack_require__(541); var MAX_LENGTH = 1024 * 64; /** @@ -54883,10 +54313,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 524 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(525); +var parse = __webpack_require__(533); var types = parse.types; module.exports = function (re, opts) { @@ -54932,13 +54362,13 @@ function isRegExp (x) { /***/ }), -/* 525 */ +/* 533 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(526); -var types = __webpack_require__(527); -var sets = __webpack_require__(528); -var positions = __webpack_require__(529); +var util = __webpack_require__(534); +var types = __webpack_require__(535); +var sets = __webpack_require__(536); +var positions = __webpack_require__(537); module.exports = function(regexpStr) { @@ -55220,11 +54650,11 @@ module.exports.types = types; /***/ }), -/* 526 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(527); -var sets = __webpack_require__(528); +var types = __webpack_require__(535); +var sets = __webpack_require__(536); // All of these are private and only used by randexp. @@ -55337,7 +54767,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 527 */ +/* 535 */ /***/ (function(module, exports) { module.exports = { @@ -55353,10 +54783,10 @@ module.exports = { /***/ }), -/* 528 */ +/* 536 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(527); +var types = __webpack_require__(535); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -55441,10 +54871,10 @@ exports.anyChar = function() { /***/ }), -/* 529 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(527); +var types = __webpack_require__(535); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -55464,7 +54894,7 @@ exports.end = function() { /***/ }), -/* 530 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55477,8 +54907,8 @@ exports.end = function() { -var isobject = __webpack_require__(440); -var isDescriptor = __webpack_require__(452); +var isobject = __webpack_require__(448); +var isDescriptor = __webpack_require__(460); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -55509,14 +54939,14 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 531 */ +/* 539 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(532); -var assignSymbols = __webpack_require__(441); +var isExtendable = __webpack_require__(540); +var assignSymbols = __webpack_require__(449); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -55576,7 +55006,7 @@ function isEnum(obj, key) { /***/ }), -/* 532 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55589,7 +55019,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(439); +var isPlainObject = __webpack_require__(447); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -55597,14 +55027,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 533 */ +/* 541 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(531); -var safe = __webpack_require__(524); +var extend = __webpack_require__(539); +var safe = __webpack_require__(532); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -55676,14 +55106,14 @@ module.exports = toRegex; /***/ }), -/* 534 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(535); -var extglob = __webpack_require__(550); +var nanomatch = __webpack_require__(543); +var extglob = __webpack_require__(558); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -55760,7 +55190,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 535 */ +/* 543 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55771,17 +55201,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(29); -var toRegex = __webpack_require__(421); -var extend = __webpack_require__(536); +var toRegex = __webpack_require__(429); +var extend = __webpack_require__(544); /** * Local dependencies */ -var compilers = __webpack_require__(538); -var parsers = __webpack_require__(539); -var cache = __webpack_require__(542); -var utils = __webpack_require__(544); +var compilers = __webpack_require__(546); +var parsers = __webpack_require__(547); +var cache = __webpack_require__(550); +var utils = __webpack_require__(552); var MAX_LENGTH = 1024 * 64; /** @@ -56605,14 +56035,14 @@ module.exports = nanomatch; /***/ }), -/* 536 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(537); -var assignSymbols = __webpack_require__(441); +var isExtendable = __webpack_require__(545); +var assignSymbols = __webpack_require__(449); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -56672,7 +56102,7 @@ function isEnum(obj, key) { /***/ }), -/* 537 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56685,7 +56115,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(439); +var isPlainObject = __webpack_require__(447); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -56693,7 +56123,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 538 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57039,15 +56469,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 539 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(432); -var toRegex = __webpack_require__(421); -var isOdd = __webpack_require__(540); +var regexNot = __webpack_require__(440); +var toRegex = __webpack_require__(429); +var isOdd = __webpack_require__(548); /** * Characters to use in negation regex (we want to "not" match @@ -57433,7 +56863,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 540 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57446,7 +56876,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(541); +var isNumber = __webpack_require__(549); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -57460,7 +56890,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 541 */ +/* 549 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57488,14 +56918,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 542 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(543))(); +module.exports = new (__webpack_require__(551))(); /***/ }), -/* 543 */ +/* 551 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57508,7 +56938,7 @@ module.exports = new (__webpack_require__(543))(); -var MapCache = __webpack_require__(521); +var MapCache = __webpack_require__(529); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -57630,7 +57060,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 544 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57643,14 +57073,14 @@ var path = __webpack_require__(16); * Module dependencies */ -var isWindows = __webpack_require__(545)(); -var Snapdragon = __webpack_require__(460); -utils.define = __webpack_require__(546); -utils.diff = __webpack_require__(547); -utils.extend = __webpack_require__(536); -utils.pick = __webpack_require__(548); -utils.typeOf = __webpack_require__(549); -utils.unique = __webpack_require__(433); +var isWindows = __webpack_require__(553)(); +var Snapdragon = __webpack_require__(468); +utils.define = __webpack_require__(554); +utils.diff = __webpack_require__(555); +utils.extend = __webpack_require__(544); +utils.pick = __webpack_require__(556); +utils.typeOf = __webpack_require__(557); +utils.unique = __webpack_require__(441); /** * Returns true if the given value is effectively an empty string @@ -58016,7 +57446,7 @@ utils.unixify = function(options) { /***/ }), -/* 545 */ +/* 553 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -58044,7 +57474,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 546 */ +/* 554 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58057,8 +57487,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(440); -var isDescriptor = __webpack_require__(452); +var isobject = __webpack_require__(448); +var isDescriptor = __webpack_require__(460); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -58089,7 +57519,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 547 */ +/* 555 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58143,7 +57573,7 @@ function diffArray(one, two) { /***/ }), -/* 548 */ +/* 556 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58156,7 +57586,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(440); +var isObject = __webpack_require__(448); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -58185,7 +57615,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 549 */ +/* 557 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -58320,7 +57750,7 @@ function isBuffer(val) { /***/ }), -/* 550 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58330,18 +57760,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(430); -var unique = __webpack_require__(433); -var toRegex = __webpack_require__(421); +var extend = __webpack_require__(438); +var unique = __webpack_require__(441); +var toRegex = __webpack_require__(429); /** * Local dependencies */ -var compilers = __webpack_require__(551); -var parsers = __webpack_require__(557); -var Extglob = __webpack_require__(560); -var utils = __webpack_require__(559); +var compilers = __webpack_require__(559); +var parsers = __webpack_require__(565); +var Extglob = __webpack_require__(568); +var utils = __webpack_require__(567); var MAX_LENGTH = 1024 * 64; /** @@ -58658,13 +58088,13 @@ module.exports = extglob; /***/ }), -/* 551 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(552); +var brackets = __webpack_require__(560); /** * Extglob compilers @@ -58834,7 +58264,7 @@ module.exports = function(extglob) { /***/ }), -/* 552 */ +/* 560 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58844,17 +58274,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(553); -var parsers = __webpack_require__(555); +var compilers = __webpack_require__(561); +var parsers = __webpack_require__(563); /** * Module dependencies */ -var debug = __webpack_require__(493)('expand-brackets'); -var extend = __webpack_require__(430); -var Snapdragon = __webpack_require__(460); -var toRegex = __webpack_require__(421); +var debug = __webpack_require__(501)('expand-brackets'); +var extend = __webpack_require__(438); +var Snapdragon = __webpack_require__(468); +var toRegex = __webpack_require__(429); /** * Parses the given POSIX character class `pattern` and returns a @@ -59052,13 +58482,13 @@ module.exports = brackets; /***/ }), -/* 553 */ +/* 561 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(554); +var posix = __webpack_require__(562); module.exports = function(brackets) { brackets.compiler @@ -59146,7 +58576,7 @@ module.exports = function(brackets) { /***/ }), -/* 554 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59175,14 +58605,14 @@ module.exports = { /***/ }), -/* 555 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(556); -var define = __webpack_require__(422); +var utils = __webpack_require__(564); +var define = __webpack_require__(430); /** * Text regex @@ -59401,14 +58831,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 556 */ +/* 564 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(421); -var regexNot = __webpack_require__(432); +var toRegex = __webpack_require__(429); +var regexNot = __webpack_require__(440); var cached; /** @@ -59442,15 +58872,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 557 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(552); -var define = __webpack_require__(558); -var utils = __webpack_require__(559); +var brackets = __webpack_require__(560); +var define = __webpack_require__(566); +var utils = __webpack_require__(567); /** * Characters to use in text regex (we want to "not" match @@ -59605,7 +59035,7 @@ module.exports = parsers; /***/ }), -/* 558 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59618,7 +59048,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(452); +var isDescriptor = __webpack_require__(460); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -59643,14 +59073,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 559 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(432); -var Cache = __webpack_require__(543); +var regex = __webpack_require__(440); +var Cache = __webpack_require__(551); /** * Utils @@ -59719,7 +59149,7 @@ utils.createRegex = function(str) { /***/ }), -/* 560 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59729,16 +59159,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(460); -var define = __webpack_require__(558); -var extend = __webpack_require__(430); +var Snapdragon = __webpack_require__(468); +var define = __webpack_require__(566); +var extend = __webpack_require__(438); /** * Local dependencies */ -var compilers = __webpack_require__(551); -var parsers = __webpack_require__(557); +var compilers = __webpack_require__(559); +var parsers = __webpack_require__(565); /** * Customize Snapdragon parser and renderer @@ -59804,16 +59234,16 @@ module.exports = Extglob; /***/ }), -/* 561 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(550); -var nanomatch = __webpack_require__(535); -var regexNot = __webpack_require__(432); -var toRegex = __webpack_require__(523); +var extglob = __webpack_require__(558); +var nanomatch = __webpack_require__(543); +var regexNot = __webpack_require__(440); +var toRegex = __webpack_require__(531); var not; /** @@ -59894,14 +59324,14 @@ function textRegex(pattern) { /***/ }), -/* 562 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(543))(); +module.exports = new (__webpack_require__(551))(); /***/ }), -/* 563 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59914,13 +59344,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var Snapdragon = __webpack_require__(460); -utils.define = __webpack_require__(530); -utils.diff = __webpack_require__(547); -utils.extend = __webpack_require__(531); -utils.pick = __webpack_require__(548); -utils.typeOf = __webpack_require__(564); -utils.unique = __webpack_require__(433); +var Snapdragon = __webpack_require__(468); +utils.define = __webpack_require__(538); +utils.diff = __webpack_require__(555); +utils.extend = __webpack_require__(539); +utils.pick = __webpack_require__(556); +utils.typeOf = __webpack_require__(572); +utils.unique = __webpack_require__(441); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -60217,7 +59647,7 @@ utils.unixify = function(options) { /***/ }), -/* 564 */ +/* 572 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -60352,7 +59782,7 @@ function isBuffer(val) { /***/ }), -/* 565 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60371,9 +59801,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(566); -var reader_1 = __webpack_require__(579); -var fs_stream_1 = __webpack_require__(583); +var readdir = __webpack_require__(574); +var reader_1 = __webpack_require__(587); +var fs_stream_1 = __webpack_require__(591); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -60434,15 +59864,15 @@ exports.default = ReaderAsync; /***/ }), -/* 566 */ +/* 574 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(567); -const readdirAsync = __webpack_require__(575); -const readdirStream = __webpack_require__(578); +const readdirSync = __webpack_require__(575); +const readdirAsync = __webpack_require__(583); +const readdirStream = __webpack_require__(586); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -60526,7 +59956,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 567 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60534,11 +59964,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(568); +const DirectoryReader = __webpack_require__(576); let syncFacade = { - fs: __webpack_require__(573), - forEach: __webpack_require__(574), + fs: __webpack_require__(581), + forEach: __webpack_require__(582), sync: true }; @@ -60567,7 +59997,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 568 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60576,9 +60006,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(28).Readable; const EventEmitter = __webpack_require__(46).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(569); -const stat = __webpack_require__(571); -const call = __webpack_require__(572); +const normalizeOptions = __webpack_require__(577); +const stat = __webpack_require__(579); +const call = __webpack_require__(580); /** * Asynchronously reads the contents of a directory and streams the results @@ -60954,14 +60384,14 @@ module.exports = DirectoryReader; /***/ }), -/* 569 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(570); +const globToRegExp = __webpack_require__(578); module.exports = normalizeOptions; @@ -61138,7 +60568,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 570 */ +/* 578 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -61275,13 +60705,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 571 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(572); +const call = __webpack_require__(580); module.exports = stat; @@ -61356,7 +60786,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 572 */ +/* 580 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61417,14 +60847,14 @@ function callOnce (fn) { /***/ }), -/* 573 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(572); +const call = __webpack_require__(580); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -61488,7 +60918,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 574 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61517,7 +60947,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 575 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61525,12 +60955,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(576); -const DirectoryReader = __webpack_require__(568); +const maybe = __webpack_require__(584); +const DirectoryReader = __webpack_require__(576); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(577), + forEach: __webpack_require__(585), async: true }; @@ -61572,7 +61002,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 576 */ +/* 584 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61599,7 +61029,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 577 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61635,7 +61065,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 578 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61643,11 +61073,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(568); +const DirectoryReader = __webpack_require__(576); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(577), + forEach: __webpack_require__(585), async: true }; @@ -61667,16 +61097,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 579 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(580); -var entry_1 = __webpack_require__(582); -var pathUtil = __webpack_require__(581); +var deep_1 = __webpack_require__(588); +var entry_1 = __webpack_require__(590); +var pathUtil = __webpack_require__(589); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -61742,14 +61172,14 @@ exports.default = Reader; /***/ }), -/* 580 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(581); -var patternUtils = __webpack_require__(413); +var pathUtils = __webpack_require__(589); +var patternUtils = __webpack_require__(421); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -61832,7 +61262,7 @@ exports.default = DeepFilter; /***/ }), -/* 581 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61863,14 +61293,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 582 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(581); -var patternUtils = __webpack_require__(413); +var pathUtils = __webpack_require__(589); +var patternUtils = __webpack_require__(421); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -61955,7 +61385,7 @@ exports.default = EntryFilter; /***/ }), -/* 583 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61975,8 +61405,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(28); -var fsStat = __webpack_require__(584); -var fs_1 = __webpack_require__(588); +var fsStat = __webpack_require__(592); +var fs_1 = __webpack_require__(596); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -62026,14 +61456,14 @@ exports.default = FileSystemStream; /***/ }), -/* 584 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(585); -const statProvider = __webpack_require__(587); +const optionsManager = __webpack_require__(593); +const statProvider = __webpack_require__(595); /** * Asynchronous API. */ @@ -62064,13 +61494,13 @@ exports.statSync = statSync; /***/ }), -/* 585 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(586); +const fsAdapter = __webpack_require__(594); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -62083,7 +61513,7 @@ exports.prepare = prepare; /***/ }), -/* 586 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62106,7 +61536,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 587 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62158,7 +61588,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 588 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62189,7 +61619,7 @@ exports.default = FileSystem; /***/ }), -/* 589 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62209,9 +61639,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(28); -var readdir = __webpack_require__(566); -var reader_1 = __webpack_require__(579); -var fs_stream_1 = __webpack_require__(583); +var readdir = __webpack_require__(574); +var reader_1 = __webpack_require__(587); +var fs_stream_1 = __webpack_require__(591); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -62279,7 +61709,7 @@ exports.default = ReaderStream; /***/ }), -/* 590 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62298,9 +61728,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(566); -var reader_1 = __webpack_require__(579); -var fs_sync_1 = __webpack_require__(591); +var readdir = __webpack_require__(574); +var reader_1 = __webpack_require__(587); +var fs_sync_1 = __webpack_require__(599); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -62360,7 +61790,7 @@ exports.default = ReaderSync; /***/ }), -/* 591 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62379,8 +61809,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(584); -var fs_1 = __webpack_require__(588); +var fsStat = __webpack_require__(592); +var fs_1 = __webpack_require__(596); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -62426,7 +61856,7 @@ exports.default = FileSystemSync; /***/ }), -/* 592 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62442,13 +61872,13 @@ exports.flatten = flatten; /***/ }), -/* 593 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(594); +var merge2 = __webpack_require__(602); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -62463,7 +61893,7 @@ exports.merge = merge; /***/ }), -/* 594 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62577,13 +62007,13 @@ function pauseStreams (streams, options) { /***/ }), -/* 595 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(596); +const pathType = __webpack_require__(604); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -62649,13 +62079,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 596 */ +/* 604 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(597); +const pify = __webpack_require__(605); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -62698,7 +62128,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 597 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62789,17 +62219,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 598 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(409); -const gitIgnore = __webpack_require__(599); -const pify = __webpack_require__(600); -const slash = __webpack_require__(601); +const fastGlob = __webpack_require__(417); +const gitIgnore = __webpack_require__(607); +const pify = __webpack_require__(608); +const slash = __webpack_require__(609); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -62897,7 +62327,7 @@ module.exports.sync = options => { /***/ }), -/* 599 */ +/* 607 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -63366,7 +62796,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 600 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63441,7 +62871,7 @@ module.exports = (input, options) => { /***/ }), -/* 601 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63459,17 +62889,17 @@ module.exports = input => { /***/ }), -/* 602 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const {Buffer} = __webpack_require__(603); -const CpFileError = __webpack_require__(605); -const fs = __webpack_require__(607); -const ProgressEmitter = __webpack_require__(609); +const {Buffer} = __webpack_require__(611); +const CpFileError = __webpack_require__(613); +const fs = __webpack_require__(615); +const ProgressEmitter = __webpack_require__(617); const cpFile = (source, destination, options) => { if (!source || !destination) { @@ -63623,11 +63053,11 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 603 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { /* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(604) +var buffer = __webpack_require__(612) var Buffer = buffer.Buffer // alternative to using Object.keys for old browsers @@ -63691,18 +63121,18 @@ SafeBuffer.allocUnsafeSlow = function (size) { /***/ }), -/* 604 */ +/* 612 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 605 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(606); +const NestedError = __webpack_require__(614); class CpFileError extends NestedError { constructor(message, nested) { @@ -63716,7 +63146,7 @@ module.exports = CpFileError; /***/ }), -/* 606 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(44); @@ -63770,15 +63200,15 @@ module.exports = NestedError; /***/ }), -/* 607 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(22); const makeDir = __webpack_require__(115); -const pify = __webpack_require__(608); -const CpFileError = __webpack_require__(605); +const pify = __webpack_require__(616); +const CpFileError = __webpack_require__(613); const fsP = pify(fs); @@ -63923,7 +63353,7 @@ if (fs.copyFileSync) { /***/ }), -/* 608 */ +/* 616 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63998,7 +63428,7 @@ module.exports = (input, options) => { /***/ }), -/* 609 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64039,12 +63469,12 @@ module.exports = ProgressEmitter; /***/ }), -/* 610 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(611); +const NestedError = __webpack_require__(619); class CpyError extends NestedError { constructor(message, nested) { @@ -64058,7 +63488,7 @@ module.exports = CpyError; /***/ }), -/* 611 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -64114,7 +63544,7 @@ module.exports = NestedError; /***/ }), -/* 612 */ +/* 620 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index 8480e74ceb3a2..9d258af96996b 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -18,7 +18,6 @@ "@types/cmd-shim": "^2.0.0", "@types/cpy": "^5.1.0", "@types/dedent": "^0.7.0", - "@types/execa": "^0.9.0", "@types/getopts": "^2.0.1", "@types/glob": "^5.0.35", "@types/globby": "^6.1.0", @@ -41,7 +40,7 @@ "cpy": "^7.3.0", "dedent": "^0.7.0", "del": "^4.1.1", - "execa": "^1.0.0", + "execa": "^3.2.0", "getopts": "^2.2.4", "glob": "^7.1.2", "globby": "^8.0.1", diff --git a/packages/kbn-pm/src/utils/child_process.ts b/packages/kbn-pm/src/utils/child_process.ts index 9b4b7b2516f1c..784446924a8dc 100644 --- a/packages/kbn-pm/src/utils/child_process.ts +++ b/packages/kbn-pm/src/utils/child_process.ts @@ -34,6 +34,7 @@ function generateColors() { export function spawn(command: string, args: string[], opts: execa.Options) { return execa(command, args, { stdio: 'inherit', + preferLocal: true, ...opts, }); } @@ -48,6 +49,7 @@ export function spawnStreaming( ) { const spawned = execa(command, args, { stdio: ['ignore', 'pipe', 'pipe'], + preferLocal: true, ...opts, }); diff --git a/renovate.json5 b/renovate.json5 index 21af4ad1e83f8..12e101fd31d77 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -353,14 +353,6 @@ '@types/elasticsearch', ], }, - { - groupSlug: 'execa', - groupName: 'execa related packages', - packageNames: [ - 'execa', - '@types/execa', - ], - }, { groupSlug: 'fetch-mock', groupName: 'fetch-mock related packages', diff --git a/src/core/utils/integration_tests/deep_freeze.test.ts b/src/core/utils/integration_tests/deep_freeze.test.ts index a9440f70ae470..e6625542bc38a 100644 --- a/src/core/utils/integration_tests/deep_freeze.test.ts +++ b/src/core/utils/integration_tests/deep_freeze.test.ts @@ -27,16 +27,14 @@ it( 'types return values to prevent mutations in typescript', async () => { await expect( - execa.stdout('tsc', ['--noEmit'], { + execa('tsc', ['--noEmit'], { cwd: resolve(__dirname, '__fixtures__/frozen_object_mutation'), - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(` -"Command failed: tsc --noEmit - -index.ts(28,12): error TS2540: Cannot assign to 'baz' because it is a read-only property. -index.ts(36,11): error TS2540: Cannot assign to 'bar' because it is a read-only property. -" -`); + preferLocal: true, + }).catch(err => err.stdout) + ).resolves.toMatchInlineSnapshot(` + "index.ts(28,12): error TS2540: Cannot assign to 'baz' because it is a read-only property. + index.ts(36,11): error TS2540: Cannot assign to 'bar' because it is a read-only property." + `); }, MINUTE ); diff --git a/src/dev/build/lib/exec.js b/src/dev/build/lib/exec.js index 57dced92ca625..82762f3bd03a9 100644 --- a/src/dev/build/lib/exec.js +++ b/src/dev/build/lib/exec.js @@ -36,6 +36,7 @@ export async function exec(log, cmd, args, options = {}) { stdio: ['ignore', 'pipe', 'pipe'], cwd, env, + preferLocal: true, }); await watchStdioForLine(proc, line => log[level](line), exitAfter); diff --git a/src/dev/build/lib/version_info.js b/src/dev/build/lib/version_info.js index b0f51eaaa1d79..8225000c13f07 100644 --- a/src/dev/build/lib/version_info.js +++ b/src/dev/build/lib/version_info.js @@ -28,7 +28,9 @@ async function getBuildNumber() { return log.stdout.split('\n').length; } - const wc = await execa.shell('git log --format="%h" | wc -l'); + const wc = await execa.command('git log --format="%h" | wc -l', { + shell: true + }); return parseFloat(wc.stdout.trim()); } @@ -39,7 +41,7 @@ export async function getVersionInfo({ isRelease, versionQualifier, pkg }) { ); return { - buildSha: await execa.stdout('git', ['rev-parse', 'HEAD']), + buildSha: (await execa('git', ['rev-parse', 'HEAD'])).stdout, buildVersion, buildNumber: await getBuildNumber(), }; diff --git a/src/dev/jest/integration_tests/junit_reporter.test.js b/src/dev/jest/integration_tests/junit_reporter.test.js index c26c8cfad8025..ed5d73cd87c40 100644 --- a/src/dev/jest/integration_tests/junit_reporter.test.js +++ b/src/dev/jest/integration_tests/junit_reporter.test.js @@ -52,7 +52,7 @@ it( } ); - expect(result.code).toBe(1); + expect(result.exitCode).toBe(1); await expect(parseXml(readFileSync(XML_PATH, 'utf8'))).resolves.toEqual({ testsuites: { $: { diff --git a/src/dev/prs/run_update_prs_cli.ts b/src/dev/prs/run_update_prs_cli.ts index 6d99ac5fa45f3..bb7f50758a28c 100644 --- a/src/dev/prs/run_update_prs_cli.ts +++ b/src/dev/prs/run_update_prs_cli.ts @@ -86,7 +86,7 @@ run( // attempt to init upstream remote await execInDir('git', ['remote', 'add', 'upstream', UPSTREAM_URL]); } catch (error) { - if (error.code !== 128) { + if (error.exitCode !== 128) { throw error; } diff --git a/src/dev/run_check_core_api_changes.ts b/src/dev/run_check_core_api_changes.ts index d2c75c86ce744..ccf92cc432d2b 100644 --- a/src/dev/run_check_core_api_changes.ts +++ b/src/dev/run_check_core_api_changes.ts @@ -76,12 +76,16 @@ const apiExtractorConfig = (folder: string): ExtractorConfig => { }; const runBuildTypes = async () => { - await execa.shell('yarn run build:types'); + await execa('yarn', ['run', 'build:types']); }; const runApiDocumenter = async (folder: string) => { - await execa.shell( - `api-documenter markdown -i ./build/${folder} -o ./docs/development/core/${folder}` + await execa( + 'api-documenter', + ['markdown', '-i', `./build/${folder}`, '-o', `./docs/development/core/${folder}`], + { + preferLocal: true, + } ); }; diff --git a/src/dev/typescript/exec_in_projects.ts b/src/dev/typescript/exec_in_projects.ts index 8895e964c7817..a34f2bdd28670 100644 --- a/src/dev/typescript/exec_in_projects.ts +++ b/src/dev/typescript/exec_in_projects.ts @@ -45,6 +45,7 @@ export function execInProjects( cwd: process.cwd(), env: chalk.enabled ? { FORCE_COLOR: 'true' } : {}, stdio: ['ignore', 'pipe', 'pipe'], + preferLocal: true, }).catch(error => { throw new ProjectFailure(project, error); }), diff --git a/src/dev/typescript/run_check_ts_projects_cli.ts b/src/dev/typescript/run_check_ts_projects_cli.ts index f42a4e2759370..85f3d473dce6b 100644 --- a/src/dev/typescript/run_check_ts_projects_cli.ts +++ b/src/dev/typescript/run_check_ts_projects_cli.ts @@ -30,7 +30,7 @@ import { PROJECTS } from './projects'; export async function runCheckTsProjectsCli() { run( async ({ log }) => { - const files = await execa.stdout('git', ['ls-tree', '--name-only', '-r', 'HEAD'], { + const { stdout: files } = await execa('git', ['ls-tree', '--name-only', '-r', 'HEAD'], { cwd: REPO_ROOT, }); diff --git a/tasks/function_test_groups.js b/tasks/function_test_groups.js index 69b998c4f229b..31656df2cb644 100644 --- a/tasks/function_test_groups.js +++ b/tasks/function_test_groups.js @@ -58,12 +58,13 @@ grunt.registerTask( const done = this.async(); try { - const stats = JSON.parse(await execa.stderr(process.execPath, [ + const result = await execa(process.execPath, [ 'scripts/functional_test_runner', ...TEST_TAGS.map(tag => `--include-tag=${tag}`), '--config', 'test/functional/config.js', '--test-stats' - ])); + ]); + const stats = JSON.parse(result.stderr); if (stats.excludedTests.length > 0) { grunt.fail.fatal(` diff --git a/x-pack/package.json b/x-pack/package.json index d55910ccd5a5c..bb77508f769b2 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -133,7 +133,7 @@ "enzyme-adapter-react-16": "^1.14.0", "enzyme-adapter-utils": "^1.12.0", "enzyme-to-json": "^3.3.4", - "execa": "^1.0.0", + "execa": "^3.2.0", "fancy-log": "^1.3.2", "fetch-mock": "^7.3.9", "graphql-code-generator": "^0.18.2", diff --git a/yarn.lock b/yarn.lock index 606487f607648..26949392b2ba4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3295,13 +3295,6 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" integrity sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA== -"@types/execa@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@types/execa/-/execa-0.9.0.tgz#9b025d2755f17e80beaf9368c3f4f319d8b0fb93" - integrity sha512-mgfd93RhzjYBUHHV532turHC2j4l/qxsF/PbfDmprHDEUHmNZGlDn1CEsulGK3AfsPdhkWzZQT/S/k0UGhLGsA== - dependencies: - "@types/node" "*" - "@types/fancy-log@^1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@types/fancy-log/-/fancy-log-1.3.1.tgz#dd94fbc8c2e2ab8ab402ca8d04bb8c34965f0696" @@ -9090,6 +9083,15 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" @@ -11840,6 +11842,22 @@ execa@^2.0.4: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-3.2.0.tgz#18326b79c7ab7fbd6610fd900c1b9e95fa48f90a" + integrity sha512-kJJfVbI/lZE1PZYDI5VPxp8zXPO9rtxOkhpZ0jMKha56AI9y2gGVC6bkukStQf0ka5Rh15BA5m7cCCH4jmHqkw== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execall@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73" @@ -15125,6 +15143,11 @@ https-proxy-agent@^2.2.2: agent-base "^4.3.0" debug "^3.1.0" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -20386,6 +20409,13 @@ npm-run-path@^3.0.0: dependencies: path-key "^3.0.0" +npm-run-path@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.0.tgz#d644ec1bd0569187d2a52909971023a0a58e8438" + integrity sha512-8eyAOAH+bYXFPSnNnKr3J+yoybe8O87Is5rtAQ8qRczJz1ajcsjg8l2oZqP+Ppx15Ii3S1vUTjQN2h4YO2tWWQ== + dependencies: + path-key "^3.0.0" + npmconf@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/npmconf/-/npmconf-2.1.3.tgz#1cbe5dd02e899d365fed7260b54055473f90a15c" @@ -21518,7 +21548,7 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-key@^3.0.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.0.tgz#99a10d870a803bdd5ee6f0470e58dfcd2f9a54d3" integrity sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg== @@ -25466,11 +25496,23 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shell-quote@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" @@ -29973,6 +30015,13 @@ which@^1.1.1, which@^1.2.1, which@^1.2.14, which@^1.2.8, which@^1.3.0: dependencies: isexe "^2.0.0" +which@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.1.tgz#f1cf94d07a8e571b6ff006aeb91d0300c47ef0a4" + integrity sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w== + dependencies: + isexe "^2.0.0" + wide-align@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" From cc4c710ef212cc792d2c63312154a5b4970e43e1 Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 23 Oct 2019 19:49:51 -0700 Subject: [PATCH 102/191] follow redirects when downloading node.js (#49133) * follow redirects when downloading node.js * always download node to test redirects * pass -L in non-windows block too * Revert "always download node to test redirects" This reverts commit 36dfe8b80afd8fca74d2783b1d0d7bfa259f4555. --- src/dev/ci_setup/setup_env.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dev/ci_setup/setup_env.sh b/src/dev/ci_setup/setup_env.sh index 51c21dc45cdd1..3b239bd3ff731 100644 --- a/src/dev/ci_setup/setup_env.sh +++ b/src/dev/ci_setup/setup_env.sh @@ -75,11 +75,11 @@ if [[ "$installNode" == "true" ]]; then mkdir -p "$nodeDir" if [[ "$OS" == "win" ]]; then nodePkg="$nodeDir/${nodeUrl##*/}" - curl --silent -o "$nodePkg" "$nodeUrl" + curl --silent -L -o "$nodePkg" "$nodeUrl" unzip -qo "$nodePkg" -d "$nodeDir" mv "${nodePkg%.*}" "$nodeBin" else - curl --silent "$nodeUrl" | tar -xz -C "$nodeDir" --strip-components=1 + curl --silent -L "$nodeUrl" | tar -xz -C "$nodeDir" --strip-components=1 fi fi fi From 8addf85fbf9f137733c7c297f28e73ec30803e6b Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 24 Oct 2019 09:28:12 +0300 Subject: [PATCH 103/191] move createGetterSetter to plugins/kibana_utils (#49069) --- .../data/public/index_patterns/services.ts | 16 +------- .../public/np_ready/public/services.ts | 16 +------- .../public/core/create_getter_setter.ts | 36 +++++++++++++++++ .../core/create_kibana_utils_core.test.ts | 39 +++++++++++++++++++ .../public/core/create_kibana_utils_core.ts | 39 +++++++++++++++++++ src/plugins/kibana_utils/public/core/index.ts | 21 ++++++++++ .../public/core/saved_objects_client.ts | 35 +++++++++++++++++ src/plugins/kibana_utils/public/core/state.ts | 23 +++++++++++ src/plugins/kibana_utils/public/index.ts | 1 + 9 files changed, 196 insertions(+), 30 deletions(-) create mode 100644 src/plugins/kibana_utils/public/core/create_getter_setter.ts create mode 100644 src/plugins/kibana_utils/public/core/create_kibana_utils_core.test.ts create mode 100644 src/plugins/kibana_utils/public/core/create_kibana_utils_core.ts create mode 100644 src/plugins/kibana_utils/public/core/index.ts create mode 100644 src/plugins/kibana_utils/public/core/saved_objects_client.ts create mode 100644 src/plugins/kibana_utils/public/core/state.ts diff --git a/src/legacy/core_plugins/data/public/index_patterns/services.ts b/src/legacy/core_plugins/data/public/index_patterns/services.ts index 3782f494e8178..5cc087548d6fb 100644 --- a/src/legacy/core_plugins/data/public/index_patterns/services.ts +++ b/src/legacy/core_plugins/data/public/index_patterns/services.ts @@ -18,21 +18,7 @@ */ import { NotificationsStart } from 'src/core/public'; - -const createGetterSetter = (name: string): [() => T, (value: T) => void] => { - let value: T; - - const get = (): T => { - if (!value) throw new Error(`${name} was not set`); - return value; - }; - - const set = (newValue: T) => { - value = newValue; - }; - - return [get, set]; -}; +import { createGetterSetter } from '../../../../../plugins/kibana_utils/public'; export const [getNotifications, setNotifications] = createGetterSetter( 'Notifications' diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/services.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/services.ts index 4d95a8a91d0bb..ae2a7955233d1 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/services.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/services.ts @@ -17,25 +17,11 @@ * under the License. */ +import { createGetterSetter } from '../../../../../../plugins/kibana_utils/public'; import { IInterpreter } from './types'; import { Start as IInspector } from '../../../../../../plugins/inspector/public'; import { ExpressionsSetup } from './plugin'; -const createGetterSetter = (name: string): [() => T, (value: T) => void] => { - let value: T; - - const get = (): T => { - if (!value) throw new Error(`${name} was not set`); - return value; - }; - - const set = (newValue: T) => { - value = newValue; - }; - - return [get, set]; -}; - export const [getInspector, setInspector] = createGetterSetter('Inspector'); export const [getInterpreter, setInterpreter] = createGetterSetter('Interpreter'); export const [getRenderersRegistry, setRenderersRegistry] = createGetterSetter< diff --git a/src/plugins/kibana_utils/public/core/create_getter_setter.ts b/src/plugins/kibana_utils/public/core/create_getter_setter.ts new file mode 100644 index 0000000000000..be2fd48ee6e7b --- /dev/null +++ b/src/plugins/kibana_utils/public/core/create_getter_setter.ts @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export type Get = () => T; +export type Set = (value: T) => void; + +export const createGetterSetter = (name: string): [Get, Set] => { + let value: T; + + const get: Get = () => { + if (!value) throw new Error(`${name} was not set.`); + return value; + }; + + const set: Set = newValue => { + value = newValue; + }; + + return [get, set]; +}; diff --git a/src/plugins/kibana_utils/public/core/create_kibana_utils_core.test.ts b/src/plugins/kibana_utils/public/core/create_kibana_utils_core.test.ts new file mode 100644 index 0000000000000..c5b23bdf0055f --- /dev/null +++ b/src/plugins/kibana_utils/public/core/create_kibana_utils_core.test.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createKibanaUtilsCore } from './create_kibana_utils_core'; +import { CoreStart } from 'kibana/public'; + +describe('createKibanaUtilsCore', () => { + it('should allows to work with multiple instances', () => { + const core1 = {} as CoreStart; + const core2 = {} as CoreStart; + + const { setCoreStart: setCoreStart1, getCoreStart: getCoreStart1 } = createKibanaUtilsCore(); + const { setCoreStart: setCoreStart2, getCoreStart: getCoreStart2 } = createKibanaUtilsCore(); + + setCoreStart1(core1); + setCoreStart2(core2); + + expect(getCoreStart1()).toBe(core1); + expect(getCoreStart2()).toBe(core2); + + expect(getCoreStart1() !== getCoreStart2()).toBeTruthy(); + }); +}); diff --git a/src/plugins/kibana_utils/public/core/create_kibana_utils_core.ts b/src/plugins/kibana_utils/public/core/create_kibana_utils_core.ts new file mode 100644 index 0000000000000..84ecffa1da634 --- /dev/null +++ b/src/plugins/kibana_utils/public/core/create_kibana_utils_core.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createGetterSetter, Get, Set } from './create_getter_setter'; +import { CoreStart } from '../../../../core/public'; +import { KUSavedObjectClient, createSavedObjectsClient } from './saved_objects_client'; + +interface Return { + getCoreStart: Get; + setCoreStart: Set; + savedObjects: KUSavedObjectClient; +} + +export const createKibanaUtilsCore = (): Return => { + const [getCoreStart, setCoreStart] = createGetterSetter('CoreStart'); + const savedObjects = createSavedObjectsClient(getCoreStart); + + return { + getCoreStart, + setCoreStart, + savedObjects, + }; +}; diff --git a/src/plugins/kibana_utils/public/core/index.ts b/src/plugins/kibana_utils/public/core/index.ts new file mode 100644 index 0000000000000..7e8dff7191fe8 --- /dev/null +++ b/src/plugins/kibana_utils/public/core/index.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './create_getter_setter'; +export * from './create_kibana_utils_core'; diff --git a/src/plugins/kibana_utils/public/core/saved_objects_client.ts b/src/plugins/kibana_utils/public/core/saved_objects_client.ts new file mode 100644 index 0000000000000..40407fea5d189 --- /dev/null +++ b/src/plugins/kibana_utils/public/core/saved_objects_client.ts @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreStart } from '../../../../core/public'; +import { Get } from './create_getter_setter'; + +type CoreSavedObjectClient = CoreStart['savedObjects']['client']; + +export interface KUSavedObjectClient { + get: CoreSavedObjectClient['get']; +} + +export const createSavedObjectsClient = (getCoreStart: Get) => { + const savedObjectsClient: KUSavedObjectClient = { + get: (...args) => getCoreStart().savedObjects.client.get(...args), + }; + + return savedObjectsClient; +}; diff --git a/src/plugins/kibana_utils/public/core/state.ts b/src/plugins/kibana_utils/public/core/state.ts new file mode 100644 index 0000000000000..8ac6e4e0e58e6 --- /dev/null +++ b/src/plugins/kibana_utils/public/core/state.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createGetterSetter } from './create_getter_setter'; +import { CoreStart } from '../../../../core/public'; + +export const [getCoreStart, setCoreStart] = createGetterSetter('CoreStart'); diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts index bac0ef629789a..7cb4d4a34e971 100644 --- a/src/plugins/kibana_utils/public/index.ts +++ b/src/plugins/kibana_utils/public/index.ts @@ -17,6 +17,7 @@ * under the License. */ +export * from './core'; export * from './store'; export * from './parse'; export * from './render_complete'; From 3fd9f914374f08e17afd4b054c22eca6d5a65ffe Mon Sep 17 00:00:00 2001 From: Artyom Gospodarsky Date: Thu, 24 Oct 2019 11:22:09 +0300 Subject: [PATCH 104/191] Set values as html to table rows (#48911) --- .../kbn_doc_views/public/views/table/table_row.tsx | 8 +++++--- src/plugins/data/common/field_formats/converters/url.ts | 2 -- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx b/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx index 2059e35b2c42e..cfc539eafe7b9 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx +++ b/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx @@ -93,9 +93,11 @@ export function DocViewTableRow({ )} {displayUnderscoreWarning && } {displayNoMappingWarning && } -
- {value} -
+
); diff --git a/src/plugins/data/common/field_formats/converters/url.ts b/src/plugins/data/common/field_formats/converters/url.ts index 984cced336d2b..6c00f11a408dc 100644 --- a/src/plugins/data/common/field_formats/converters/url.ts +++ b/src/plugins/data/common/field_formats/converters/url.ts @@ -198,5 +198,3 @@ export class UrlFormat extends FieldFormat { } }; } - -// console.log(UrlFormat); From fc306c4451ad54c9e2e2c82f0bd8515b6d52dbb4 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Thu, 24 Oct 2019 10:31:15 +0200 Subject: [PATCH 105/191] [APM] Refactor & scope aggregation types (#48394) * [APM] Refactor & scope aggregation types Iterate on the APM aggregation types, make them more readable and explicitly scope them as APM-specific. ES typings: - Refactored aggregation types (mostly better naming, slightly less hacks) - Do not add APM typings to `elasticsearch` module to explicitly scope them as APM specific - Make restTotalHitsAsInt a type option rather than a separate type - `terms` bucket key type now accounts for the fact it can be both number and string `mergeProjection`: - Type check arguments for compatibility with ESSearchRequest - Require valid aggregation objects in source parameter. Seems less brittle, and surfaces errors closer to the source Other changes: - Sort options in some cases need `as const`, type casts or type guards - Simplify types for metric aggregations * Add type casts for bucket keys in remaining places * Review feedback --- .../plugins/apm/common/projections/typings.ts | 15 +- .../util/merge_projection/index.test.ts | 7 +- .../util/merge_projection/index.ts | 20 +- .../app/ErrorGroupOverview/index.tsx | 4 +- .../plugins/apm/public/services/rest/ml.ts | 2 +- .../plugins/apm/public/utils/testHelpers.tsx | 2 +- .../lib/errors/distribution/get_buckets.ts | 2 +- .../apm/server/lib/errors/get_error_groups.ts | 22 +- .../get_environment_ui_filter_es.test.ts | 2 +- .../get_environment_ui_filter_es.ts | 2 +- .../get_kuery_ui_filter_es.ts | 2 +- .../convert_ui_filters/get_ui_filters_es.ts | 2 +- .../apm/server/lib/helpers/es_client.ts | 20 +- .../server/lib/helpers/setup_request.test.ts | 2 +- .../java/gc/fetchAndTransformGcMetrics.ts | 2 +- .../metrics/fetch_and_transform_metrics.ts | 14 +- .../lib/metrics/transform_metrics_chart.ts | 57 ++-- .../apm/server/lib/service_nodes/index.ts | 64 ++--- .../lib/services/get_service_agent_name.ts | 4 +- .../services/get_service_transaction_types.ts | 2 +- .../services/get_services/get_agent_status.ts | 11 +- .../get_services/get_services_items.ts | 9 +- .../get_agent_name_by_service.ts | 4 +- .../get_environments/get_all_environments.ts | 2 +- .../get_existing_environments_for_service.ts | 2 +- .../agent_configuration/get_service_names.ts | 2 +- .../settings/agent_configuration/search.ts | 5 +- .../apm/server/lib/traces/get_trace_items.ts | 13 +- .../server/lib/transaction_groups/fetcher.ts | 17 +- .../lib/transaction_groups/transform.ts | 5 +- .../avg_duration_by_country/index.ts | 2 +- .../lib/transactions/breakdown/index.ts | 8 +- .../get_anomaly_data/get_ml_bucket_size.ts | 2 +- .../charts/get_timeseries_data/fetcher.ts | 2 +- .../charts/get_timeseries_data/transform.ts | 5 +- .../distribution/get_buckets/fetcher.ts | 7 +- .../server/lib/ui_filters/get_environments.ts | 4 +- .../get_filter_aggregations.ts | 2 +- .../lib/ui_filters/local_ui_filters/index.ts | 2 +- .../plugins/apm/server/routes/errors.ts | 2 +- .../plugins/apm/typings/elasticsearch.ts | 203 -------------- .../apm/typings/elasticsearch/aggregations.ts | 256 ++++++++++++++++++ .../apm/typings/elasticsearch/index.ts | 60 ++++ .../plugins/lens/server/routes/field_stats.ts | 31 +-- .../legacy/plugins/lens/server/usage/task.ts | 11 +- 45 files changed, 532 insertions(+), 382 deletions(-) delete mode 100644 x-pack/legacy/plugins/apm/typings/elasticsearch.ts create mode 100644 x-pack/legacy/plugins/apm/typings/elasticsearch/aggregations.ts create mode 100644 x-pack/legacy/plugins/apm/typings/elasticsearch/index.ts diff --git a/x-pack/legacy/plugins/apm/common/projections/typings.ts b/x-pack/legacy/plugins/apm/common/projections/typings.ts index 0c56fd2f75bde..2b55395b70c6b 100644 --- a/x-pack/legacy/plugins/apm/common/projections/typings.ts +++ b/x-pack/legacy/plugins/apm/common/projections/typings.ts @@ -4,15 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams } from 'elasticsearch'; +import { ESSearchRequest, ESSearchBody } from '../../typings/elasticsearch'; +import { + AggregationOptionsByType, + AggregationInputMap +} from '../../typings/elasticsearch/aggregations'; -export type Projection = Omit & { - body: { - query: any; - } & { +export type Projection = Omit & { + body: Omit & { aggs?: { [key: string]: { - terms: any; + terms: AggregationOptionsByType['terms']; + aggs?: AggregationInputMap; }; }; }; diff --git a/x-pack/legacy/plugins/apm/common/projections/util/merge_projection/index.test.ts b/x-pack/legacy/plugins/apm/common/projections/util/merge_projection/index.test.ts index ae1b7c552ab4e..aa72b5fd71365 100644 --- a/x-pack/legacy/plugins/apm/common/projections/util/merge_projection/index.test.ts +++ b/x-pack/legacy/plugins/apm/common/projections/util/merge_projection/index.test.ts @@ -29,12 +29,15 @@ describe('mergeProjection', () => { }); it('merges plain objects', () => { + const termsAgg = { terms: { field: 'bar' } }; expect( mergeProjection( - { body: { query: {}, aggs: { foo: { terms: { field: 'bar' } } } } }, + { body: { query: {}, aggs: { foo: termsAgg } } }, { body: { - aggs: { foo: { aggs: { bar: { terms: { field: 'baz' } } } } } + aggs: { + foo: { ...termsAgg, aggs: { bar: { terms: { field: 'baz' } } } } + } } } ) diff --git a/x-pack/legacy/plugins/apm/common/projections/util/merge_projection/index.ts b/x-pack/legacy/plugins/apm/common/projections/util/merge_projection/index.ts index 5b6b5b0b7f058..9a8f11c6493c5 100644 --- a/x-pack/legacy/plugins/apm/common/projections/util/merge_projection/index.ts +++ b/x-pack/legacy/plugins/apm/common/projections/util/merge_projection/index.ts @@ -4,10 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ import { merge, isPlainObject } from 'lodash'; +import { DeepPartial } from 'utility-types'; +import { AggregationInputMap } from '../../../../typings/elasticsearch/aggregations'; +import { + ESSearchRequest, + ESSearchBody +} from '../../../../typings/elasticsearch'; import { Projection } from '../../typings'; type PlainObject = Record; +type SourceProjection = Omit, 'body'> & { + body: Omit, 'aggs'> & { + aggs?: AggregationInputMap; + }; +}; + type DeepMerge = U extends PlainObject ? (T extends PlainObject ? (Omit & @@ -19,10 +31,10 @@ type DeepMerge = U extends PlainObject : U) : U; -export function mergeProjection( - target: T, - source: U -): DeepMerge { +export function mergeProjection< + T extends Projection, + U extends SourceProjection +>(target: T, source: U): DeepMerge { return merge({}, target, source, (a, b) => { if (isPlainObject(a) && isPlainObject(b)) { return undefined; diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/index.tsx index 92ae1737a408f..fe1a80d702dba 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/index.tsx @@ -49,6 +49,8 @@ const ErrorGroupOverview: React.SFC = () => { const { data: errorGroupListData } = useFetcher( callApmApi => { + const normalizedSortDirection = sortDirection === 'asc' ? 'asc' : 'desc'; + if (serviceName && start && end) { return callApmApi({ pathname: '/api/apm/services/{serviceName}/errors', @@ -60,7 +62,7 @@ const ErrorGroupOverview: React.SFC = () => { start, end, sortField, - sortDirection, + sortDirection: normalizedSortDirection, uiFilters: JSON.stringify(uiFilters) } } diff --git a/x-pack/legacy/plugins/apm/public/services/rest/ml.ts b/x-pack/legacy/plugins/apm/public/services/rest/ml.ts index 968450e6aa796..9150c63127317 100644 --- a/x-pack/legacy/plugins/apm/public/services/rest/ml.ts +++ b/x-pack/legacy/plugins/apm/public/services/rest/ml.ts @@ -5,7 +5,6 @@ */ import { npStart } from 'ui/new_platform'; -import { ESFilter } from 'elasticsearch'; import { HttpServiceBase } from 'kibana/public'; import { PROCESSOR_EVENT, @@ -14,6 +13,7 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { getMlJobId, getMlPrefix } from '../../../common/ml_job_constants'; import { callApi } from './callApi'; +import { ESFilter } from '../../../typings/elasticsearch'; interface MlResponseItem { id: string; diff --git a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx index 73b81bfed4794..2e3c8940680fe 100644 --- a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx @@ -15,9 +15,9 @@ import { Moment } from 'moment-timezone'; import React from 'react'; import { render, waitForElement } from 'react-testing-library'; import { MemoryRouter } from 'react-router-dom'; -import { ESFilter } from 'elasticsearch'; import { LocationProvider } from '../context/LocationContext'; import { PromiseReturnType } from '../../typings/common'; +import { ESFilter } from '../../typings/elasticsearch'; export function toJson(wrapper: ReactWrapper) { return enzymeToJson(wrapper, { diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts index 9c49a7f613aaa..6059f2b0051a7 100644 --- a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts +++ b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ESFilter } from 'elasticsearch'; import { idx } from '@kbn/elastic-idx'; +import { ESFilter } from '../../../../typings/elasticsearch'; import { ERROR_GROUP_ID, PROCESSOR_EVENT, diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts b/x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts index f692f94e255fc..193ee4c2bbd1c 100644 --- a/x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts +++ b/x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts @@ -17,6 +17,7 @@ import { APMError } from '../../../typings/es_schemas/ui/APMError'; import { Setup } from '../helpers/setup_request'; import { getErrorGroupsProjection } from '../../../common/projections/errors'; import { mergeProjection } from '../../../common/projections/util/merge_projection'; +import { SortOptions } from '../../../typings/elasticsearch/aggregations'; export type ErrorGroupListAPIResponse = PromiseReturnType< typeof getErrorGroups @@ -30,7 +31,7 @@ export async function getErrorGroups({ }: { serviceName: string; sortField?: string; - sortDirection?: string; + sortDirection?: 'asc' | 'desc'; setup: Setup; }) { const { client } = setup; @@ -40,18 +41,21 @@ export async function getErrorGroups({ const projection = getErrorGroupsProjection({ setup, serviceName }); + const order: SortOptions = sortByLatestOccurrence + ? { + max_timestamp: sortDirection + } + : { _count: sortDirection }; + const params = mergeProjection(projection, { body: { size: 0, aggs: { error_groups: { terms: { + ...projection.body.aggs.error_groups.terms, size: 500, - order: sortByLatestOccurrence - ? { - max_timestamp: sortDirection - } - : { _count: sortDirection } + order }, aggs: { sample: { @@ -64,7 +68,7 @@ export async function getErrorGroups({ ERROR_GROUP_ID, '@timestamp' ], - sort: [{ '@timestamp': 'desc' }], + sort: [{ '@timestamp': 'desc' as const }], size: 1 } }, @@ -98,13 +102,13 @@ export async function getErrorGroups({ }; } - const resp = await client.search(params); + const resp = await client.search(params); // aggregations can be undefined when no matching indices are found. // this is an exception rather than the rule so the ES type does not account for this. const hits = (idx(resp, _ => _.aggregations.error_groups.buckets) || []).map( bucket => { - const source = bucket.sample.hits.hits[0]._source as SampleError; + const source = bucket.sample.hits.hits[0]._source; const message = idx(source, _ => _.error.log.message) || idx(source, _ => _.error.exception[0].message); diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/__test__/get_environment_ui_filter_es.test.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/__test__/get_environment_ui_filter_es.test.ts index df471af4f5ee0..0f0a11a868d6d 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/__test__/get_environment_ui_filter_es.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/__test__/get_environment_ui_filter_es.test.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ESFilter } from 'elasticsearch'; import { getEnvironmentUiFilterES } from '../get_environment_ui_filter_es'; import { ENVIRONMENT_NOT_DEFINED } from '../../../../../common/environment_filter_values'; import { SERVICE_ENVIRONMENT } from '../../../../../common/elasticsearch_fieldnames'; +import { ESFilter } from '../../../../../typings/elasticsearch'; describe('getEnvironmentUiFilterES', () => { it('should return undefined, when environment is undefined', () => { diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_environment_ui_filter_es.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_environment_ui_filter_es.ts index 8a94e42a40b21..57feaf6a6fd0e 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_environment_ui_filter_es.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_environment_ui_filter_es.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ESFilter } from 'elasticsearch'; +import { ESFilter } from '../../../../typings/elasticsearch'; import { ENVIRONMENT_NOT_DEFINED } from '../../../../common/environment_filter_values'; import { SERVICE_ENVIRONMENT } from '../../../../common/elasticsearch_fieldnames'; diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_kuery_ui_filter_es.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_kuery_ui_filter_es.ts index 4ba4caa8c69d8..2543c2b9a8a61 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_kuery_ui_filter_es.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_kuery_ui_filter_es.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ESFilter } from 'elasticsearch'; import { Server } from 'hapi'; import { idx } from '@kbn/elastic-idx'; import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query'; +import { ESFilter } from '../../../../typings/elasticsearch'; import { ISavedObject } from '../../../../public/services/rest/savedObjects'; import { StaticIndexPattern } from '../../../../../../../../src/legacy/core_plugins/data/public'; import { getAPMIndexPattern } from '../../../lib/index_pattern'; diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_ui_filters_es.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_ui_filters_es.ts index 1658cb07e4d2f..bea7e510875db 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_ui_filters_es.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/convert_ui_filters/get_ui_filters_es.ts @@ -5,7 +5,7 @@ */ import { Server } from 'hapi'; -import { ESFilter } from 'elasticsearch'; +import { ESFilter } from '../../../../typings/elasticsearch'; import { UIFilters } from '../../../../typings/ui-filters'; import { getEnvironmentUiFilterES } from './get_environment_ui_filter_es'; import { getKueryUiFilterES } from './get_kuery_ui_filter_es'; diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts index 79fcfe95c0552..9b2c97fab7aa3 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts @@ -9,13 +9,16 @@ import { SearchParams, IndexDocumentParams, IndicesDeleteParams, - IndicesCreateParams, - AggregationSearchResponseWithTotalHitsAsObject + IndicesCreateParams } from 'elasticsearch'; import { Legacy } from 'kibana'; import { cloneDeep, has, isString, set } from 'lodash'; import { OBSERVER_VERSION_MAJOR } from '../../../common/elasticsearch_fieldnames'; import { StringMap } from '../../../typings/common'; +import { + ESSearchResponse, + ESSearchRequest +} from '../../../typings/elasticsearch'; // `type` was deprecated in 7.0 export type APMIndexDocumentParams = Omit, 'type'>; @@ -92,10 +95,13 @@ export function getESClient(req: Legacy.Request) { const query = req.query as StringMap; return { - search: async ( - params: U, + search: async < + TDocument = unknown, + TSearchRequest extends ESSearchRequest = {} + >( + params: TSearchRequest, apmOptions?: APMOptions - ): Promise> => { + ): Promise> => { const nextParams = await getParamsForSearchRequest( req, params, @@ -117,9 +123,7 @@ export function getESClient(req: Legacy.Request) { req, 'search', nextParams - ) as unknown) as Promise< - AggregationSearchResponseWithTotalHitsAsObject - >; + ) as unknown) as Promise>; }, index: (params: APMIndexDocumentParams) => { return cluster.callWithRequest(req, 'index', params); diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts index cfc33b4fad7ea..e8cf56fcd0802 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -31,7 +31,7 @@ describe('setupRequest', () => { it('should call callWithRequest with default args', async () => { const { mockRequest, callWithRequestSpy } = getMockRequest(); const { client } = await setupRequest(mockRequest); - await client.search({ index: 'apm-*', body: { foo: 'bar' } }); + await client.search({ index: 'apm-*', body: { foo: 'bar' } } as any); expect(callWithRequestSpy).toHaveBeenCalledWith(mockRequest, 'search', { index: 'apm-*', body: { diff --git a/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts b/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts index 7b8fc4ac44f64..f785e45062807 100644 --- a/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts +++ b/x-pack/legacy/plugins/apm/server/lib/metrics/by_agent/java/gc/fetchAndTransformGcMetrics.ts @@ -124,7 +124,7 @@ export async function fetchAndTransformGcMetrics({ } const series = aggregations.per_pool.buckets.map((poolBucket, i) => { - const label = poolBucket.key; + const label = poolBucket.key as string; const timeseriesData = poolBucket.over_time; const data = (idx(timeseriesData, _ => _.buckets) || []).map(bucket => { diff --git a/x-pack/legacy/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts b/x-pack/legacy/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts index 9837fb21b6da0..3d425e50bc60a 100644 --- a/x-pack/legacy/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts +++ b/x-pack/legacy/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts @@ -4,20 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Unionize } from 'utility-types'; import { Setup } from '../helpers/setup_request'; import { getMetricsDateHistogramParams } from '../helpers/metrics'; import { ChartBase } from './types'; import { transformDataToMetricsChart } from './transform_metrics_chart'; import { getMetricsProjection } from '../../../common/projections/metrics'; import { mergeProjection } from '../../../common/projections/util/merge_projection'; +import { AggregationOptionsByType } from '../../../typings/elasticsearch/aggregations'; interface Aggs { - [key: string]: { - min?: any; - max?: any; - sum?: any; - avg?: any; - }; + [key: string]: Unionize<{ + min: AggregationOptionsByType['min']; + max: AggregationOptionsByType['max']; + sum: AggregationOptionsByType['sum']; + avg: AggregationOptionsByType['avg']; + }>; } interface Filter { diff --git a/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts index 89bc3b4107a5f..594a0d35ed176 100644 --- a/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts +++ b/x-pack/legacy/plugins/apm/server/lib/metrics/transform_metrics_chart.ts @@ -4,12 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { - AggregationSearchResponseWithTotalHitsAsObject, - AggregatedValue -} from 'elasticsearch'; import { idx } from '@kbn/elastic-idx'; +import { Unionize, Overwrite } from 'utility-types'; import { ChartBase } from './types'; +import { + ESSearchResponse, + ESSearchRequest +} from '../../../typings/elasticsearch'; +import { AggregationOptionsByType } from '../../../typings/elasticsearch/aggregations'; const colors = [ theme.euiColorVis0, @@ -25,33 +27,30 @@ export type GenericMetricsChart = ReturnType< typeof transformDataToMetricsChart >; -interface AggregatedParams { - body: { - aggs: { - timeseriesData: { - date_histogram: any; - aggs: { - min?: any; - max?: any; - sum?: any; - avg?: any; +interface MetricsAggregationMap { + min: AggregationOptionsByType['min']; + max: AggregationOptionsByType['max']; + sum: AggregationOptionsByType['sum']; + avg: AggregationOptionsByType['avg']; +} + +type GenericMetricsRequest = Overwrite< + ESSearchRequest, + { + body: { + aggs: { + timeseriesData: { + date_histogram: AggregationOptionsByType['date_histogram']; + aggs: Record>; }; - }; - } & { - [key: string]: { - min?: any; - max?: any; - sum?: any; - avg?: any; - }; + } & Record>; }; - }; -} + } +>; -export function transformDataToMetricsChart( - result: AggregationSearchResponseWithTotalHitsAsObject, - chartBase: ChartBase -) { +export function transformDataToMetricsChart< + TRequest extends GenericMetricsRequest +>(result: ESSearchResponse, chartBase: ChartBase) { const { aggregations, hits } = result; const timeseriesData = idx(aggregations, _ => _.timeseriesData); @@ -70,7 +69,7 @@ export function transformDataToMetricsChart( color: chartBase.series[seriesKey].color || colors[i], overallValue, data: (idx(timeseriesData, _ => _.buckets) || []).map(bucket => { - const { value } = bucket[seriesKey] as AggregatedValue; + const { value } = bucket[seriesKey] as { value: number | null }; const y = value === null || isNaN(value) ? null : value; return { x: bucket.key, diff --git a/x-pack/legacy/plugins/apm/server/lib/service_nodes/index.ts b/x-pack/legacy/plugins/apm/server/lib/service_nodes/index.ts index afdf4795c4d29..1e415252200ce 100644 --- a/x-pack/legacy/plugins/apm/server/lib/service_nodes/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/service_nodes/index.ts @@ -24,45 +24,45 @@ const getServiceNodes = async ({ }) => { const { client } = setup; - const projection = mergeProjection( - getServiceNodesProjection({ setup, serviceName }), - { - body: { - aggs: { - nodes: { - terms: { - size: 10000, - missing: SERVICE_NODE_NAME_MISSING + const projection = getServiceNodesProjection({ setup, serviceName }); + + const params = mergeProjection(projection, { + body: { + aggs: { + nodes: { + terms: { + ...projection.body.aggs.nodes.terms, + size: 10000, + missing: SERVICE_NODE_NAME_MISSING + }, + aggs: { + cpu: { + avg: { + field: METRIC_PROCESS_CPU_PERCENT + } + }, + heapMemory: { + avg: { + field: METRIC_JAVA_HEAP_MEMORY_USED + } }, - aggs: { - cpu: { - avg: { - field: METRIC_PROCESS_CPU_PERCENT - } - }, - heapMemory: { - avg: { - field: METRIC_JAVA_HEAP_MEMORY_USED - } - }, - nonHeapMemory: { - avg: { - field: METRIC_JAVA_NON_HEAP_MEMORY_USED - } - }, - threadCount: { - max: { - field: METRIC_JAVA_THREAD_COUNT - } + nonHeapMemory: { + avg: { + field: METRIC_JAVA_NON_HEAP_MEMORY_USED + } + }, + threadCount: { + max: { + field: METRIC_JAVA_THREAD_COUNT } } } } } } - ); + }); - const response = await client.search(projection); + const response = await client.search(params); if (!response.aggregations) { return []; @@ -70,7 +70,7 @@ const getServiceNodes = async ({ return response.aggregations.nodes.buckets.map(bucket => { return { - name: bucket.key, + name: bucket.key as string, cpu: bucket.cpu.value, heapMemory: bucket.heapMemory.value, nonHeapMemory: bucket.nonHeapMemory.value, diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts index 3c6f684389970..b39e35a305b19 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts +++ b/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts @@ -44,6 +44,8 @@ export async function getServiceAgentName(serviceName: string, setup: Setup) { }; const { aggregations } = await client.search(params); - const agentName = idx(aggregations, _ => _.agents.buckets[0].key); + const agentName = idx(aggregations, _ => _.agents.buckets[0].key) as + | string + | undefined; return { agentName }; } diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts index a1f035da9dc1a..9d651247d5cee 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts +++ b/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts @@ -41,6 +41,6 @@ export async function getServiceTransactionTypes( const { aggregations } = await client.search(params); const buckets = idx(aggregations, _ => _.types.buckets) || []; - const transactionTypes = buckets.map(bucket => bucket.key); + const transactionTypes = buckets.map(bucket => bucket.key as string); return { transactionTypes }; } diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts index d1654632dbb26..f9a7671abd994 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts +++ b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams } from 'elasticsearch'; import { PROCESSOR_EVENT } from '../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../helpers/setup_request'; @@ -12,13 +11,13 @@ import { Setup } from '../../helpers/setup_request'; export async function getAgentStatus(setup: Setup) { const { client, config } = setup; - const params: SearchParams = { + const params = { terminateAfter: 1, index: [ - config.get('apm_oss.errorIndices'), - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.sourcemapIndices'), - config.get('apm_oss.transactionIndices') + config.get('apm_oss.errorIndices'), + config.get('apm_oss.metricsIndices'), + config.get('apm_oss.sourcemapIndices'), + config.get('apm_oss.transactionIndices') ], body: { size: 0, diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_services_items.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_services_items.ts index c50506db1faec..60f3091567059 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_services_items.ts +++ b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_services_items.ts @@ -28,6 +28,7 @@ export async function getServicesItems(setup: Setup) { aggs: { services: { terms: { + ...projection.body.aggs.services.terms, size: 500 }, aggs: { @@ -69,12 +70,14 @@ export async function getServicesItems(setup: Setup) { const environmentsBuckets = bucket.environments.buckets; const environments = environmentsBuckets.map( - environmentBucket => environmentBucket.key + environmentBucket => environmentBucket.key as string ); return { - serviceName: bucket.key, - agentName: idx(bucket, _ => _.agents.buckets[0].key), + serviceName: bucket.key as string, + agentName: idx(bucket, _ => _.agents.buckets[0].key) as + | string + | undefined, transactionsPerMinute, errorsPerMinute, avgResponseTime: bucket.avg.value, diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts index a18873e86c5a8..7742bc938816f 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts @@ -49,6 +49,8 @@ export async function getAgentNameByService({ }; const { aggregations } = await client.search(params); - const agentName = idx(aggregations, _ => _.agent_names.buckets[0].key); + const agentName = idx(aggregations, _ => _.agent_names.buckets[0].key) as + | string + | undefined; return { agentName }; } diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts index 76ebf75aada29..aad31feef000b 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts @@ -58,6 +58,6 @@ export async function getAllEnvironments({ const resp = await client.search(params); const buckets = idx(resp.aggregations, _ => _.environments.buckets) || []; - const environments = buckets.map(bucket => bucket.key); + const environments = buckets.map(bucket => bucket.key as string); return [ALL_OPTION_VALUE, ...environments]; } diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts index 120cc62cc3bc9..6b557f21f3457 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts @@ -44,5 +44,5 @@ export async function getExistingEnvironmentsForService({ const resp = await client.search(params); const buckets = idx(resp.aggregations, _ => _.environments.buckets) || []; - return buckets.map(bucket => bucket.key); + return buckets.map(bucket => bucket.key as string); } diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts index 55af96acbc719..dfc1041c96488 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts @@ -47,6 +47,6 @@ export async function getServiceNames({ setup }: { setup: Setup }) { const resp = await client.search(params); const buckets = idx(resp.aggregations, _ => _.services.buckets) || []; - const serviceNames = buckets.map(bucket => bucket.key).sort(); + const serviceNames = buckets.map(bucket => bucket.key as string).sort(); return [ALL_OPTION_VALUE, ...serviceNames]; } diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts index 664bcb9325472..6b0dc370dd878 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts @@ -3,8 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { ESSearchHit } from 'elasticsearch'; +import { ESSearchHit } from '../../../../typings/elasticsearch'; import { SERVICE_NAME, SERVICE_ENVIRONMENT @@ -50,7 +49,7 @@ export async function searchConfigurations({ } }; - const resp = await client.search(params); + const resp = await client.search(params); const { hits } = resp.hits; const exactMatch = hits.find( diff --git a/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts b/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts index 74e16424b1098..71b65982db9f0 100644 --- a/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts +++ b/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchParams } from 'elasticsearch'; import { PROCESSOR_EVENT, TRACE_ID, @@ -21,10 +20,10 @@ export async function getTraceItems(traceId: string, setup: Setup) { const { start, end, client, config } = setup; const maxTraceItems = config.get('xpack.apm.ui.maxTraceItems'); - const params: SearchParams = { + const params = { index: [ - config.get('apm_oss.spanIndices'), - config.get('apm_oss.transactionIndices') + config.get('apm_oss.spanIndices'), + config.get('apm_oss.transactionIndices') ], body: { size: maxTraceItems, @@ -41,9 +40,9 @@ export async function getTraceItems(traceId: string, setup: Setup) { } }, sort: [ - { _score: { order: 'asc' } }, - { [TRANSACTION_DURATION]: { order: 'desc' } }, - { [SPAN_DURATION]: { order: 'desc' } } + { _score: { order: 'asc' as const } }, + { [TRANSACTION_DURATION]: { order: 'desc' as const } }, + { [SPAN_DURATION]: { order: 'desc' as const } } ], track_total_hits: true } diff --git a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.ts index a647bd2faff36..bfa46abcad36f 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -12,6 +12,8 @@ import { PromiseReturnType } from '../../../typings/common'; import { Setup } from '../helpers/setup_request'; import { getTransactionGroupsProjection } from '../../../common/projections/transaction_groups'; import { mergeProjection } from '../../../common/projections/util/merge_projection'; +import { SortOptions } from '../../../typings/elasticsearch/aggregations'; +import { Transaction } from '../../../typings/es_schemas/ui/Transaction'; interface TopTransactionOptions { type: 'top_transactions'; @@ -36,6 +38,11 @@ export function transactionGroupsFetcher(options: Options, setup: Setup) { options }); + const sort: SortOptions = [ + { _score: 'desc' as const }, // sort by _score to ensure that buckets with sampled:true ends up on top + { '@timestamp': { order: 'desc' as const } } + ]; + const params = mergeProjection(projection, { body: { size: 0, @@ -48,17 +55,15 @@ export function transactionGroupsFetcher(options: Options, setup: Setup) { aggs: { transactions: { terms: { - order: { sum: 'desc' }, + ...projection.body.aggs.transactions.terms, + order: { sum: 'desc' as const }, size: config.get('xpack.apm.ui.transactionGroupBucketSize') }, aggs: { sample: { top_hits: { size: 1, - sort: [ - { _score: 'desc' }, // sort by _score to ensure that buckets with sampled:true ends up on top - { '@timestamp': { order: 'desc' } } - ] + sort } }, avg: { avg: { field: TRANSACTION_DURATION } }, @@ -72,5 +77,5 @@ export function transactionGroupsFetcher(options: Options, setup: Setup) { } }); - return client.search(params); + return client.search(params); } diff --git a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/transform.ts b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/transform.ts index b4e70d260f512..3ec64be08d117 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/transform.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/transform.ts @@ -6,7 +6,6 @@ import moment from 'moment'; import { idx } from '@kbn/elastic-idx'; -import { Transaction } from '../../../typings/es_schemas/ui/Transaction'; import { ESResponse } from './fetcher'; function calculateRelativeImpacts(transactionGroups: ITransactionGroup[]) { @@ -34,10 +33,10 @@ function getTransactionGroup( const averageResponseTime = bucket.avg.value; const transactionsPerMinute = bucket.doc_count / minutes; const impact = bucket.sum.value; - const sample = bucket.sample.hits.hits[0]._source as Transaction; + const sample = bucket.sample.hits.hits[0]._source; return { - name: bucket.key, + name: bucket.key as string, sample, p95: bucket.p95.values['95.0'], averageResponseTime, diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts index c440ee9c1ecbe..e2989498181ca 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts @@ -63,7 +63,7 @@ export async function getTransactionAvgDurationByCountry({ const buckets = resp.aggregations.country_code.buckets; const avgDurationsByCountry = buckets.map( ({ key, doc_count, avg_duration: { value } }) => ({ - key, + key: key as string, docCount: doc_count, value: value === null ? 0 : value }) diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts index b3c1c6603f315..ecf963fec3fe9 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts @@ -50,7 +50,7 @@ export async function getTransactionBreakdown({ field: SPAN_TYPE, size: 20, order: { - _count: 'desc' + _count: 'desc' as const } }, aggs: { @@ -60,7 +60,7 @@ export async function getTransactionBreakdown({ missing: '', size: 20, order: { - _count: 'desc' + _count: 'desc' as const } }, aggs: { @@ -117,11 +117,11 @@ export async function getTransactionBreakdown({ const breakdowns = flatten( aggs.types.buckets.map(bucket => { - const type = bucket.key; + const type = bucket.key as string; return bucket.subtypes.buckets.map(subBucket => { return { - name: subBucket.key || type, + name: (subBucket.key as string) || type, percentage: (subBucket.total_self_time_per_subtype.value || 0) / sumAllSelfTimes diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/get_ml_bucket_size.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/get_ml_bucket_size.ts index 293cede80cbfc..27cff20b7ff37 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/get_ml_bucket_size.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/get_ml_bucket_size.ts @@ -49,7 +49,7 @@ export async function getMlBucketSize({ }; try { - const resp = await client.search(params); + const resp = await client.search(params); return idx(resp, _ => _.hits.hits[0]._source.bucket_span) || 0; } catch (err) { const isHttpError = 'statusCode' in err; diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts index dc5cb925b7202..97368b7d92efc 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ESFilter } from 'elasticsearch'; +import { ESFilter } from '../../../../../typings/elasticsearch'; import { PROCESSOR_EVENT, SERVICE_NAME, diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.ts index f403c64a94aea..42828367f7941 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/transform.ts @@ -57,7 +57,8 @@ export function getTpmBuckets( }); // Handle empty string result keys - const key = resultKey === '' ? NOT_AVAILABLE_LABEL : resultKey; + const key = + resultKey === '' ? NOT_AVAILABLE_LABEL : (resultKey as string); return { key, dataPoints }; } @@ -65,7 +66,7 @@ export function getTpmBuckets( return sortBy( buckets, - bucket => bucket.key.replace(/^HTTP (\d)xx$/, '00$1') // ensure that HTTP 3xx are sorted at the top + bucket => bucket.key.toString().replace(/^HTTP (\d)xx$/, '00$1') // ensure that HTTP 3xx are sorted at the top ); } diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts index 458aad225fd94..42b35402aab9d 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction'; import { PROCESSOR_EVENT, SERVICE_NAME, @@ -17,7 +18,7 @@ import { import { rangeFilter } from '../../../helpers/range_filter'; import { Setup } from '../../../helpers/setup_request'; -export function bucketFetcher( +export async function bucketFetcher( serviceName: string, transactionName: string, transactionType: string, @@ -74,5 +75,7 @@ export function bucketFetcher( } }; - return client.search(params); + const response = await client.search(params); + + return response; } diff --git a/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts b/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts index 3b48bfc7a9869..80795ce468c88 100644 --- a/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts +++ b/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ESFilter } from 'elasticsearch'; import { idx } from '@kbn/elastic-idx'; import { PROCESSOR_EVENT, @@ -14,6 +13,7 @@ import { import { rangeFilter } from '../helpers/range_filter'; import { Setup } from '../helpers/setup_request'; import { ENVIRONMENT_NOT_DEFINED } from '../../../common/environment_filter_values'; +import { ESFilter } from '../../../typings/elasticsearch'; export async function getEnvironments(setup: Setup, serviceName?: string) { const { start, end, client, config } = setup; @@ -58,7 +58,7 @@ export async function getEnvironments(setup: Setup, serviceName?: string) { const environmentsBuckets = idx(aggs, _ => _.environments.buckets) || []; const environments = environmentsBuckets.map( - environmentBucket => environmentBucket.key + environmentBucket => environmentBucket.key as string ); return environments; diff --git a/x-pack/legacy/plugins/apm/server/lib/ui_filters/local_ui_filters/get_filter_aggregations.ts b/x-pack/legacy/plugins/apm/server/lib/ui_filters/local_ui_filters/get_filter_aggregations.ts index 9c9a5c45f697c..b7aaae2ff2652 100644 --- a/x-pack/legacy/plugins/apm/server/lib/ui_filters/local_ui_filters/get_filter_aggregations.ts +++ b/x-pack/legacy/plugins/apm/server/lib/ui_filters/local_ui_filters/get_filter_aggregations.ts @@ -53,7 +53,7 @@ export const getFilterAggregations = async ({ terms: { field: field.fieldName, order: { - _count: 'desc' + _count: 'desc' as const } }, ...bucketCountAggregation diff --git a/x-pack/legacy/plugins/apm/server/lib/ui_filters/local_ui_filters/index.ts b/x-pack/legacy/plugins/apm/server/lib/ui_filters/local_ui_filters/index.ts index 7632b03584167..e8c29c29434e6 100644 --- a/x-pack/legacy/plugins/apm/server/lib/ui_filters/local_ui_filters/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/ui_filters/local_ui_filters/index.ts @@ -68,7 +68,7 @@ export async function getLocalUIFilters({ options: sortByOrder( aggregationsForFilter.by_terms.buckets.map(bucket => { return { - name: bucket.key, + name: bucket.key as string, count: 'bucket_count' in bucket ? bucket.bucket_count.value diff --git a/x-pack/legacy/plugins/apm/server/routes/errors.ts b/x-pack/legacy/plugins/apm/server/routes/errors.ts index 73bb6e97b999b..a315dd10023dc 100644 --- a/x-pack/legacy/plugins/apm/server/routes/errors.ts +++ b/x-pack/legacy/plugins/apm/server/routes/errors.ts @@ -21,7 +21,7 @@ export const errorsRoute = createRoute(core => ({ query: t.intersection([ t.partial({ sortField: t.string, - sortDirection: t.string + sortDirection: t.union([t.literal('asc'), t.literal('desc')]) }), uiFiltersRt, rangeRt diff --git a/x-pack/legacy/plugins/apm/typings/elasticsearch.ts b/x-pack/legacy/plugins/apm/typings/elasticsearch.ts deleted file mode 100644 index 08d1e2b37492e..0000000000000 --- a/x-pack/legacy/plugins/apm/typings/elasticsearch.ts +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { StringMap, IndexAsString } from './common'; - -declare module 'elasticsearch' { - // extending SearchResponse to be able to have typed aggregations - - type ESSearchHit = SearchResponse['hits']['hits'][0]; - - type AggregationType = - | 'date_histogram' - | 'histogram' - | 'terms' - | 'avg' - | 'top_hits' - | 'max' - | 'min' - | 'percentiles' - | 'sum' - | 'extended_stats' - | 'filter' - | 'filters' - | 'cardinality' - | 'sampler' - | 'value_count' - | 'derivative' - | 'bucket_script'; - - type AggOptions = AggregationOptionMap & { - [key: string]: any; - }; - - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - export type AggregationOptionMap = { - aggs?: { - [aggregationName: string]: { - [T in AggregationType]?: AggOptions & AggregationOptionMap; - }; - }; - }; - - type SubAggregation = T extends { aggs: any } - ? AggregationResultMap - : {}; - - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - type BucketAggregation = { - buckets: Array< - { - key: KeyType; - key_as_string: string; - doc_count: number; - } & (SubAggregation) - >; - }; - - type FilterAggregation = { - doc_count: number; - } & SubAggregation; - - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - type FiltersAggregation = { - // The filters aggregation can have named filters or anonymous filters, - // which changes the structure of the return - // https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html - buckets: SubAggregationMap extends { - filters: { filters: Record }; - } - ? { - [key in keyof SubAggregationMap['filters']['filters']]: { - doc_count: number; - } & SubAggregation; - } - : Array< - { - doc_count: number; - } & SubAggregation - >; - }; - - type SamplerAggregation = SubAggregation< - SubAggregationMap - > & { - doc_count: number; - }; - - interface AggregatedValue { - value: number | null; - } - - interface HitsTotal { - value: number; - relation: 'eq' | 'gte'; - } - - type AggregationResultMap = IndexAsString< - { - [AggregationName in keyof AggregationOption]: { - avg: AggregatedValue; - max: AggregatedValue; - min: AggregatedValue; - sum: AggregatedValue; - value_count: AggregatedValue; - // Elasticsearch might return terms with numbers, but this is a more limited type - terms: BucketAggregation; - date_histogram: BucketAggregation< - AggregationOption[AggregationName], - number - >; - histogram: BucketAggregation< - AggregationOption[AggregationName], - number - >; - top_hits: { - hits: { - total: HitsTotal; - max_score: number | null; - hits: Array<{ - _source: AggregationOption[AggregationName] extends { - Mapping: any; - } - ? AggregationOption[AggregationName]['Mapping'] - : never; - }>; - }; - }; - percentiles: { - values: { - [key: string]: number; - }; - }; - extended_stats: { - count: number; - min: number | null; - max: number | null; - avg: number | null; - sum: number; - sum_of_squares: number | null; - variance: number | null; - std_deviation: number | null; - std_deviation_bounds: { - upper: number | null; - lower: number | null; - }; - }; - filter: FilterAggregation; - filters: FiltersAggregation; - cardinality: { - value: number; - }; - sampler: SamplerAggregation; - derivative: BucketAggregation< - AggregationOption[AggregationName], - number - >; - bucket_script: { - value: number | null; - }; - }[AggregationType & keyof AggregationOption[AggregationName]]; - } - >; - - export type AggregationSearchResponseWithTotalHitsAsInt< - HitType, - SearchParams - > = Pick< - SearchResponse, - Exclude, 'aggregations'> - > & - (SearchParams extends { body: Required } - ? { - aggregations?: AggregationResultMap; - } - : {}); - - type Hits = Pick< - SearchResponse['hits'], - Exclude['hits'], 'total'> - > & { - total: HitsTotal; - }; - - export type AggregationSearchResponseWithTotalHitsAsObject< - HitType, - SearchParams - > = Pick< - AggregationSearchResponseWithTotalHitsAsInt, - Exclude< - keyof AggregationSearchResponseWithTotalHitsAsInt, - 'hits' - > - > & { hits: Hits }; - - export interface ESFilter { - [key: string]: { - [key: string]: string | string[] | number | StringMap | ESFilter[]; - }; - } -} diff --git a/x-pack/legacy/plugins/apm/typings/elasticsearch/aggregations.ts b/x-pack/legacy/plugins/apm/typings/elasticsearch/aggregations.ts new file mode 100644 index 0000000000000..9f17b0197a5b2 --- /dev/null +++ b/x-pack/legacy/plugins/apm/typings/elasticsearch/aggregations.ts @@ -0,0 +1,256 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Unionize } from 'utility-types'; + +type SortOrder = 'asc' | 'desc'; +type SortInstruction = Record; +export type SortOptions = SortOrder | SortInstruction | SortInstruction[]; + +type Script = + | string + | { + lang?: string; + id?: string; + source?: string; + params?: Record; + }; + +type BucketsPath = string | Record; + +type SourceOptions = string | string[]; + +type MetricsAggregationOptions = + | { + field: string; + missing?: number; + } + | { + script?: Script; + }; + +interface MetricsAggregationResponsePart { + value: number | null; +} + +export interface AggregationOptionsByType { + terms: { + field: string; + size?: number; + missing?: string; + order?: SortOptions; + }; + date_histogram: { + field: string; + format?: string; + min_doc_count?: number; + extended_bounds?: { + min: number; + max: number; + }; + } & ({ calendar_interval: string } | { fixed_interval: string }); + histogram: { + field: string; + interval: number; + min_doc_count?: number; + extended_bounds?: { + min?: number | string; + max?: number | string; + }; + }; + avg: MetricsAggregationOptions; + max: MetricsAggregationOptions; + min: MetricsAggregationOptions; + sum: MetricsAggregationOptions; + value_count: MetricsAggregationOptions; + cardinality: MetricsAggregationOptions & { + precision_threshold?: number; + }; + percentiles: { + field: string; + percents?: number[]; + }; + extended_stats: { + field: string; + }; + top_hits: { + from?: number; + size?: number; + sort?: SortOptions; + _source?: SourceOptions; + }; + filter: Record; + filters: { + filters: Record | any[]; + }; + sampler: { + shard_size?: number; + }; + derivative: { + buckets_path: BucketsPath; + }; + bucket_script: { + buckets_path: BucketsPath; + script?: Script; + }; +} + +type AggregationType = keyof AggregationOptionsByType; + +type AggregationOptionsMap = Unionize< + { + [TAggregationType in AggregationType]: AggregationOptionsByType[TAggregationType]; + } +> & { aggs?: AggregationInputMap }; + +export interface AggregationInputMap { + [key: string]: AggregationOptionsMap; +} + +type BucketSubAggregationResponse< + TAggregationInputMap extends AggregationInputMap | undefined, + TDocument +> = TAggregationInputMap extends AggregationInputMap + ? AggregationResponseMap + : {}; + +interface AggregationResponsePart< + TAggregationOptionsMap extends AggregationOptionsMap, + TDocument +> { + terms: { + buckets: Array< + { + doc_count: number; + key: string | number; + } & BucketSubAggregationResponse< + TAggregationOptionsMap['aggs'], + TDocument + > + >; + }; + histogram: { + buckets: Array< + { + doc_count: number; + key: number; + } & BucketSubAggregationResponse< + TAggregationOptionsMap['aggs'], + TDocument + > + >; + }; + date_histogram: { + buckets: Array< + { + doc_count: number; + key: number; + key_as_string: string; + } & BucketSubAggregationResponse< + TAggregationOptionsMap['aggs'], + TDocument + > + >; + }; + avg: MetricsAggregationResponsePart; + sum: MetricsAggregationResponsePart; + max: MetricsAggregationResponsePart; + min: MetricsAggregationResponsePart; + value_count: MetricsAggregationResponsePart; + cardinality: { + value: number; + }; + percentiles: { + values: Record; + }; + extended_stats: { + count: number; + min: number | null; + max: number | null; + avg: number | null; + sum: number | null; + sum_of_squares: number | null; + variance: number | null; + std_deviation: number | null; + std_deviation_bounds: { + upper: number | null; + lower: number | null; + }; + }; + top_hits: { + hits: { + total: { + value: number; + relation: 'eq' | 'gte'; + }; + max_score: number | null; + hits: Array<{ + _source: TDocument; + }>; + }; + }; + filter: { + doc_count: number; + } & AggregationResponseMap; + filters: TAggregationOptionsMap extends { filters: { filters: any[] } } + ? Array< + { doc_count: number } & AggregationResponseMap< + TAggregationOptionsMap['aggs'], + TDocument + > + > + : (TAggregationOptionsMap extends { + filters: { + filters: Record; + }; + } + ? { + buckets: { + [key in keyof TAggregationOptionsMap['filters']['filters']]: { + doc_count: number; + } & AggregationResponseMap< + TAggregationOptionsMap['aggs'], + TDocument + >; + }; + } + : never); + sampler: { + doc_count: number; + } & AggregationResponseMap; + derivative: + | { + value: number; + } + | undefined; + bucket_script: + | { + value: number | null; + } + | undefined; +} + +// Type for debugging purposes. If you see an error in AggregationResponseMap +// similar to "cannot be used to index type", uncomment the type below and hover +// over it to see what aggregation response types are missing compared to the +// input map. + +// type MissingAggregationResponseTypes = Exclude< +// AggregationType, +// keyof AggregationResponsePart<{}> +// >; + +export type AggregationResponseMap< + TAggregationInputMap extends AggregationInputMap | undefined, + TDocument +> = TAggregationInputMap extends AggregationInputMap + ? { + [TName in keyof TAggregationInputMap]: AggregationResponsePart< + TAggregationInputMap[TName], + TDocument + >[AggregationType & keyof TAggregationInputMap[TName]]; + } + : undefined; diff --git a/x-pack/legacy/plugins/apm/typings/elasticsearch/index.ts b/x-pack/legacy/plugins/apm/typings/elasticsearch/index.ts new file mode 100644 index 0000000000000..657968fbd704f --- /dev/null +++ b/x-pack/legacy/plugins/apm/typings/elasticsearch/index.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Omit } from 'utility-types'; +import { SearchParams, SearchResponse } from 'elasticsearch'; +import { AggregationResponseMap, AggregationInputMap } from './aggregations'; +import { StringMap } from '../common'; + +export interface ESSearchBody { + query?: any; + size?: number; + aggs?: AggregationInputMap; + track_total_hits?: boolean | number; +} + +export type ESSearchRequest = Omit & { + body?: ESSearchBody; +}; + +export interface ESSearchOptions { + restTotalHitsAsInt: boolean; +} + +export type ESSearchHit = SearchResponse['hits']['hits'][0]; + +export type ESSearchResponse< + TDocument, + TSearchRequest extends ESSearchRequest, + TOptions extends ESSearchOptions = { restTotalHitsAsInt: false } +> = Omit, 'aggregations' | 'hits'> & + (TSearchRequest extends { body: { aggs: AggregationInputMap } } + ? { + aggregations?: AggregationResponseMap< + TSearchRequest['body']['aggs'], + TDocument + >; + } + : {}) & + ({ + hits: Omit['hits'], 'total'> & + (TOptions['restTotalHitsAsInt'] extends true + ? { + total: number; + } + : { + total: { + value: number; + relation: 'eq' | 'gte'; + }; + }); + }); + +export interface ESFilter { + [key: string]: { + [key: string]: string | string[] | number | StringMap | ESFilter[]; + }; +} diff --git a/x-pack/legacy/plugins/lens/server/routes/field_stats.ts b/x-pack/legacy/plugins/lens/server/routes/field_stats.ts index e7e378e6b20e4..ceefb492cdabe 100644 --- a/x-pack/legacy/plugins/lens/server/routes/field_stats.ts +++ b/x-pack/legacy/plugins/lens/server/routes/field_stats.ts @@ -7,8 +7,8 @@ import Boom from 'boom'; import DateMath from '@elastic/datemath'; import { schema } from '@kbn/config-schema'; -import { AggregationSearchResponseWithTotalHitsAsInt } from 'elasticsearch'; import { CoreSetup } from 'src/core/server'; +import { ESSearchResponse } from '../../../apm/typings/elasticsearch'; import { FieldStatsResponse, BASE_API_URL } from '../../common'; const SHARD_SIZE = 5000; @@ -135,9 +135,11 @@ export async function getNumberHistogram( }, }; - const minMaxResult = (await aggSearchWithBody( - searchBody - )) as AggregationSearchResponseWithTotalHitsAsInt; + const minMaxResult = (await aggSearchWithBody(searchBody)) as ESSearchResponse< + unknown, + { body: { aggs: typeof searchBody } }, + { restTotalHitsAsInt: true } + >; const minValue = minMaxResult.aggregations!.sample.min_value.value; const maxValue = minMaxResult.aggregations!.sample.max_value.value; @@ -178,11 +180,10 @@ export async function getNumberHistogram( }, }, }; - const histogramResult = (await aggSearchWithBody( - histogramBody - )) as AggregationSearchResponseWithTotalHitsAsInt< + const histogramResult = (await aggSearchWithBody(histogramBody)) as ESSearchResponse< unknown, - { body: { aggs: typeof histogramBody } } + { body: { aggs: typeof histogramBody } }, + { restTotalHitsAsInt: true } >; return { @@ -214,11 +215,10 @@ export async function getStringSamples( }, }, }; - const topValuesResult = (await aggSearchWithBody( - topValuesBody - )) as AggregationSearchResponseWithTotalHitsAsInt< + const topValuesResult = (await aggSearchWithBody(topValuesBody)) as ESSearchResponse< unknown, - { body: { aggs: typeof topValuesBody } } + { body: { aggs: typeof topValuesBody } }, + { restTotalHitsAsInt: true } >; return { @@ -263,11 +263,10 @@ export async function getDateHistogram( const histogramBody = { histo: { date_histogram: { field: field.name, fixed_interval: fixedInterval } }, }; - const results = (await aggSearchWithBody( - histogramBody - )) as AggregationSearchResponseWithTotalHitsAsInt< + const results = (await aggSearchWithBody(histogramBody)) as ESSearchResponse< unknown, - { body: { aggs: typeof histogramBody } } + { body: { aggs: typeof histogramBody } }, + { restTotalHitsAsInt: true } >; return { diff --git a/x-pack/legacy/plugins/lens/server/usage/task.ts b/x-pack/legacy/plugins/lens/server/usage/task.ts index ba74bcd240886..8fc6c8cbefe8a 100644 --- a/x-pack/legacy/plugins/lens/server/usage/task.ts +++ b/x-pack/legacy/plugins/lens/server/usage/task.ts @@ -8,17 +8,13 @@ import moment from 'moment'; import KbnServer, { Server } from 'src/legacy/server/kbn_server'; import { CoreSetup } from 'src/core/server'; import { CallClusterOptions } from 'src/legacy/core_plugins/elasticsearch'; -// This import has the side effect of allowing us to use the elasticsearch type -// extensions below. Without this import, the compiler is unable to find these -// in tests -import {} from '../../../apm/typings/elasticsearch'; import { SearchParams, DeleteDocumentByQueryParams, SearchResponse, DeleteDocumentByQueryResponse, - AggregationSearchResponseWithTotalHitsAsInt, } from 'elasticsearch'; +import { ESSearchResponse } from '../../../apm/typings/elasticsearch'; import { XPackMainPlugin } from '../../../xpack_main/xpack_main'; import { RunContext } from '../../../task_manager'; import { getVisualizationCounts } from './visualization_counts'; @@ -135,11 +131,12 @@ export async function getDailyEvents( }, }; - const metrics: AggregationSearchResponseWithTotalHitsAsInt< + const metrics: ESSearchResponse< unknown, { body: { aggs: typeof aggs }; - } + }, + { restTotalHitsAsInt: true } > = await callCluster('search', { index: kibanaIndex, rest_total_hits_as_int: true, From 1d1f5608e5fb7834079289fcf5b6fecd44bab614 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2019 10:41:31 +0200 Subject: [PATCH 106/191] Update dependency @elastic/charts to ^13.5.7 (#48865) --- package.json | 2 +- yarn.lock | 20 ++++---------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 7ad77c4b44aba..a0a98e0f75b04 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "dependencies": { "@babel/core": "^7.5.5", "@babel/register": "^7.5.5", - "@elastic/charts": "^13.5.4", + "@elastic/charts": "^13.5.7", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", "@elastic/eui": "14.5.0", diff --git a/yarn.lock b/yarn.lock index 26949392b2ba4..2513a0d34ed2a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1064,13 +1064,12 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@elastic/charts@^13.5.4": - version "13.5.4" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-13.5.4.tgz#b958639d485ed58d116ac66a16e4accef97919e0" - integrity sha512-F+aE4VgJ7xvl9RmWtJiHZwADQT9FwBSWgQS1IR1VQ5wLyOI9LUwrDGZXMtLR56M7wjPWbk0228n5xPgjsuBcdg== +"@elastic/charts@^13.5.7": + version "13.5.7" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-13.5.7.tgz#97ba458059613efd542ae68d7d2da059aac38484" + integrity sha512-8ibgrEJD3fpoLurB/DnNaWRmMGxAPHdtvCiPl1saPIjvlmGlrUNlXMneVgsPLqerNT0vuJDgqfQHHQcef/S2Hw== dependencies: "@types/d3-shape" "^1.3.1" - "@types/luxon" "^1.11.1" classnames "^2.2.6" d3-array "^1.2.4" d3-collection "^1.0.7" @@ -1078,7 +1077,6 @@ d3-shape "^1.3.4" fp-ts "^1.14.2" konva "^2.6.0" - luxon "^1.11.3" mobx "^4.9.2" mobx-react "^5.4.3" newtype-ts "^0.2.4" @@ -3634,11 +3632,6 @@ resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03" integrity sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w== -"@types/luxon@^1.11.1": - version "1.12.0" - resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-1.12.0.tgz#acf14294d18e6eba427a5e5d7dfce0f5cd2a9400" - integrity sha512-+UzPmwHSEEyv7aGlNkVpuFxp/BirXgl8NnPGCtmyx2KXIzAapoW3IqSVk87/Z3PUk8vEL8Pe1HXEMJbNBOQgtg== - "@types/mapbox-gl@^0.54.1": version "0.54.3" resolved "https://registry.yarnpkg.com/@types/mapbox-gl/-/mapbox-gl-0.54.3.tgz#6215fbf4dbb555d2ca6ce3be0b1de045eec0f967" @@ -18728,11 +18721,6 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" -luxon@^1.11.3: - version "1.13.1" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.13.1.tgz#b7fb7ba1e5c93ebda098af8d579314797e0a0d69" - integrity sha512-IQKRIiz9ldUrgcozN13SAeNZVYfD3bEI9X6TcrGu+dkgE4GR/Iik03ozbTM5cTr0lz8ucYPL2jtYT7Va2Flbsg== - lz-string@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" From 6bd88b266c9d1cf7555807902246f8ebbe640fb9 Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Thu, 24 Oct 2019 11:17:31 +0200 Subject: [PATCH 107/191] Add Saved object finder to migration guide (#49034) --- src/core/MIGRATION.md | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 36883440e0b5d..6a12b587085e1 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -174,10 +174,10 @@ In the new platform, there are three lifecycle functions today: `setup`, `start` The table below explains how each lifecycle event relates to the state of Kibana. | lifecycle event | server | browser | -|-----------------|-------------------------------------------|-----------------------------------------------------| +| --------------- | ----------------------------------------- | --------------------------------------------------- | | *setup* | bootstrapping and configuring routes | loading plugin bundles and configuring applications | | *start* | server is now serving traffic | browser is now showing UI to the user | -| *stop* | server has received a request to shutdown | user is navigating away from Kibana | +| *stop* | server has received a request to shutdown | user is navigating away from Kibana | There is no equivalent behavior to `start` or `stop` in legacy plugins, so this guide primarily focuses on migrating functionality into `setup`. @@ -1096,7 +1096,7 @@ import { npStart: { core } } from 'ui/new_platform'; ``` | Legacy Platform | New Platform | Notes | -|-------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------| +| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `chrome.addBasePath` | [`core.http.basePath.prepend`](/docs/development/core/public/kibana-plugin-public.httpservicebase.basepath.md) | | | `chrome.breadcrumbs.set` | [`core.chrome.setBreadcrumbs`](/docs/development/core/public/kibana-plugin-public.chromestart.setbreadcrumbs.md) | | | `chrome.getUiSettingsClient` | [`core.uiSettings`](/docs/development/core/public/kibana-plugin-public.uisettingsclient.md) | | @@ -1125,24 +1125,24 @@ import { setup, start } from '../core_plugins/embeddables/public/legacy'; import { setup, start } from '../core_plugins/visualizations/public/legacy'; ``` -| Legacy Platform | New Platform | Notes | -|--------------------------------------------------------|--------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------| -| `import 'ui/apply_filters'` | `import { ApplyFiltersPopover } from '../data/public'` | `import '../data/public/legacy` should be called to load legacy directives | -| `import 'ui/filter_bar'` | `import { FilterBar } from '../data/public'` | `import '../data/public/legacy` should be called to load legacy directives | -| `import 'ui/query_bar'` | `import { QueryBar, QueryBarInput } from '../data/public'` | Directives are deprecated. | -| `import 'ui/search_bar'` | `import { SearchBar } from '../data/public'` | Directive is deprecated. | -| `import 'ui/kbn_top_nav'` | `import { TopNavMenu } from '../kibana_react/public'` | Directive is still available in `ui/kbn_top_nav`. | -| `core_plugins/interpreter` | `data.expressions` | still in progress | -| `ui/courier` | `data.search` | still in progress | -| `ui/embeddable` | `embeddables` | still in progress | -| `ui/filter_manager` | `data.filter` | -- | -| `ui/index_patterns` | `data.indexPatterns` | still in progress | -| `ui/registry/vis_types` | `visualizations.types` | -- | -| `ui/vis` | `visualizations.types` | -- | -| `ui/vis/vis_factory` | `visualizations.types` | -- | -| `ui/vis/vis_filters` | `visualizations.filters` | -- | -| `ui/utils/parse_es_interval` | `import { parseEsInterval } from '../data/public'` | `parseEsInterval`, `ParsedInterval`, `InvalidEsCalendarIntervalError`, `InvalidEsIntervalFormatError` items were moved to the `Data Plugin` as a static code | - +| Legacy Platform | New Platform | Notes | +| ------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `import 'ui/apply_filters'` | `import { ApplyFiltersPopover } from '../data/public'` | `import '../data/public/legacy` should be called to load legacy directives | +| `import 'ui/filter_bar'` | `import { FilterBar } from '../data/public'` | `import '../data/public/legacy` should be called to load legacy directives | +| `import 'ui/query_bar'` | `import { QueryBar, QueryBarInput } from '../data/public'` | Directives are deprecated. | +| `import 'ui/search_bar'` | `import { SearchBar } from '../data/public'` | Directive is deprecated. | +| `import 'ui/kbn_top_nav'` | `import { TopNavMenu } from '../kibana_react/public'` | Directive is still available in `ui/kbn_top_nav`. | +| `ui/saved_objects/components/saved_object_finder` | `import { SavedObjectFinder } from '../kibana_react/public'` | | +| `core_plugins/interpreter` | `data.expressions` | still in progress | +| `ui/courier` | `data.search` | still in progress | +| `ui/embeddable` | `embeddables` | still in progress | +| `ui/filter_manager` | `data.filter` | -- | +| `ui/index_patterns` | `data.indexPatterns` | still in progress | +| `ui/registry/vis_types` | `visualizations.types` | -- | +| `ui/vis` | `visualizations.types` | -- | +| `ui/vis/vis_factory` | `visualizations.types` | -- | +| `ui/vis/vis_filters` | `visualizations.filters` | -- | +| `ui/utils/parse_es_interval` | `import { parseEsInterval } from '../data/public'` | `parseEsInterval`, `ParsedInterval`, `InvalidEsCalendarIntervalError`, `InvalidEsIntervalFormatError` items were moved to the `Data Plugin` as a static code | #### Server-side @@ -1150,9 +1150,9 @@ import { setup, start } from '../core_plugins/visualizations/public/legacy'; In server code, `core` can be accessed from either `server.newPlatform` or `kbnServer.newPlatform`. There are not currently very many services available on the server-side: | Legacy Platform | New Platform | Notes | -|----------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| +| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | | `server.config()` | [`initializerContext.config.create()`](/docs/development/core/server/kibana-plugin-server.plugininitializercontext.config.md) | Must also define schema. See _[how to configure plugin](#configure-plugin)_ | -| `server.route` | [`core.http.createRouter`](/docs/development/core/server/kibana-plugin-server.httpservicesetup.createrouter.md) | [Examples](./MIGRATION_EXAMPLES.md#route-registration) | +| `server.route` | [`core.http.createRouter`](/docs/development/core/server/kibana-plugin-server.httpservicesetup.createrouter.md) | [Examples](./MIGRATION_EXAMPLES.md#route-registration) | | `request.getBasePath()` | [`core.http.basePath.get`](/docs/development/core/server/kibana-plugin-server.httpservicesetup.basepath.md) | | | `server.plugins.elasticsearch.getCluster('data')` | [`core.elasticsearch.dataClient$`](/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.dataclient_.md) | Handlers will also include a pre-configured client | | `server.plugins.elasticsearch.getCluster('admin')` | [`core.elasticsearch.adminClient$`](/docs/development/core/server/kibana-plugin-server.elasticsearchservicesetup.adminclient_.md) | Handlers will also include a pre-configured client | @@ -1166,7 +1166,7 @@ The legacy platform uses a set of "uiExports" to inject modules from one plugin This table shows where these uiExports have moved to in the New Platform. In most cases, if a uiExport you need is not yet available in the New Platform, you may leave in your legacy plugin for the time being and continue to migrate the rest of your app to the New Platform. | Legacy Platform | New Platform | Notes | -|------------------------------|---------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------| +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `aliases` | | | | `app` | [`core.application.register`](/docs/development/core/public/kibana-plugin-public.applicationsetup.register.md) | | | `canvas` | | Should be an API on the canvas plugin. | From 1fcf45a3ad3abb0b9f9c896838ac819be3b4d3ad Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Thu, 24 Oct 2019 11:22:32 +0200 Subject: [PATCH 108/191] SavedObjectsRepository#create default to empty references array (#49026) --- .../service/lib/repository.test.js | 22 +++++++++++++++++++ .../saved_objects/service/lib/repository.ts | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 9e4edcd8d2943..e514210752f51 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -546,6 +546,28 @@ describe('SavedObjectsRepository', () => { ); expect(onBeforeWrite).toHaveBeenCalledTimes(1); }); + + it('defaults to empty references array if none are provided', async () => { + await savedObjectsRepository.create( + 'index-pattern', + { + title: 'Logstash', + }, + { + id: 'logstash-*', + } + ); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster).toHaveBeenCalledWith( + expect.any(String), + expect.objectContaining({ + body: expect.objectContaining({ + references: [], + }), + }) + ); + }); }); describe('#bulkCreate', () => { diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 898239e5736de..179aa6fffc7de 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -146,15 +146,15 @@ export class SavedObjectsRepository { * @property {boolean} [options.overwrite=false] * @property {object} [options.migrationVersion=undefined] * @property {string} [options.namespace] - * @property {array} [options.references] - [{ name, type, id }] + * @property {array} [options.references=[]] - [{ name, type, id }] * @returns {promise} - { id, type, version, attributes } */ public async create( type: string, attributes: T, - options: SavedObjectsCreateOptions = { overwrite: false, references: [] } + options: SavedObjectsCreateOptions = {} ): Promise> { - const { id, migrationVersion, overwrite, namespace, references } = options; + const { id, migrationVersion, overwrite = false, namespace, references = [] } = options; if (!this._allowedTypes.includes(type)) { throw SavedObjectsErrorHelpers.createUnsupportedTypeError(type); From ed9aaf1563b0063fdc89d58fc6e76619b95087e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Thu, 24 Oct 2019 11:34:27 +0200 Subject: [PATCH 109/191] [APM] Add timezone to chart tooltip (#49019) --- .../__test__/__snapshots__/List.test.tsx.snap | 32 ++++++++-- .../app/ErrorGroupOverview/List/index.tsx | 8 ++- .../shared/TimestampTooltip/index.test.tsx | 61 ++++++++++++++++--- .../shared/TimestampTooltip/index.tsx | 24 ++++++-- .../components/shared/charts/Tooltip/index.js | 6 +- 5 files changed, 112 insertions(+), 19 deletions(-) diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap index 2689ce8bd9424..7f562efcf64aa 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap @@ -714,7 +714,13 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
- 1337 minutes ago (mocking 1515578797) + + 1337 minutes ago (mocking 1515578797) +
@@ -833,7 +839,13 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
- 1337 minutes ago (mocking 1515578797) + + 1337 minutes ago (mocking 1515578797) +
@@ -952,7 +964,13 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
- 1337 minutes ago (mocking 1515578796) + + 1337 minutes ago (mocking 1515578796) +
@@ -1071,7 +1089,13 @@ exports[`ErrorGroupOverview -> List should render with data 1`] = `
- 1337 minutes ago (mocking 1515578773) + + 1337 minutes ago (mocking 1515578773) +
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx index 37fa6499ff176..2f06f1d52de6b 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx @@ -7,7 +7,6 @@ import { EuiBadge, EuiToolTip } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; -import moment from 'moment'; import React, { useMemo } from 'react'; import styled from 'styled-components'; import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n'; @@ -22,6 +21,7 @@ import { import { useUrlParams } from '../../../../hooks/useUrlParams'; import { ManagedTable } from '../../../shared/ManagedTable'; import { ErrorDetailLink } from '../../../shared/Links/apm/ErrorDetailLink'; +import { TimestampTooltip } from '../../../shared/TimestampTooltip'; const GroupIdLink = styled(ErrorDetailLink)` font-family: ${fontFamilyCode}; @@ -142,7 +142,11 @@ const ErrorGroupList: React.FC = props => { ), align: 'right', render: (value?: number) => - value ? moment(value).fromNow() : NOT_AVAILABLE_LABEL + value ? ( + + ) : ( + NOT_AVAILABLE_LABEL + ) } ], [serviceName] diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TimestampTooltip/index.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TimestampTooltip/index.test.tsx index c9f6afa0b3611..a7149c7604695 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TimestampTooltip/index.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TimestampTooltip/index.test.tsx @@ -7,17 +7,56 @@ import { shallow } from 'enzyme'; import React from 'react'; import moment from 'moment-timezone'; -import { TimestampTooltip } from './index'; +import { TimestampTooltip, asAbsoluteTime } from './index'; import { mockNow } from '../../../utils/testHelpers'; +describe('asAbsoluteTime', () => { + afterAll(() => moment.tz.setDefault('')); + + it('should add a leading plus for timezones with positive UTC offset', () => { + moment.tz.setDefault('Europe/Copenhagen'); + expect(asAbsoluteTime({ time: 1559390400000, precision: 'minutes' })).toBe( + 'Jun 1, 2019, 14:00 (UTC+2)' + ); + }); + + it('should add a leading minus for timezones with negative UTC offset', () => { + moment.tz.setDefault('America/Los_Angeles'); + expect(asAbsoluteTime({ time: 1559390400000, precision: 'minutes' })).toBe( + 'Jun 1, 2019, 05:00 (UTC-7)' + ); + }); + + it('should use default UTC offset formatting when offset contains minutes', () => { + moment.tz.setDefault('Canada/Newfoundland'); + expect(asAbsoluteTime({ time: 1559390400000, precision: 'minutes' })).toBe( + 'Jun 1, 2019, 09:30 (UTC-02:30)' + ); + }); + + it('should respect DST', () => { + moment.tz.setDefault('Europe/Copenhagen'); + const timeWithDST = 1559390400000; // Jun 1, 2019 + const timeWithoutDST = 1575201600000; // Dec 1, 2019 + + expect(asAbsoluteTime({ time: timeWithDST })).toBe( + 'Jun 1, 2019, 14:00:00.000 (UTC+2)' + ); + + expect(asAbsoluteTime({ time: timeWithoutDST })).toBe( + 'Dec 1, 2019, 13:00:00.000 (UTC+1)' + ); + }); +}); + describe('TimestampTooltip', () => { - const timestamp = 1570720000123; + const timestamp = 1570720000123; // Oct 10, 2019, 08:06:40.123 (UTC-7) beforeAll(() => { // mock Date.now mockNow(1570737000000); - moment.tz.setDefault('Etc/GMT'); + moment.tz.setDefault('America/Los_Angeles'); }); afterAll(() => moment.tz.setDefault('')); @@ -26,7 +65,7 @@ describe('TimestampTooltip', () => { expect(shallow()) .toMatchInlineSnapshot(` @@ -40,7 +79,15 @@ describe('TimestampTooltip', () => { shallow() .find('EuiToolTip') .prop('content') - ).toBe('Oct 10th 2019, 15:06:40.123 (+0000 GMT)'); + ).toBe('Oct 10, 2019, 08:06:40.123 (UTC-7)'); + }); + + it('should format with precision in seconds', () => { + expect( + shallow() + .find('EuiToolTip') + .prop('content') + ).toBe('Oct 10, 2019, 08:06:40 (UTC-7)'); }); it('should format with precision in minutes', () => { @@ -48,7 +95,7 @@ describe('TimestampTooltip', () => { shallow() .find('EuiToolTip') .prop('content') - ).toBe('Oct 10th 2019, 15:06 (+0000 GMT)'); + ).toBe('Oct 10, 2019, 08:06 (UTC-7)'); }); it('should format with precision in days', () => { @@ -56,6 +103,6 @@ describe('TimestampTooltip', () => { shallow() .find('EuiToolTip') .prop('content') - ).toBe('Oct 10th 2019 (+0000 GMT)'); + ).toBe('Oct 10, 2019 (UTC-7)'); }); }); diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TimestampTooltip/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TimestampTooltip/index.tsx index 1f7fcccdd56d0..d7ef6517c2fb8 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TimestampTooltip/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TimestampTooltip/index.tsx @@ -12,7 +12,7 @@ interface Props { * timestamp in milliseconds */ time: number; - precision?: 'days' | 'minutes' | 'milliseconds'; + precision?: 'days' | 'minutes' | 'seconds' | 'milliseconds'; } function getPreciseTime(precision: Props['precision']) { @@ -21,17 +21,33 @@ function getPreciseTime(precision: Props['precision']) { return ''; case 'minutes': return ', HH:mm'; + case 'seconds': + return ', HH:mm:ss'; default: return ', HH:mm:ss.SSS'; } } +function withLeadingPlus(value: number) { + return value > 0 ? `+${value}` : value; +} + +export function asAbsoluteTime({ time, precision = 'milliseconds' }: Props) { + const momentTime = moment(time); + const utcOffsetHours = momentTime.utcOffset() / 60; + const utcOffsetFormatted = Number.isInteger(utcOffsetHours) + ? withLeadingPlus(utcOffsetHours) + : 'Z'; + + return momentTime.format( + `MMM D, YYYY${getPreciseTime(precision)} (UTC${utcOffsetFormatted})` + ); +} + export function TimestampTooltip({ time, precision = 'milliseconds' }: Props) { const momentTime = moment(time); const relativeTimeLabel = momentTime.fromNow(); - const absoluteTimeLabel = momentTime.format( - `MMM Do YYYY${getPreciseTime(precision)} (ZZ zz)` - ); + const absoluteTimeLabel = asAbsoluteTime({ time, precision }); return ( diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/Tooltip/index.js b/x-pack/legacy/plugins/apm/public/components/shared/charts/Tooltip/index.js index 20096d81a94cb..f5992ac7fc63b 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/charts/Tooltip/index.js +++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/Tooltip/index.js @@ -7,7 +7,6 @@ import React from 'react'; import { isEmpty } from 'lodash'; import { Hint } from 'react-vis'; -import moment from 'moment'; import styled from 'styled-components'; import PropTypes from 'prop-types'; import { @@ -20,6 +19,7 @@ import { } from '../../../../style/variables'; import Legend from '../Legend'; import theme from '@elastic/eui/dist/eui_theme_light.json'; +import { asAbsoluteTime } from '../../TimestampTooltip'; const TooltipElm = styled.div` margin: 0 ${px(unit)}; @@ -87,7 +87,9 @@ export default function Tooltip({ return ( -
{header || moment(x).format('MMMM Do YYYY, HH:mm:ss')}
+
+ {header || asAbsoluteTime({ time: x, precision: 'seconds' })} +
{showLegends ? ( From a279a0bc327a9b77982783b3d163189351262cba Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Thu, 24 Oct 2019 11:47:28 +0200 Subject: [PATCH 110/191] [ML] fix token replacement regexp (#49086) --- .../ml/public/util/custom_url_utils.test.ts | 37 +++++++++++++++++++ .../ml/public/util/custom_url_utils.ts | 6 +-- .../plugins/ml/public/util/string_utils.js | 2 +- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/util/custom_url_utils.test.ts b/x-pack/legacy/plugins/ml/public/util/custom_url_utils.test.ts index 6eb33d92a85f7..d4556f085f4b2 100644 --- a/x-pack/legacy/plugins/ml/public/util/custom_url_utils.test.ts +++ b/x-pack/legacy/plugins/ml/public/util/custom_url_utils.test.ts @@ -269,6 +269,43 @@ describe('ML - custom URL utils', () => { ); // eslint-disable-line max-len }); + test('replaces tokens with nesting', () => { + const testUrlApache: KibanaUrlConfig = { + url_name: 'Raw data', + time_range: 'auto', + url_value: + 'kibana#/dashboard/ml_http_access_explorer_ecs?_g=(time:(from:\u0027$earliest$\u0027,mode:absolute,to:\u0027$latest$\u0027))&_a=(description:\u0027\u0027,filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:http.response.status_code,negate:!f,params:(query:\u0027$http.response.status_code$\u0027),type:phrase,value:\u0027$http.response.status_code$\u0027),query:(match:(http.response.status_code:(query:\u0027$http.response.status_code$\u0027,type:phrase))))),query:(language:kuery,query:\u0027\u0027))', // eslint-disable-line max-len + }; + + const testRecord = { + job_id: 'farequote', + result_type: 'record', + probability: 6.533287347648861e-45, + record_score: 93.84475, + initial_record_score: 94.867922946384, + bucket_span: 300, + detector_index: 0, + is_interim: false, + timestamp: 1486656600000, + function: 'mean', + function_description: 'mean', + typical: [99.2329899996025], + actual: [274.7279901504516], + field_name: 'responsetime', + earliest: '2017-02-09T15:10:00.000Z', + latest: '2017-02-09T17:15:00.000Z', + http: { + response: { + status_code: 403, + }, + }, + }; + + expect(getUrlForRecord(testUrlApache, testRecord)).toBe( + "kibana#/dashboard/ml_http_access_explorer_ecs?_g=(time:(from:'2017-02-09T15:10:00.000Z',mode:absolute,to:'2017-02-09T17:15:00.000Z'))&_a=(description:\u0027\u0027,filters:!((\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:event.dataset,negate:!f,params:(query:\u0027apache.access\u0027),type:phrase,value:\u0027apache.access\u0027),query:(match:(event.dataset:(query:\u0027apache.access\u0027,type:phrase)))),(\u0027$state\u0027:(store:appState),meta:(alias:!n,disabled:!f,index:\u0027INDEX_PATTERN_ID\u0027,key:http.response.status_code,negate:!f,params:(query:\u0027403\u0027),type:phrase,value:\u0027403\u0027),query:(match:(http.response.status_code:(query:\u0027403\u0027,type:phrase))))),query:(language:kuery,query:\u0027\u0027))" + ); // eslint-disable-line max-len + }); + test('returns expected URL for other type URL', () => { expect(getUrlForRecord(TEST_OTHER_URL, TEST_RECORD)).toBe( 'http://airlinecodes.info/airline-code-AAL' diff --git a/x-pack/legacy/plugins/ml/public/util/custom_url_utils.ts b/x-pack/legacy/plugins/ml/public/util/custom_url_utils.ts index 61c0f3a159f14..7fda7a88d318f 100644 --- a/x-pack/legacy/plugins/ml/public/util/custom_url_utils.ts +++ b/x-pack/legacy/plugins/ml/public/util/custom_url_utils.ts @@ -103,8 +103,8 @@ function isKibanaUrl(urlConfig: UrlConfig) { /** * Escape any double quotes in the value for correct use in KQL. */ -function escapeForKQL(value: string): string { - return value.replace(/\"/g, '\\"'); +function escapeForKQL(value: string | number): string { + return String(value).replace(/\"/g, '\\"'); } // Builds a Kibana dashboard or Discover URL from the supplied config, with any @@ -127,7 +127,7 @@ function buildKibanaUrl(urlConfig: UrlConfig, record: CustomUrlAnomalyRecordDoc) ); const replaceSingleTokenValues = (str: string) => - str.replace(/\$(\w+)\$/g, (match, name: string) => { + str.replace(/\$([^?&$\'"]+)\$/g, (match, name: string) => { // Use lodash get to allow nested JSON fields to be retrieved. let tokenValue: string | string[] | undefined = get(record, name); tokenValue = Array.isArray(tokenValue) ? tokenValue[0] : tokenValue; diff --git a/x-pack/legacy/plugins/ml/public/util/string_utils.js b/x-pack/legacy/plugins/ml/public/util/string_utils.js index 7d97f0b1d3167..cb1ccafc5e605 100644 --- a/x-pack/legacy/plugins/ml/public/util/string_utils.js +++ b/x-pack/legacy/plugins/ml/public/util/string_utils.js @@ -20,7 +20,7 @@ import d3 from 'd3'; // 'http://www.google.co.uk/#q=airline+code+AAL'. // If a corresponding key is not found in valuesByTokenName, then the String is not replaced. export function replaceStringTokens(str, valuesByTokenName, encodeForURI) { - return String(str).replace((/\$([^?&$\'"]{1,40})\$/g), (match, name) => { + return String(str).replace((/\$([^?&$\'"]+)\$/g), (match, name) => { // Use lodash get to allow nested JSON fields to be retrieved. let tokenValue = _.get(valuesByTokenName, name, null); if (encodeForURI === true && tokenValue !== null) { From 1d517fc04a545dd223329b7d75c9b1dcbeab1237 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 24 Oct 2019 11:58:48 +0100 Subject: [PATCH 111/191] [ML] Fixing wizard combo boxes (#49080) * [ML] Fixing wizard combo boxes * renaming function * updating tests to allow for empty select options * test refactor --- .../components/time_field/time_field_select.tsx | 9 ++++----- .../advanced_detector_modal.tsx | 10 +++++++--- .../components/agg_select/agg_select.tsx | 4 ++-- .../categorization_field_select.tsx | 9 ++++----- .../components/multi_metric_view/metric_selection.tsx | 4 ++-- .../components/population_view/metric_selection.tsx | 4 ++-- .../components/single_metric_view/metric_selection.tsx | 6 +++--- .../summary_count_field/summary_count_field_select.tsx | 9 ++++----- .../anomaly_detection/single_metric_job.ts | 2 +- .../services/machine_learning/job_wizard_common.ts | 7 +++---- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx index 25e462dfa2286..d81ceca567313 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx @@ -23,11 +23,10 @@ export const TimeFieldSelect: FC = ({ fields, changeHandler, selectedFiel f => f.id !== EVENT_RATE_FIELD_ID && f.type === ES_FIELD_TYPES.DATE ); - const selection: EuiComboBoxOptionProps[] = [ - { - label: selectedField !== null ? selectedField : '', - }, - ]; + const selection: EuiComboBoxOptionProps[] = []; + if (selectedField !== null) { + selection.push({ label: selectedField }); + } function onChange(selectedOptions: EuiComboBoxOptionProps[]) { const option = selectedOptions[0]; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx index fb1f71f0d298a..6ddfdb22feda8 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx @@ -104,12 +104,12 @@ export const AdvancedDetectorModal: FC = ({ const allFieldOptions: EuiComboBoxOptionProps[] = [ ...createFieldOptions(fields), ...createScriptFieldOptions(jobCreator.scriptFields), - ]; + ].sort(comboBoxOptionsSort); - const splitFieldOptions = [ + const splitFieldOptions: EuiComboBoxOptionProps[] = [ ...allFieldOptions, ...createMlcategoryFieldOption(jobCreator.categorizationFieldName), - ]; + ].sort(comboBoxOptionsSort); const eventRateField = fields.find(f => f.id === EVENT_RATE_FIELD_ID); @@ -398,3 +398,7 @@ function createSelectedOptions( ): EuiComboBoxOptionProps[] { return options.length === 1 && options[0].label !== option.label ? [] : [option]; } + +function comboBoxOptionsSort(a: EuiComboBoxOptionProps, b: EuiComboBoxOptionProps) { + return a.label.localeCompare(b.label); +} diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/agg_select/agg_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/agg_select/agg_select.tsx index d205691fcb64b..bda29b244a5b1 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/agg_select/agg_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/agg_select/agg_select.tsx @@ -82,6 +82,6 @@ export const AggSelect: FC = ({ fields, changeHandler, selectedOptions, r ); }; -export function createLabel(pair: AggFieldPair | null): string { - return pair === null ? '' : `${pair.agg.title}(${pair.field.name})`; +export function createLabel(pair: AggFieldPair): string { + return `${pair.agg.title}(${pair.field.name})`; } diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx index f9d99f7d0f4e0..9e3f5f7c34547 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx @@ -31,11 +31,10 @@ export const CategorizationFieldSelect: FC = ({ fields, changeHandler, se ...createScriptFieldOptions(jobCreator.scriptFields), ]; - const selection: EuiComboBoxOptionProps[] = [ - { - label: selectedField !== null ? selectedField : '', - }, - ]; + const selection: EuiComboBoxOptionProps[] = []; + if (selectedField !== null) { + selection.push({ label: selectedField }); + } function onChange(selectedOptions: EuiComboBoxOptionProps[]) { const option = selectedOptions[0]; diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/multi_metric_view/metric_selection.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/multi_metric_view/metric_selection.tsx index f913b5a5720d6..b0a5049924cbc 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/multi_metric_view/metric_selection.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/multi_metric_view/metric_selection.tsx @@ -33,7 +33,7 @@ export const MultiMetricDetectors: FC = ({ setIsValid }) => { const jobCreator = jc as MultiMetricJobCreator; const { fields } = newJobCapsService; - const [selectedOptions, setSelectedOptions] = useState([{ label: '' }]); + const [selectedOptions, setSelectedOptions] = useState([]); const [aggFieldPairList, setAggFieldPairList] = useState( jobCreator.aggFieldPairs ); @@ -57,7 +57,7 @@ export const MultiMetricDetectors: FC = ({ setIsValid }) => { if (typeof option !== 'undefined') { const newPair = { agg: option.agg, field: option.field }; setAggFieldPairList([...aggFieldPairList, newPair]); - setSelectedOptions([{ label: '' }]); + setSelectedOptions([]); } else { setAggFieldPairList([]); } diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/population_view/metric_selection.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/population_view/metric_selection.tsx index 87d3e87d65536..9a24381c9e35f 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/population_view/metric_selection.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/population_view/metric_selection.tsx @@ -36,7 +36,7 @@ export const PopulationDetectors: FC = ({ setIsValid }) => { const jobCreator = jc as PopulationJobCreator; const { fields } = newJobCapsService; - const [selectedOptions, setSelectedOptions] = useState([{ label: '' }]); + const [selectedOptions, setSelectedOptions] = useState([]); const [aggFieldPairList, setAggFieldPairList] = useState( jobCreator.aggFieldPairs ); @@ -62,7 +62,7 @@ export const PopulationDetectors: FC = ({ setIsValid }) => { if (typeof option !== 'undefined') { const newPair = { agg: option.agg, field: option.field, by: { field: null, value: null } }; setAggFieldPairList([...aggFieldPairList, newPair]); - setSelectedOptions([{ label: '' }]); + setSelectedOptions([]); } else { setAggFieldPairList([]); } diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/single_metric_view/metric_selection.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/single_metric_view/metric_selection.tsx index 45872faae4c09..19ccca44dc0a5 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/single_metric_view/metric_selection.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/single_metric_view/metric_selection.tsx @@ -32,9 +32,9 @@ export const SingleMetricDetectors: FC = ({ setIsValid }) => { const jobCreator = jc as SingleMetricJobCreator; const { fields } = newJobCapsService; - const [selectedOptions, setSelectedOptions] = useState([ - { label: createLabel(jobCreator.aggFieldPair) }, - ]); + const [selectedOptions, setSelectedOptions] = useState( + jobCreator.aggFieldPair !== null ? [{ label: createLabel(jobCreator.aggFieldPair) }] : [] + ); const [aggFieldPair, setAggFieldPair] = useState(jobCreator.aggFieldPair); const [lineChartsData, setLineChartData] = useState({}); const [loadingData, setLoadingData] = useState(false); diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/summary_count_field/summary_count_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/summary_count_field/summary_count_field_select.tsx index 6bf510a70bfcb..2f240344e0ea5 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/summary_count_field/summary_count_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/summary_count_field/summary_count_field_select.tsx @@ -27,11 +27,10 @@ export const SummaryCountFieldSelect: FC = ({ fields, changeHandler, sele ...createScriptFieldOptions(jobCreator.scriptFields), ]; - const selection: EuiComboBoxOptionProps[] = [ - { - label: selectedField !== null ? selectedField : '', - }, - ]; + const selection: EuiComboBoxOptionProps[] = []; + if (selectedField !== null) { + selection.push({ label: selectedField }); + } function onChange(selectedOptions: EuiComboBoxOptionProps[]) { const option = selectedOptions[0]; diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts index b5b3d2371bf1a..7da395d42ffdc 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts @@ -232,7 +232,7 @@ export default function({ getService }: FtrProviderContext) { it('pre-fills field and aggregation', async () => { await ml.jobWizardCommon.assertAggAndFieldInputExists(); - await ml.jobWizardCommon.assertAggAndFieldSelection(aggAndFieldIdentifier); + await ml.jobWizardCommon.assertAggAndFieldSelection([aggAndFieldIdentifier]); await ml.jobWizardCommon.assertAnomalyChartExists('LINE'); }); diff --git a/x-pack/test/functional/services/machine_learning/job_wizard_common.ts b/x-pack/test/functional/services/machine_learning/job_wizard_common.ts index 08f1fb92d3487..73764e8f36518 100644 --- a/x-pack/test/functional/services/machine_learning/job_wizard_common.ts +++ b/x-pack/test/functional/services/machine_learning/job_wizard_common.ts @@ -70,17 +70,16 @@ export function MachineLearningJobWizardCommonProvider({ getService }: FtrProvid await testSubjects.existOrFail('mlJobWizardAggSelection > comboBoxInput'); }, - async assertAggAndFieldSelection(expectedIdentifier: string) { + async assertAggAndFieldSelection(expectedIdentifier: string[]) { const comboBoxSelectedOptions = await comboBox.getComboBoxSelectedOptions( 'mlJobWizardAggSelection > comboBoxInput' ); - expect(comboBoxSelectedOptions.length).to.eql(1); - expect(comboBoxSelectedOptions[0]).to.eql(expectedIdentifier); + expect(comboBoxSelectedOptions).to.eql(expectedIdentifier); }, async selectAggAndField(identifier: string, isIdentifierKeptInField: boolean) { await comboBox.set('mlJobWizardAggSelection > comboBoxInput', identifier); - await this.assertAggAndFieldSelection(isIdentifierKeptInField ? identifier : ''); + await this.assertAggAndFieldSelection(isIdentifierKeptInField ? [identifier] : []); }, async assertBucketSpanInputExists() { From 68c2a7681458b34762ba7e9f4427d4b251a643b2 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 24 Oct 2019 12:06:17 +0100 Subject: [PATCH 112/191] [ML] Adding missing text fields to advanced wizard (#49057) * [ML] Adding missing text fields to advanced wizard * removing comment out code --- .../categorization_field_select.tsx | 4 +- .../cloudwatch_job_caps_response.json | 905 ++++++++++++++++++ .../farequote_job_caps_response.json | 528 ---------- .../new_job_capabilities._service.test.ts | 44 +- .../services/new_job_capabilities_service.ts | 37 +- .../job_service/new_job_caps/field_service.ts | 9 +- .../new_job_caps/new_job_caps.test.ts | 2 + 7 files changed, 972 insertions(+), 557 deletions(-) create mode 100644 x-pack/legacy/plugins/ml/public/services/__mocks__/cloudwatch_job_caps_response.json delete mode 100644 x-pack/legacy/plugins/ml/public/services/__mocks__/farequote_job_caps_response.json diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx index 9e3f5f7c34547..9d9972a0b533a 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx @@ -26,7 +26,9 @@ export const CategorizationFieldSelect: FC = ({ fields, changeHandler, se const options: EuiComboBoxOptionProps[] = [ ...createFieldOptions( fields, - f => f.id !== EVENT_RATE_FIELD_ID && f.type === ES_FIELD_TYPES.KEYWORD + f => + f.id !== EVENT_RATE_FIELD_ID && + (f.type === ES_FIELD_TYPES.KEYWORD || f.type === ES_FIELD_TYPES.TEXT) ), ...createScriptFieldOptions(jobCreator.scriptFields), ]; diff --git a/x-pack/legacy/plugins/ml/public/services/__mocks__/cloudwatch_job_caps_response.json b/x-pack/legacy/plugins/ml/public/services/__mocks__/cloudwatch_job_caps_response.json new file mode 100644 index 0000000000000..783b2d4e081bc --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/services/__mocks__/cloudwatch_job_caps_response.json @@ -0,0 +1,905 @@ +{ + "cloudwatch-*": { + "aggs": [ + { + "id": "count", + "title": "Count", + "kibanaName": "count", + "dslName": "count", + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "high_count", + "title": "High count", + "kibanaName": "count", + "dslName": "count", + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "low_count", + "title": "Low count", + "kibanaName": "count", + "dslName": "count", + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "mean", + "title": "Mean", + "kibanaName": "avg", + "dslName": "avg", + "type": "metrics", + "mlModelPlotAgg": { + "max": "avg", + "min": "avg" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "high_mean", + "title": "High mean", + "kibanaName": "avg", + "dslName": "avg", + "type": "metrics", + "mlModelPlotAgg": { + "max": "avg", + "min": "avg" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "low_mean", + "title": "Low mean", + "kibanaName": "avg", + "dslName": "avg", + "type": "metrics", + "mlModelPlotAgg": { + "max": "avg", + "min": "avg" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "sum", + "title": "Sum", + "kibanaName": "sum", + "dslName": "sum", + "type": "metrics", + "mlModelPlotAgg": { + "max": "sum", + "min": "sum" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "high_sum", + "title": "High sum", + "kibanaName": "sum", + "dslName": "sum", + "type": "metrics", + "mlModelPlotAgg": { + "max": "sum", + "min": "sum" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "low_sum", + "title": "Low sum", + "kibanaName": "sum", + "dslName": "sum", + "type": "metrics", + "mlModelPlotAgg": { + "max": "sum", + "min": "sum" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "median", + "title": "Median", + "kibanaName": "median", + "dslName": "percentiles", + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "high_median", + "title": "High median", + "kibanaName": "median", + "dslName": "percentiles", + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "low_median", + "title": "Low median", + "kibanaName": "median", + "dslName": "percentiles", + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "min", + "title": "Min", + "kibanaName": "min", + "dslName": "min", + "type": "metrics", + "mlModelPlotAgg": { + "max": "min", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "max", + "title": "Max", + "kibanaName": "max", + "dslName": "max", + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "max" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "distinct_count", + "title": "Distinct count", + "kibanaName": "cardinality", + "dslName": "cardinality", + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "instance", + "region", + "sourcetype.keyword", + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "non_zero_count", + "title": "Non zero count", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "high_non_zero_count", + "title": "High non zero count", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "low_non_zero_count", + "title": "Low non zero count", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "high_distinct_count", + "title": "High distinct count", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "instance", + "region", + "sourcetype.keyword", + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "low_distinct_count", + "title": "Low distinct count", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "instance", + "region", + "sourcetype.keyword", + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "metric", + "title": "Metric", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "varp", + "title": "varp", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "high_varp", + "title": "High varp", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "low_varp", + "title": "Low varp", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "non_null_sum", + "title": "Non null sum", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "high_non_null_sum", + "title": "High non null sum", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "low_non_null_sum", + "title": "Low non null sum", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "rare", + "title": "Rare", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "freq_rare", + "title": "Freq rare", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "info_content", + "title": "Info content", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "high_info_content", + "title": "High info content", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "low_info_content", + "title": "Low info content", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + }, + { + "id": "time_of_day", + "title": "Time of day", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "time_of_week", + "title": "Time of week", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + } + }, + { + "id": "lat_long", + "title": "Lat long", + "kibanaName": null, + "dslName": null, + "type": "metrics", + "mlModelPlotAgg": { + "max": "max", + "min": "min" + }, + "fieldIds": [ + "CPUUtilization", + "DiskReadBytes", + "DiskReadOps", + "DiskWriteBytes", + "DiskWriteOps", + "NetworkIn", + "NetworkOut" + ] + } + ], + "fields": [ + { + "id": "@timestamp", + "name": "@timestamp", + "type": "date", + "aggregatable": true, + "aggIds": [] + }, + { + "id": "CPUUtilization", + "name": "CPUUtilization", + "type": "double", + "aggregatable": true, + "aggIds": [ + "mean", + "high_mean", + "low_mean", + "sum", + "high_sum", + "low_sum", + "median", + "high_median", + "low_median", + "min", + "max", + "distinct_count", + "high_distinct_count", + "low_distinct_count", + "metric", + "varp", + "high_varp", + "low_varp", + "non_null_sum", + "high_non_null_sum", + "low_non_null_sum", + "info_content", + "high_info_content", + "low_info_content", + "lat_long" + ] + }, + { + "id": "DiskReadBytes", + "name": "DiskReadBytes", + "type": "double", + "aggregatable": true, + "aggIds": [ + "mean", + "high_mean", + "low_mean", + "sum", + "high_sum", + "low_sum", + "median", + "high_median", + "low_median", + "min", + "max", + "distinct_count", + "high_distinct_count", + "low_distinct_count", + "metric", + "varp", + "high_varp", + "low_varp", + "non_null_sum", + "high_non_null_sum", + "low_non_null_sum", + "info_content", + "high_info_content", + "low_info_content", + "lat_long" + ] + }, + { + "id": "DiskReadOps", + "name": "DiskReadOps", + "type": "double", + "aggregatable": true, + "aggIds": [ + "mean", + "high_mean", + "low_mean", + "sum", + "high_sum", + "low_sum", + "median", + "high_median", + "low_median", + "min", + "max", + "distinct_count", + "high_distinct_count", + "low_distinct_count", + "metric", + "varp", + "high_varp", + "low_varp", + "non_null_sum", + "high_non_null_sum", + "low_non_null_sum", + "info_content", + "high_info_content", + "low_info_content", + "lat_long" + ] + }, + { + "id": "DiskWriteBytes", + "name": "DiskWriteBytes", + "type": "double", + "aggregatable": true, + "aggIds": [ + "mean", + "high_mean", + "low_mean", + "sum", + "high_sum", + "low_sum", + "median", + "high_median", + "low_median", + "min", + "max", + "distinct_count", + "high_distinct_count", + "low_distinct_count", + "metric", + "varp", + "high_varp", + "low_varp", + "non_null_sum", + "high_non_null_sum", + "low_non_null_sum", + "info_content", + "high_info_content", + "low_info_content", + "lat_long" + ] + }, + { + "id": "DiskWriteOps", + "name": "DiskWriteOps", + "type": "double", + "aggregatable": true, + "aggIds": [ + "mean", + "high_mean", + "low_mean", + "sum", + "high_sum", + "low_sum", + "median", + "high_median", + "low_median", + "min", + "max", + "distinct_count", + "high_distinct_count", + "low_distinct_count", + "metric", + "varp", + "high_varp", + "low_varp", + "non_null_sum", + "high_non_null_sum", + "low_non_null_sum", + "info_content", + "high_info_content", + "low_info_content", + "lat_long" + ] + }, + { + "id": "instance", + "name": "instance", + "type": "keyword", + "aggregatable": true, + "aggIds": [ + "distinct_count", + "high_distinct_count", + "low_distinct_count" + ] + }, + { + "id": "NetworkIn", + "name": "NetworkIn", + "type": "double", + "aggregatable": true, + "aggIds": [ + "mean", + "high_mean", + "low_mean", + "sum", + "high_sum", + "low_sum", + "median", + "high_median", + "low_median", + "min", + "max", + "distinct_count", + "high_distinct_count", + "low_distinct_count", + "metric", + "varp", + "high_varp", + "low_varp", + "non_null_sum", + "high_non_null_sum", + "low_non_null_sum", + "info_content", + "high_info_content", + "low_info_content", + "lat_long" + ] + }, + { + "id": "NetworkOut", + "name": "NetworkOut", + "type": "double", + "aggregatable": true, + "aggIds": [ + "mean", + "high_mean", + "low_mean", + "sum", + "high_sum", + "low_sum", + "median", + "high_median", + "low_median", + "min", + "max", + "distinct_count", + "high_distinct_count", + "low_distinct_count", + "metric", + "varp", + "high_varp", + "low_varp", + "non_null_sum", + "high_non_null_sum", + "low_non_null_sum", + "info_content", + "high_info_content", + "low_info_content", + "lat_long" + ] + }, + { + "id": "region", + "name": "region", + "type": "keyword", + "aggregatable": true, + "aggIds": [ + "distinct_count", + "high_distinct_count", + "low_distinct_count" + ] + }, + { + "id": "sourcetype", + "name": "sourcetype", + "type": "text", + "aggregatable": false, + "aggIds": [] + }, + { + "id": "sourcetype.keyword", + "name": "sourcetype.keyword", + "type": "keyword", + "aggregatable": true, + "aggIds": [ + "distinct_count", + "high_distinct_count", + "low_distinct_count" + ] + } + ] + } +} diff --git a/x-pack/legacy/plugins/ml/public/services/__mocks__/farequote_job_caps_response.json b/x-pack/legacy/plugins/ml/public/services/__mocks__/farequote_job_caps_response.json deleted file mode 100644 index cff91d90e8ffc..0000000000000 --- a/x-pack/legacy/plugins/ml/public/services/__mocks__/farequote_job_caps_response.json +++ /dev/null @@ -1,528 +0,0 @@ -{ - "farequote-*": { - "aggs": [ - { - "id": "count", - "title": "Count", - "kibanaName": "count", - "dslName": "count", - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "high_count", - "title": "High count", - "kibanaName": "count", - "dslName": "count", - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "low_count", - "title": "Low count", - "kibanaName": "count", - "dslName": "count", - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "mean", - "title": "Mean", - "kibanaName": "avg", - "dslName": "avg", - "type": "metrics", - "mlModelPlotAgg": { - "max": "avg", - "min": "avg" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "high_mean", - "title": "High mean", - "kibanaName": "avg", - "dslName": "avg", - "type": "metrics", - "mlModelPlotAgg": { - "max": "avg", - "min": "avg" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "low_mean", - "title": "Low mean", - "kibanaName": "avg", - "dslName": "avg", - "type": "metrics", - "mlModelPlotAgg": { - "max": "avg", - "min": "avg" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "sum", - "title": "Sum", - "kibanaName": "sum", - "dslName": "sum", - "type": "metrics", - "mlModelPlotAgg": { - "max": "sum", - "min": "sum" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "high_sum", - "title": "High sum", - "kibanaName": "sum", - "dslName": "sum", - "type": "metrics", - "mlModelPlotAgg": { - "max": "sum", - "min": "sum" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "low_sum", - "title": "Low sum", - "kibanaName": "sum", - "dslName": "sum", - "type": "metrics", - "mlModelPlotAgg": { - "max": "sum", - "min": "sum" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "median", - "title": "Median", - "kibanaName": "median", - "dslName": "percentiles", - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "high_median", - "title": "High median", - "kibanaName": "median", - "dslName": "percentiles", - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "low_median", - "title": "Low median", - "kibanaName": "median", - "dslName": "percentiles", - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "min", - "title": "Min", - "kibanaName": "min", - "dslName": "min", - "type": "metrics", - "mlModelPlotAgg": { - "max": "min", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "max", - "title": "Max", - "kibanaName": "max", - "dslName": "max", - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "max" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "distinct_count", - "title": "Distinct count", - "kibanaName": "cardinality", - "dslName": "cardinality", - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "airline", - "responsetime" - ] - }, - { - "id": "non_zero_count", - "title": "Non zero count", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "high_non_zero_count", - "title": "High non zero count", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "low_non_zero_count", - "title": "Low non zero count", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "high_distinct_count", - "title": "High distinct count", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "low_distinct_count", - "title": "Low distinct count", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "metric", - "title": "Metric", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "varp", - "title": "varp", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "high_varp", - "title": "High varp", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "low_varp", - "title": "Low varp", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "non_null_sum", - "title": "Non null sum", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "high_non_null_sum", - "title": "High non null sum", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "low_non_null_sum", - "title": "Low non null sum", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "rare", - "title": "Rare", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "freq_rare", - "title": "Freq rare", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "info_content", - "title": "Info content", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "high_info_content", - "title": "High info content", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "low_info_content", - "title": "Low info content", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - }, - { - "id": "time_of_day", - "title": "Time of day", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "time_of_week", - "title": "Time of week", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [] - }, - { - "id": "lat_long", - "title": "Lat long", - "kibanaName": null, - "dslName": null, - "type": "metrics", - "mlModelPlotAgg": { - "max": "max", - "min": "min" - }, - "fieldIds": [ - "responsetime" - ] - } - ], - "fields": [ - { - "id": "@timestamp", - "name": "@timestamp", - "type": "date", - "aggregatable": true, - "aggIds": [] - }, - { - "id": "airline", - "name": "airline", - "type": "keyword", - "aggregatable": true, - "aggIds": [ - "distinct_count" - ] - }, - { - "id": "responsetime", - "name": "responsetime", - "type": "float", - "aggregatable": true, - "aggIds": [ - "mean", - "high_mean", - "low_mean", - "sum", - "high_sum", - "low_sum", - "median", - "high_median", - "low_median", - "min", - "max", - "distinct_count", - "high_distinct_count", - "low_distinct_count", - "metric", - "varp", - "high_varp", - "low_varp", - "non_null_sum", - "high_non_null_sum", - "low_non_null_sum", - "info_content", - "high_info_content", - "low_info_content", - "lat_long" - ] - } - ] - } -} diff --git a/x-pack/legacy/plugins/ml/public/services/new_job_capabilities._service.test.ts b/x-pack/legacy/plugins/ml/public/services/new_job_capabilities._service.test.ts index fc8bb2407f75a..91c945ea8ff29 100644 --- a/x-pack/legacy/plugins/ml/public/services/new_job_capabilities._service.test.ts +++ b/x-pack/legacy/plugins/ml/public/services/new_job_capabilities._service.test.ts @@ -9,40 +9,60 @@ import { IndexPattern } from 'ui/index_patterns'; // there is magic happening here. starting the include name with `mock..` // ensures it can be lazily loaded by the jest.mock function below. -import mockFarequoteResponse from './__mocks__/farequote_job_caps_response.json'; +import mockCloudwatchResponse from './__mocks__/cloudwatch_job_caps_response.json'; jest.mock('./ml_api_service', () => ({ ml: { jobs: { - newJobCaps: jest.fn(() => Promise.resolve(mockFarequoteResponse)), + newJobCaps: jest.fn(() => Promise.resolve(mockCloudwatchResponse)), }, }, })); const indexPattern = ({ - id: 'farequote-*', - title: 'farequote-*', + id: 'cloudwatch-*', + title: 'cloudwatch-*', } as unknown) as IndexPattern; describe('new_job_capabilities_service', () => { - describe('farequote newJobCaps()', () => { + describe('cloudwatch newJobCaps()', () => { it('can construct job caps objects from endpoint json', async done => { await newJobCapsService.initializeFromIndexPattern(indexPattern); const { fields, aggs } = await newJobCapsService.newJobCaps; - const responseTimeField = fields.find(f => f.id === 'responsetime') || { aggs: [] }; - const airlineField = fields.find(f => f.id === 'airline') || { aggs: [] }; + const networkOutField = fields.find(f => f.id === 'NetworkOut') || { aggs: [] }; + const regionField = fields.find(f => f.id === 'region') || { aggs: [] }; const meanAgg = aggs.find(a => a.id === 'mean') || { fields: [] }; const distinctCountAgg = aggs.find(a => a.id === 'distinct_count') || { fields: [] }; - expect(fields).toHaveLength(4); + expect(fields).toHaveLength(12); expect(aggs).toHaveLength(35); - expect(responseTimeField.aggs).toHaveLength(25); - expect(airlineField.aggs).toHaveLength(1); + expect(networkOutField.aggs).toHaveLength(25); + expect(regionField.aggs).toHaveLength(3); + + expect(meanAgg.fields).toHaveLength(7); + expect(distinctCountAgg.fields).toHaveLength(10); + done(); + }); + + it('job caps including text fields', async done => { + await newJobCapsService.initializeFromIndexPattern(indexPattern, true, false); + const { fields, aggs } = await newJobCapsService.newJobCaps; + + expect(fields).toHaveLength(13); // one more field + expect(aggs).toHaveLength(35); + + done(); + }); + + it('job caps excluding event rate', async done => { + await newJobCapsService.initializeFromIndexPattern(indexPattern, false, true); + const { fields, aggs } = await newJobCapsService.newJobCaps; + + expect(fields).toHaveLength(11); // one less field + expect(aggs).toHaveLength(35); - expect(meanAgg.fields).toHaveLength(1); - expect(distinctCountAgg.fields).toHaveLength(2); done(); }); }); diff --git a/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts b/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts index 890683793339a..f404d23618cef 100644 --- a/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts +++ b/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts @@ -50,15 +50,10 @@ export function loadNewJobCapabilities( const categoryFieldTypes = [ES_FIELD_TYPES.TEXT, ES_FIELD_TYPES.KEYWORD, ES_FIELD_TYPES.IP]; class NewJobCapsService { - private _fields: Field[]; - private _aggs: Aggregation[]; - private _includeEventRateField: boolean; - - constructor(includeEventRateField = true) { - this._fields = []; - this._aggs = []; - this._includeEventRateField = includeEventRateField; - } + private _fields: Field[] = []; + private _aggs: Aggregation[] = []; + private _includeEventRateField: boolean = true; + private _removeTextFields: boolean = true; public get fields(): Field[] { return this._fields; @@ -79,8 +74,15 @@ class NewJobCapsService { return this._fields.filter(f => categoryFieldTypes.includes(f.type)); } - public async initializeFromIndexPattern(indexPattern: IndexPattern) { + public async initializeFromIndexPattern( + indexPattern: IndexPattern, + includeEventRateField = true, + removeTextFields = true + ) { try { + this._includeEventRateField = includeEventRateField; + this._removeTextFields = removeTextFields; + const resp = await ml.jobs.newJobCaps(indexPattern.title, indexPattern.type === 'rollup'); const { fields, aggs } = createObjects(resp, indexPattern.title); @@ -88,7 +90,10 @@ class NewJobCapsService { addEventRateField(aggs, fields); } - this._fields = fields; + // remove any text fields which have a keyword equivalents + const processedFields = this._removeTextFields ? processTextFields(fields) : fields; + + this._fields = processedFields; this._aggs = aggs; } catch (error) { console.error('Unable to load new job capabilities', error); // eslint-disable-line no-console @@ -199,4 +204,14 @@ function addEventRateField(aggs: Aggregation[], fields: Field[]) { fields.splice(0, 0, eventRateField); } +// remove fields which are text and have a keyword equivalent +function processTextFields(fields: Field[]) { + const keywordIds = fields.filter(f => f.type === ES_FIELD_TYPES.KEYWORD).map(f => f.id); + return fields.filter( + f => + f.type !== ES_FIELD_TYPES.TEXT || + (f.type === ES_FIELD_TYPES.TEXT && keywordIds.includes(`${f.id}.keyword`) === false) + ); +} + export const newJobCapsService = new NewJobCapsService(); diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts index df4a2c059f1ef..d7c26bda77d20 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/field_service.ts @@ -136,7 +136,8 @@ async function combineFieldsAndAggs( const numericalFields = getNumericalFields(fields); const ipFields = getIpFields(fields); - const mix = mixFactory(rollupFields); + const isRollup = Object.keys(rollupFields).length > 0; + const mix = mixFactory(isRollup, rollupFields); aggs.forEach(a => { if (a.type === METRIC_AGG_TYPE && a.fields !== undefined) { @@ -165,7 +166,7 @@ async function combineFieldsAndAggs( return { aggs, - fields: filterFields(fields), + fields: isRollup ? filterFields(fields) : fields, }; } @@ -178,9 +179,7 @@ function filterFields(fields: Field[]): Field[] { // returns a mix function that is used to cross-reference aggs and fields. // wrapped in a provider to allow filtering based on rollup job capabilities -function mixFactory(rollupFields: RollupFields) { - const isRollup = Object.keys(rollupFields).length > 0; - +function mixFactory(isRollup: boolean, rollupFields: RollupFields) { return function mix(field: Field, agg: Aggregation): void { if ( isRollup === false || diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts index 87653a1e3f47d..2c8f8a8f82fb8 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job_caps/new_job_caps.test.ts @@ -66,7 +66,9 @@ describe('job_service - job_caps', () => { expect(response).toEqual(farequoteJobCapsEmpty); done(); }); + }); + describe('cloudwatch newJobCaps()', () => { it('can get rollup job caps for rollup index pattern', async done => { const indexPattern = 'cloud_roll_index'; const isRollup = true; From b75f5e29581df5fe7be48ffeec105be095be783d Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 24 Oct 2019 15:01:25 +0300 Subject: [PATCH 113/191] Convert agg_types/__tests__ to JEST (Metrics folder) (#49056) --- .../agg_types/__tests__/metrics/median.js | 73 ---- .../__tests__/metrics/parent_pipeline.js | 220 ---------- .../__tests__/metrics/percentile_ranks.js | 57 --- .../__tests__/metrics/percentiles.js | 55 --- .../__tests__/metrics/sibling_pipeline.js | 166 -------- .../__tests__/metrics/std_deviation.js | 74 ---- .../agg_types/__tests__/metrics/top_hit.js | 376 ------------------ .../get_response_agg_config_class.ts | 36 +- .../lib/make_nested_label.test.ts} | 41 +- .../public/agg_types/metrics/median.test.ts | 69 ++++ .../agg_types/metrics/parent_pipeline.test.ts | 248 ++++++++++++ .../metrics/percentile_ranks.test.ts | 75 ++++ .../agg_types/metrics/percentile_ranks.ts | 4 +- .../agg_types/metrics/percentiles.test.ts | 73 ++++ .../public/agg_types/metrics/percentiles.ts | 4 +- .../metrics/percentiles_get_value.ts | 2 +- .../metrics/sibling_pipeline.test.ts | 188 +++++++++ .../agg_types/metrics/std_deviation.test.ts | 83 ++++ .../public/agg_types/metrics/std_deviation.ts | 4 +- .../public/agg_types/metrics/top_hit.test.ts | 366 +++++++++++++++++ .../editors/default/components/agg_params.tsx | 5 +- .../editors/default/controls/sub_metric.tsx | 2 +- 22 files changed, 1150 insertions(+), 1071 deletions(-) delete mode 100644 src/legacy/ui/public/agg_types/__tests__/metrics/median.js delete mode 100644 src/legacy/ui/public/agg_types/__tests__/metrics/parent_pipeline.js delete mode 100644 src/legacy/ui/public/agg_types/__tests__/metrics/percentile_ranks.js delete mode 100644 src/legacy/ui/public/agg_types/__tests__/metrics/percentiles.js delete mode 100644 src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js delete mode 100644 src/legacy/ui/public/agg_types/__tests__/metrics/std_deviation.js delete mode 100644 src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js rename src/legacy/ui/public/agg_types/metrics/{ => lib}/get_response_agg_config_class.ts (75%) rename src/legacy/ui/public/agg_types/{__tests__/metrics/lib/make_nested_label.js => metrics/lib/make_nested_label.test.ts} (62%) create mode 100644 src/legacy/ui/public/agg_types/metrics/median.test.ts create mode 100644 src/legacy/ui/public/agg_types/metrics/parent_pipeline.test.ts create mode 100644 src/legacy/ui/public/agg_types/metrics/percentile_ranks.test.ts create mode 100644 src/legacy/ui/public/agg_types/metrics/percentiles.test.ts create mode 100644 src/legacy/ui/public/agg_types/metrics/sibling_pipeline.test.ts create mode 100644 src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts create mode 100644 src/legacy/ui/public/agg_types/metrics/top_hit.test.ts diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/median.js b/src/legacy/ui/public/agg_types/__tests__/metrics/median.js deleted file mode 100644 index df65afa5e4222..0000000000000 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/median.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { VisProvider } from '../../../vis'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -describe('AggTypeMetricMedianProvider class', function () { - let indexPattern; - let aggDsl; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - const Vis = Private(VisProvider); - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - - const vis = new Vis(indexPattern, { - 'title': 'New Visualization', - 'type': 'metric', - 'params': { - 'fontSize': 60 - }, - 'aggs': [ - { - 'id': '1', - 'type': 'median', - 'schema': 'metric', - 'params': { - 'field': 'bytes', - 'percents': [ - 50 - ] - } - } - ], - 'listeners': {} - }); - - // Grab the aggConfig off the vis (we don't actually use the vis for - // anything else) - const aggConfig = vis.aggs.aggs[0]; - aggDsl = aggConfig.toDsl(); - })); - - it('requests the percentiles aggregation in the Elasticsearch query DSL', function () { - expect(Object.keys(aggDsl)[0]).to.be('percentiles'); - }); - - it ('asks Elasticsearch for the 50th percentile', function () { - expect(aggDsl.percentiles.percents).to.eql([50]); - }); - - it ('asks Elasticsearch for array-based values in the aggregation response', function () { - expect(aggDsl.percentiles.keyed).to.be(false); - }); -}); diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/parent_pipeline.js b/src/legacy/ui/public/agg_types/__tests__/metrics/parent_pipeline.js deleted file mode 100644 index e4ca6075c624b..0000000000000 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/parent_pipeline.js +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import ngMock from 'ng_mock'; -import { derivativeMetricAgg } from '../../metrics/derivative'; -import { cumulativeSumMetricAgg } from '../../metrics/cumulative_sum'; -import { movingAvgMetricAgg } from '../../metrics/moving_avg'; -import { serialDiffMetricAgg } from '../../metrics/serial_diff'; -import { VisProvider } from '../../../vis'; -import StubbedIndexPattern from 'fixtures/stubbed_logstash_index_pattern'; - -const metrics = [ - { name: 'derivative', title: 'Derivative', agg: derivativeMetricAgg }, - { name: 'cumulative_sum', title: 'Cumulative Sum', agg: cumulativeSumMetricAgg }, - { name: 'moving_avg', title: 'Moving Avg', agg: movingAvgMetricAgg, dslName: 'moving_fn' }, - { name: 'serial_diff', title: 'Serial Diff', agg: serialDiffMetricAgg }, -]; - -describe('parent pipeline aggs', function () { - metrics.forEach(metric => { - describe(`${metric.title} metric`, function () { - - let aggDsl; - let metricAgg; - let aggConfig; - - function init(settings) { - ngMock.module('kibana'); - ngMock.inject(function (Private) { - const Vis = Private(VisProvider); - const indexPattern = Private(StubbedIndexPattern); - indexPattern.stubSetFieldFormat('bytes', 'bytes'); - metricAgg = metric.agg; - - const params = settings || { - metricAgg: '1', - customMetric: null - }; - - const vis = new Vis(indexPattern, { - title: 'New Visualization', - type: 'metric', - params: { - fontSize: 60 - }, - aggs: [ - { - id: '1', - type: 'count', - schema: 'metric' - }, - { - id: '2', - type: metric.name, - schema: 'metric', - params - }, - { - id: '3', - type: 'max', - params: { field: '@timestamp' }, - schema: 'metric' - } - ], - listeners: {} - }); - - // Grab the aggConfig off the vis (we don't actually use the vis for anything else) - aggConfig = vis.aggs.aggs[1]; - aggDsl = aggConfig.toDsl(vis.aggs); - }); - } - - it(`should return a label prefixed with ${metric.title} of`, function () { - init(); - expect(metricAgg.makeLabel(aggConfig)).to.eql(`${metric.title} of Count`); - }); - - it(`should return a label ${metric.title} of max bytes`, function () { - init({ - metricAgg: 'custom', - customMetric: { - id: '1-orderAgg', - type: 'max', - params: { field: 'bytes' }, - schema: 'orderAgg' - } - }); - expect(metricAgg.makeLabel(aggConfig)).to.eql(`${metric.title} of Max bytes`); - }); - - it(`should return a label prefixed with number of ${metric.title.toLowerCase()}`, function () { - init({ - metricAgg: 'custom', - customMetric: { - id: '2-orderAgg', - type: metric.name, - params: { - buckets_path: 'custom', - customMetric: { - id: '2-orderAgg-orderAgg', - type: 'count', - schema: 'orderAgg' - } - }, - schema: 'orderAgg' - } - }); - expect(metricAgg.makeLabel(aggConfig)).to.eql(`2. ${metric.title.toLowerCase()} of Count`); - }); - - it('should set parent aggs', function () { - init({ - metricAgg: 'custom', - customMetric: { - id: '2-metric', - type: 'max', - params: { field: 'bytes' }, - schema: 'orderAgg' - } - }); - expect(aggDsl[metric.dslName || metric.name].buckets_path).to.be('2-metric'); - expect(aggDsl.parentAggs['2-metric'].max.field).to.be('bytes'); - }); - - it('should set nested parent aggs', function () { - init({ - metricAgg: 'custom', - customMetric: { - id: '2-metric', - type: metric.name, - params: { - buckets_path: 'custom', - customMetric: { - id: '2-metric-metric', - type: 'max', - params: { field: 'bytes' }, - schema: 'orderAgg' - } - }, - schema: 'orderAgg' - } - }); - expect(aggDsl[metric.dslName || metric.name].buckets_path).to.be('2-metric'); - expect(aggDsl.parentAggs['2-metric'][metric.dslName || metric.name].buckets_path).to.be('2-metric-metric'); - }); - - it('should have correct formatter', function () { - init({ - metricAgg: '3' - }); - expect(metricAgg.getFormat(aggConfig).type.id).to.be('date'); - }); - - it('should have correct customMetric nested formatter', function () { - init({ - metricAgg: 'custom', - customMetric: { - id: '2-metric', - type: metric.name, - params: { - buckets_path: 'custom', - customMetric: { - id: '2-metric-metric', - type: 'max', - params: { field: 'bytes' }, - schema: 'orderAgg' - } - }, - schema: 'orderAgg' - } - }); - expect(metricAgg.getFormat(aggConfig).type.id).to.be('bytes'); - }); - - it('should call modifyAggConfigOnSearchRequestStart for its customMetric\'s parameters', () => { - init({ - metricAgg: 'custom', - customMetric: { - id: '2-metric', - type: 'max', - params: { field: 'bytes' }, - schema: 'orderAgg' - } - }); - - const searchSource = {}; - const customMetricSpy = sinon.spy(); - const customMetric = aggConfig.params.customMetric; - - // Attach a modifyAggConfigOnSearchRequestStart with a spy to the first parameter - customMetric.type.params[0].modifyAggConfigOnSearchRequestStart = customMetricSpy; - - aggConfig.type.params.forEach(param => { - param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource); - }); - expect(customMetricSpy.calledWith(customMetric, searchSource)).to.be(true); - }); - }); - }); - -}); diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/percentile_ranks.js b/src/legacy/ui/public/agg_types/__tests__/metrics/percentile_ranks.js deleted file mode 100644 index 1f767f8886262..0000000000000 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/percentile_ranks.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { percentileRanksMetricAgg } from '../../metrics/percentile_ranks'; -import { VisProvider } from '../../../vis'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -describe('AggTypesMetricsPercentileRanksProvider class', function () { - - let Vis; - let indexPattern; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - Vis = Private(VisProvider); - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - })); - - it('uses the custom label if it is set', function () { - const vis = new Vis(indexPattern, {}); - - // Grab the aggConfig off the vis (we don't actually use the vis for - // anything else) - const aggConfig = vis.aggs.aggs[0]; - aggConfig.params.customLabel = 'my custom field label'; - aggConfig.params.values = [ 5000, 10000 ]; - aggConfig.params.field = { - displayName: 'bytes' - }; - - const responseAggs = percentileRanksMetricAgg.getResponseAggs(aggConfig); - const percentileRankLabelFor5kBytes = responseAggs[0].makeLabel(); - const percentileRankLabelFor10kBytes = responseAggs[1].makeLabel(); - - expect(percentileRankLabelFor5kBytes).to.be('Percentile rank 5,000 of "my custom field label"'); - expect(percentileRankLabelFor10kBytes).to.be('Percentile rank 10,000 of "my custom field label"'); - }); - -}); diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/percentiles.js b/src/legacy/ui/public/agg_types/__tests__/metrics/percentiles.js deleted file mode 100644 index afbf8b95d6e73..0000000000000 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/percentiles.js +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { percentilesMetricAgg } from '../../metrics/percentiles'; -import { VisProvider } from '../../../vis'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -describe('AggTypesMetricsPercentilesProvider class', function () { - - let Vis; - let indexPattern; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - Vis = Private(VisProvider); - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - })); - - it('uses the custom label if it is set', function () { - const vis = new Vis(indexPattern, {}); - - // Grab the aggConfig off the vis (we don't actually use the vis for - // anything else) - const aggConfig = vis.aggs.aggs[0]; - aggConfig.params.customLabel = 'prince'; - aggConfig.params.percents = [ 95 ]; - aggConfig.params.field = { - displayName: 'bytes' - }; - - const responseAggs = percentilesMetricAgg.getResponseAggs(aggConfig); - const ninetyFifthPercentileLabel = responseAggs[0].makeLabel(); - - expect(ninetyFifthPercentileLabel).to.be('95th percentile of prince'); - }); - -}); diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js b/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js deleted file mode 100644 index aba5db9cedadf..0000000000000 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import sinon from 'sinon'; -import ngMock from 'ng_mock'; -import { bucketSumMetricAgg } from '../../metrics/bucket_sum'; -import { bucketAvgMetricAgg } from '../../metrics/bucket_avg'; -import { bucketMinMetricAgg } from '../../metrics/bucket_min'; -import { bucketMaxMetricAgg } from '../../metrics/bucket_max'; -import { VisProvider } from '../../../vis'; -import StubbedIndexPattern from 'fixtures/stubbed_logstash_index_pattern'; - -const metrics = [ - { name: 'sum_bucket', title: 'Overall Sum', provider: bucketSumMetricAgg }, - { name: 'avg_bucket', title: 'Overall Average', provider: bucketAvgMetricAgg }, - { name: 'min_bucket', title: 'Overall Min', provider: bucketMinMetricAgg }, - { name: 'max_bucket', title: 'Overall Max', provider: bucketMaxMetricAgg }, -]; - -describe('sibling pipeline aggs', function () { - metrics.forEach(metric => { - describe(`${metric.title} metric`, function () { - - let aggDsl; - let metricAgg; - let aggConfig; - - function init(settings) { - ngMock.module('kibana'); - ngMock.inject(function (Private) { - const Vis = Private(VisProvider); - const indexPattern = Private(StubbedIndexPattern); - indexPattern.stubSetFieldFormat('bytes', 'bytes'); - metricAgg = metric.provider; - - const params = settings || { - customMetric: { - id: '5', - type: 'count', - schema: 'metric' - }, - customBucket: { - id: '6', - type: 'date_histogram', - schema: 'bucket', - params: { field: '@timestamp', interval: '10s' } - } - }; - - const vis = new Vis(indexPattern, { - title: 'New Visualization', - type: 'metric', - params: { - fontSize: 60 - }, - aggs: [ - { - id: '1', - type: 'count', - schema: 'metric' - }, - { - id: '2', - type: metric.name, - schema: 'metric', - params - } - ], - listeners: {} - }); - - // Grab the aggConfig off the vis (we don't actually use the vis for anything else) - aggConfig = vis.aggs.aggs[1]; - aggDsl = aggConfig.toDsl(vis.aggs); - }); - } - - it(`should return a label prefixed with ${metric.title} of`, function () { - init(); - expect(metricAgg.makeLabel(aggConfig)).to.eql(`${metric.title} of Count`); - }); - - it('should set parent aggs', function () { - init(); - expect(aggDsl[metric.name].buckets_path).to.be('2-bucket>_count'); - expect(aggDsl.parentAggs['2-bucket'].date_histogram).to.not.be.undefined; - }); - - it('should set nested parent aggs', function () { - init({ - customMetric: { - id: '5', - type: 'avg', - schema: 'metric', - params: { field: 'bytes' }, - }, - customBucket: { - id: '6', - type: 'date_histogram', - schema: 'bucket', - params: { field: '@timestamp', interval: '10s', }, - } - }); - expect(aggDsl[metric.name].buckets_path).to.be('2-bucket>2-metric'); - expect(aggDsl.parentAggs['2-bucket'].date_histogram).to.not.be.undefined; - expect(aggDsl.parentAggs['2-bucket'].aggs['2-metric'].avg.field).to.equal('bytes'); - }); - - it('should have correct formatter', function () { - init({ - customMetric: { - id: '5', - type: 'avg', - schema: 'metric', - params: { field: 'bytes' }, - }, - customBucket: { - id: '6', - type: 'date_histogram', - schema: 'bucket', - params: { field: '@timestamp', interval: '10s' }, - } - }); - expect(metricAgg.getFormat(aggConfig).type.id).to.be('bytes'); - }); - - it('should call modifyAggConfigOnSearchRequestStart for nested aggs\' parameters', () => { - init(); - - const searchSource = {}; - const customMetricSpy = sinon.spy(); - const customBucketSpy = sinon.spy(); - const { customMetric, customBucket } = aggConfig.params; - - // Attach a modifyAggConfigOnSearchRequestStart with a spy to the first parameter - customMetric.type.params[0].modifyAggConfigOnSearchRequestStart = customMetricSpy; - customBucket.type.params[0].modifyAggConfigOnSearchRequestStart = customBucketSpy; - - aggConfig.type.params.forEach(param => { - param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource); - }); - expect(customMetricSpy.calledWith(customMetric, searchSource)).to.be(true); - expect(customBucketSpy.calledWith(customBucket, searchSource)).to.be(true); - }); - - }); - }); - -}); diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/std_deviation.js b/src/legacy/ui/public/agg_types/__tests__/metrics/std_deviation.js deleted file mode 100644 index b31794f6d9ffe..0000000000000 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/std_deviation.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { stdDeviationMetricAgg } from '../../metrics/std_deviation'; -import { VisProvider } from '../../../vis'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -describe('AggTypeMetricStandardDeviationProvider class', function () { - - let Vis; - let indexPattern; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - Vis = Private(VisProvider); - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - })); - - it('uses the custom label if it is set', function () { - const vis = new Vis(indexPattern, {}); - - // Grab the aggConfig off the vis (we don't actually use the vis for - // anything else) - const aggConfig = vis.aggs.aggs[0]; - aggConfig.params.customLabel = 'custom label'; - aggConfig.params.field = { - displayName: 'memory' - }; - - const responseAggs = stdDeviationMetricAgg.getResponseAggs(aggConfig); - const lowerStdDevLabel = responseAggs[0].makeLabel(); - const upperStdDevLabel = responseAggs[1].makeLabel(); - - expect(lowerStdDevLabel).to.be('Lower custom label'); - expect(upperStdDevLabel).to.be('Upper custom label'); - }); - - it('uses the default labels if custom label is not set', function () { - const vis = new Vis(indexPattern, {}); - - // Grab the aggConfig off the vis (we don't actually use the vis for - // anything else) - const aggConfig = vis.aggs.aggs[0]; - aggConfig.params.field = { - displayName: 'memory' - }; - - const responseAggs = stdDeviationMetricAgg.getResponseAggs(aggConfig); - const lowerStdDevLabel = responseAggs[0].makeLabel(); - const upperStdDevLabel = responseAggs[1].makeLabel(); - - expect(lowerStdDevLabel).to.be('Lower Standard Deviation of memory'); - expect(upperStdDevLabel).to.be('Upper Standard Deviation of memory'); - }); - -}); diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js b/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js deleted file mode 100644 index 927d73793f469..0000000000000 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/top_hit.js +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { topHitMetricAgg } from '../../metrics/top_hit'; -import { VisProvider } from '../../../vis'; -import StubbedIndexPattern from 'fixtures/stubbed_logstash_index_pattern'; - -describe('Top hit metric', function () { - let aggDsl; - let aggConfig; - - function init({ field, sortOrder = 'desc', aggregate = 'concat', size = 1 }) { - ngMock.module('kibana'); - ngMock.inject(function (Private) { - const Vis = Private(VisProvider); - const indexPattern = Private(StubbedIndexPattern); - - const params = {}; - if (field) { - params.field = field; - } - params.sortOrder = { - value: sortOrder - }; - params.aggregate = { - value: aggregate - }; - params.size = size; - const vis = new Vis(indexPattern, { - title: 'New Visualization', - type: 'metric', - params: { - fontSize: 60 - }, - aggs: [ - { - id: '1', - type: 'top_hits', - schema: 'metric', - params - } - ], - listeners: {} - }); - - // Grab the aggConfig off the vis (we don't actually use the vis for anything else) - aggConfig = vis.aggs.aggs[0]; - aggDsl = aggConfig.toDsl(); - }); - } - - it('should return a label prefixed with Last if sorting in descending order', function () { - init({ field: 'bytes' }); - expect(topHitMetricAgg.makeLabel(aggConfig)).to.eql('Last bytes'); - }); - - it('should return a label prefixed with First if sorting in ascending order', function () { - init({ - field: 'bytes', - sortOrder: 'asc' - }); - expect(topHitMetricAgg.makeLabel(aggConfig)).to.eql('First bytes'); - }); - - it('should request the _source field', function () { - init({ field: '_source' }); - expect(aggDsl.top_hits._source).to.be(true); - expect(aggDsl.top_hits.docvalue_fields).to.be(undefined); - }); - - it('requests both source and docvalues_fields for non-text aggregatable fields', function () { - init({ field: 'bytes' }); - expect(aggDsl.top_hits._source).to.be('bytes'); - expect(aggDsl.top_hits.docvalue_fields).to.eql([ { field: 'bytes', format: 'use_field_mapping' } ]); - }); - - it('requests both source and docvalues_fields for date aggregatable fields', function () { - init({ field: '@timestamp' }); - expect(aggDsl.top_hits._source).to.be('@timestamp'); - expect(aggDsl.top_hits.docvalue_fields).to.eql([ { field: '@timestamp', format: 'date_time' } ]); - }); - - it('requests just source for aggregatable text fields', function () { - init({ field: 'machine.os' }); - expect(aggDsl.top_hits._source).to.be('machine.os'); - expect(aggDsl.top_hits.docvalue_fields).to.be(undefined); - }); - - it('requests just source for not-aggregatable text fields', function () { - init({ field: 'non-sortable' }); - expect(aggDsl.top_hits._source).to.be('non-sortable'); - expect(aggDsl.top_hits.docvalue_fields).to.be(undefined); - }); - - it('requests just source for not-aggregatable, non-text fields', function () { - init({ field: 'hashed' }); - expect(aggDsl.top_hits._source).to.be('hashed'); - expect(aggDsl.top_hits.docvalue_fields).to.be(undefined); - }); - - describe('try to get the value from the top hit', function () { - it('should return null if there is no hit', function () { - const bucket = { - '1': { - hits: { - hits: [] - } - } - }; - - init({ field: '@tags' }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be(null); - }); - - it('should return undefined if the field does not appear in the source', function () { - const bucket = { - '1': { - hits: { - hits: [ - { - _source: { - bytes: 123 - } - } - ] - } - } - }; - - init({ field: '@tags' }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be(undefined); - }); - - it('should return the field value from the top hit', function () { - const bucket = { - '1': { - hits: { - hits: [ - { - _source: { - '@tags': 'aaa' - } - } - ] - } - } - }; - - init({ field: '@tags' }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be('aaa'); - }); - - it('should return the object if the field value is an object', function () { - const bucket = { - '1': { - hits: { - hits: [ - { - _source: { - '@tags': { - label: 'aaa' - } - } - } - ] - } - } - }; - - init({ field: '@tags' }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.eql({ label: 'aaa' }); - }); - - it('should return an array if the field has more than one values', function () { - const bucket = { - '1': { - hits: { - hits: [ - { - _source: { - '@tags': [ 'aaa', 'bbb' ] - } - } - ] - } - } - }; - - init({ field: '@tags' }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.eql([ 'aaa', 'bbb' ]); - }); - - it('should get the value from the doc_values field if the source does not have that field', function () { - const bucket = { - '1': { - hits: { - hits: [ - { - _source: { - 'machine.os': 'linux' - }, - fields: { - 'machine.os.raw': [ 'linux' ] - } - } - ] - } - } - }; - - init({ field: 'machine.os.raw' }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be('linux'); - }); - - it('should return undefined if the field is not in the source nor in the doc_values field', function () { - const bucket = { - '1': { - hits: { - hits: [ - { - _source: { - bytes: 12345 - }, - fields: { - bytes: 12345 - } - } - ] - } - } - }; - - init({ field: 'machine.os.raw' }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.be(undefined); - }); - - describe('Multivalued field and first/last X docs', function () { - it('should return a label prefixed with Last X docs if sorting in descending order', function () { - init({ - field: 'bytes', - size: 2 - }); - expect(topHitMetricAgg.makeLabel(aggConfig)).to.eql('Last 2 bytes'); - }); - - it('should return a label prefixed with First X docs if sorting in ascending order', function () { - init({ - field: 'bytes', - size: 2, - sortOrder: 'asc' - }); - expect(topHitMetricAgg.makeLabel(aggConfig)).to.eql('First 2 bytes'); - }); - - [ - { - description: 'concat values with a comma', - type: 'concat', - data: [ 1, 2, 3 ], - result: [ 1, 2, 3 ] - }, - { - description: 'sum up the values', - type: 'sum', - data: [ 1, 2, 3 ], - result: 6 - }, - { - description: 'take the minimum value', - type: 'min', - data: [ 1, 2, 3 ], - result: 1 - }, - { - description: 'take the maximum value', - type: 'max', - data: [ 1, 2, 3 ], - result: 3 - }, - { - description: 'take the average value', - type: 'average', - data: [ 1, 2, 3 ], - result: 2 - }, - { - description: 'support null/undefined', - type: 'min', - data: [ undefined, null ], - result: null - }, - { - description: 'support null/undefined', - type: 'max', - data: [ undefined, null ], - result: null - }, - { - description: 'support null/undefined', - type: 'sum', - data: [ undefined, null ], - result: null - }, - { - description: 'support null/undefined', - type: 'average', - data: [ undefined, null ], - result: null - } - ] - .forEach(agg => { - it(`should return the result of the ${agg.type} aggregation over the last doc - ${agg.description}`, function () { - const bucket = { - '1': { - hits: { - hits: [ - { - _source: { - bytes: agg.data - } - } - ] - } - } - }; - - init({ field: 'bytes', aggregate: agg.type }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.eql(agg.result); - }); - - it(`should return the result of the ${agg.type} aggregation over the last X docs - ${agg.description}`, function () { - const bucket = { - '1': { - hits: { - hits: [ - { - _source: { - bytes: _.dropRight(agg.data, 1) - } - }, - { - _source: { - bytes: _.last(agg.data) - } - } - ] - } - } - }; - - init({ field: 'bytes', aggregate: agg.type }); - expect(topHitMetricAgg.getValue(aggConfig, bucket)).to.eql(agg.result); - }); - }); - }); - }); -}); diff --git a/src/legacy/ui/public/agg_types/metrics/get_response_agg_config_class.ts b/src/legacy/ui/public/agg_types/metrics/lib/get_response_agg_config_class.ts similarity index 75% rename from src/legacy/ui/public/agg_types/metrics/get_response_agg_config_class.ts rename to src/legacy/ui/public/agg_types/metrics/lib/get_response_agg_config_class.ts index 34658431a96ab..054543de3dd06 100644 --- a/src/legacy/ui/public/agg_types/metrics/get_response_agg_config_class.ts +++ b/src/legacy/ui/public/agg_types/metrics/lib/get_response_agg_config_class.ts @@ -16,9 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - import { assign } from 'lodash'; -import { IMetricAggConfig } from './metric_agg_type'; +import { IMetricAggConfig } from '../metric_agg_type'; /** * Get the ResponseAggConfig class for an aggConfig, @@ -41,10 +40,7 @@ export interface IResponseAggConfig extends IMetricAggConfig { parentId: IMetricAggConfig['id']; } -export const create = ( - parentAgg: IMetricAggConfig, - props: Partial -): IMetricAggConfig => { +export const create = (parentAgg: IMetricAggConfig, props: Partial) => { /** * AggConfig "wrapper" for multi-value metric aggs which * need to modify AggConfig behavior for each value produced. @@ -52,23 +48,21 @@ export const create = ( * @param {string|number} key - the key or index that identifies * this part of the multi-value */ - class ResponseAggConfig { - id: IMetricAggConfig['id']; - key: string | number; - parentId: IMetricAggConfig['id']; - - constructor(key: string) { - this.key = key; - this.parentId = parentAgg.id; + function ResponseAggConfig(this: IResponseAggConfig, key: string) { + const parentId = parentAgg.id; + let id; - const subId = String(key); + const subId = String(key); - if (subId.indexOf('.') > -1) { - this.id = this.parentId + "['" + subId.replace(/'/g, "\\'") + "']"; - } else { - this.id = this.parentId + '.' + subId; - } + if (subId.indexOf('.') > -1) { + id = parentId + "['" + subId.replace(/'/g, "\\'") + "']"; + } else { + id = parentId + '.' + subId; } + + this.id = id; + this.key = key; + this.parentId = parentId; } ResponseAggConfig.prototype = Object.create(parentAgg); @@ -76,5 +70,5 @@ export const create = ( assign(ResponseAggConfig.prototype, props); - return (ResponseAggConfig as unknown) as IMetricAggConfig; + return ResponseAggConfig; }; diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/lib/make_nested_label.js b/src/legacy/ui/public/agg_types/metrics/lib/make_nested_label.test.ts similarity index 62% rename from src/legacy/ui/public/agg_types/__tests__/metrics/lib/make_nested_label.js rename to src/legacy/ui/public/agg_types/metrics/lib/make_nested_label.test.ts index f4ba550557874..aed5bd630d3d2 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/lib/make_nested_label.js +++ b/src/legacy/ui/public/agg_types/metrics/lib/make_nested_label.test.ts @@ -17,40 +17,43 @@ * under the License. */ -import expect from '@kbn/expect'; -import { makeNestedLabel } from '../../../metrics/lib/make_nested_label'; +import { makeNestedLabel } from './make_nested_label'; +import { IMetricAggConfig } from 'ui/agg_types/metrics/metric_agg_type'; -describe('metric agg make_nested_label', function () { - - function generateAggConfig(metricLabel) { - return { +describe('metric agg make_nested_label', () => { + const generateAggConfig = (metricLabel: string): IMetricAggConfig => { + return ({ params: { customMetric: { - makeLabel: () => { return metricLabel; } - } + makeLabel: () => { + return metricLabel; + }, + }, }, - getParam(key) { + getParam(this: IMetricAggConfig, key: string) { return this.params[key]; - } - }; - } + }, + } as unknown) as IMetricAggConfig; + }; - it('should return a metric label with prefix', function () { + it('should return a metric label with prefix', () => { const aggConfig = generateAggConfig('Count'); const label = makeNestedLabel(aggConfig, 'derivative'); - expect(label).to.eql('Derivative of Count'); + + expect(label).toEqual('Derivative of Count'); }); - it('should return a numbered prefix', function () { + it('should return a numbered prefix', () => { const aggConfig = generateAggConfig('Derivative of Count'); const label = makeNestedLabel(aggConfig, 'derivative'); - expect(label).to.eql('2. derivative of Count'); + + expect(label).toEqual('2. derivative of Count'); }); - it('should return a prefix with correct order', function () { + it('should return a prefix with correct order', () => { const aggConfig = generateAggConfig('3. derivative of Count'); const label = makeNestedLabel(aggConfig, 'derivative'); - expect(label).to.eql('4. derivative of Count'); - }); + expect(label).toEqual('4. derivative of Count'); + }); }); diff --git a/src/legacy/ui/public/agg_types/metrics/median.test.ts b/src/legacy/ui/public/agg_types/metrics/median.test.ts new file mode 100644 index 0000000000000..819c24f135cdc --- /dev/null +++ b/src/legacy/ui/public/agg_types/metrics/median.test.ts @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { AggConfigs } from '../agg_configs'; +import { METRIC_TYPES } from './metric_agg_types'; + +jest.mock('ui/new_platform'); + +describe('AggTypeMetricMedianProvider class', () => { + let aggConfigs: AggConfigs; + + beforeEach(() => { + const field = { + name: 'bytes', + }; + const indexPattern = { + id: '1234', + title: 'logstash-*', + fields: { + getByName: () => field, + filter: () => [field], + }, + } as any; + + aggConfigs = new AggConfigs( + indexPattern, + [ + { + id: METRIC_TYPES.MEDIAN, + type: METRIC_TYPES.MEDIAN, + schema: 'metric', + params: { + field: 'bytes', + percents: [70], + }, + }, + ], + null + ); + }); + + it('requests the percentiles aggregation in the Elasticsearch query DSL', () => { + const dsl: Record = aggConfigs.toDsl(); + + expect(dsl.median.percentiles.percents).toEqual([70]); + }); + + it('asks Elasticsearch for array-based values in the aggregation response', () => { + const dsl: Record = aggConfigs.toDsl(); + + expect(dsl.median.percentiles.keyed).toBeFalsy(); + }); +}); diff --git a/src/legacy/ui/public/agg_types/metrics/parent_pipeline.test.ts b/src/legacy/ui/public/agg_types/metrics/parent_pipeline.test.ts new file mode 100644 index 0000000000000..bf88adcee92b7 --- /dev/null +++ b/src/legacy/ui/public/agg_types/metrics/parent_pipeline.test.ts @@ -0,0 +1,248 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import sinon from 'sinon'; +import { derivativeMetricAgg } from './derivative'; +import { cumulativeSumMetricAgg } from './cumulative_sum'; +import { movingAvgMetricAgg } from './moving_avg'; +import { serialDiffMetricAgg } from './serial_diff'; +import { AggConfigs } from 'ui/agg_types'; +import { IMetricAggConfig, MetricAggType } from 'ui/agg_types/metrics/metric_agg_type'; + +jest.mock('../../vis/editors/default/schemas', () => { + class MockedSchemas { + all = [{}]; + } + return { + Schemas: jest.fn().mockImplementation(() => new MockedSchemas()), + }; +}); + +jest.mock('../../vis/editors/default/controls/sub_metric', () => { + return { + SubMetricParamEditor() {}, + }; +}); + +jest.mock('../../vis/editors/default/controls/sub_agg', () => { + return { + SubAggParamEditor() {}, + }; +}); + +jest.mock('ui/new_platform'); + +describe('parent pipeline aggs', function() { + const metrics = [ + { name: 'derivative', title: 'Derivative', provider: derivativeMetricAgg }, + { name: 'cumulative_sum', title: 'Cumulative Sum', provider: cumulativeSumMetricAgg }, + { name: 'moving_avg', title: 'Moving Avg', provider: movingAvgMetricAgg, dslName: 'moving_fn' }, + { name: 'serial_diff', title: 'Serial Diff', provider: serialDiffMetricAgg }, + ]; + + metrics.forEach(metric => { + describe(`${metric.title} metric`, () => { + let aggDsl: Record; + let metricAgg: MetricAggType; + let aggConfig: IMetricAggConfig; + + const init = ( + params: any = { + metricAgg: '1', + customMetric: null, + } + ) => { + const field = { + name: 'field', + format: { + type: { + id: 'bytes', + }, + }, + }; + const indexPattern = { + id: '1234', + title: 'logstash-*', + fields: { + getByName: () => field, + filter: () => [field], + }, + } as any; + + const aggConfigs = new AggConfigs( + indexPattern, + [ + { + id: '1', + type: 'count', + schema: 'metric', + }, + { + id: '2', + type: metric.name, + schema: 'metric', + params, + }, + { + id: '3', + type: 'max', + params: { field: 'field' }, + schema: 'metric', + }, + ], + null + ); + + // Grab the aggConfig off the vis (we don't actually use the vis for anything else) + metricAgg = metric.provider; + aggConfig = aggConfigs.aggs[1]; + aggDsl = aggConfig.toDsl(aggConfigs); + }; + + it(`should return a label prefixed with ${metric.title} of`, () => { + init(); + + expect(metricAgg.makeLabel(aggConfig)).toEqual(`${metric.title} of Count`); + }); + + it(`should return a label ${metric.title} of max bytes`, () => { + init({ + metricAgg: 'custom', + customMetric: { + id: '1-orderAgg', + type: 'max', + params: { field: 'field' }, + schema: 'orderAgg', + }, + }); + expect(metricAgg.makeLabel(aggConfig)).toEqual(`${metric.title} of Max field`); + }); + + it(`should return a label prefixed with number of ${metric.title.toLowerCase()}`, () => { + init({ + metricAgg: 'custom', + customMetric: { + id: '2-orderAgg', + type: metric.name, + params: { + buckets_path: 'custom', + customMetric: { + id: '2-orderAgg-orderAgg', + type: 'count', + schema: 'orderAgg', + }, + }, + schema: 'orderAgg', + }, + }); + expect(metricAgg.makeLabel(aggConfig)).toEqual(`2. ${metric.title.toLowerCase()} of Count`); + }); + + it('should set parent aggs', () => { + init({ + metricAgg: 'custom', + customMetric: { + id: '2-metric', + type: 'max', + params: { field: 'field' }, + schema: 'orderAgg', + }, + }); + expect(aggDsl[metric.dslName || metric.name].buckets_path).toBe('2-metric'); + expect(aggDsl.parentAggs['2-metric'].max.field).toBe('field'); + }); + + it('should set nested parent aggs', () => { + init({ + metricAgg: 'custom', + customMetric: { + id: '2-metric', + type: metric.name, + params: { + buckets_path: 'custom', + customMetric: { + id: '2-metric-metric', + type: 'max', + params: { field: 'field' }, + schema: 'orderAgg', + }, + }, + schema: 'orderAgg', + }, + }); + expect(aggDsl[metric.dslName || metric.name].buckets_path).toBe('2-metric'); + expect(aggDsl.parentAggs['2-metric'][metric.dslName || metric.name].buckets_path).toBe( + '2-metric-metric' + ); + }); + + it('should have correct formatter', () => { + init({ + metricAgg: '3', + }); + expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + }); + + it('should have correct customMetric nested formatter', () => { + init({ + metricAgg: 'custom', + customMetric: { + id: '2-metric', + type: metric.name, + params: { + buckets_path: 'custom', + customMetric: { + id: '2-metric-metric', + type: 'max', + params: { field: 'field' }, + schema: 'orderAgg', + }, + }, + schema: 'orderAgg', + }, + }); + expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + }); + + it("should call modifyAggConfigOnSearchRequestStart for its customMetric's parameters", () => { + init({ + metricAgg: 'custom', + customMetric: { + id: '2-metric', + type: 'max', + params: { field: 'field' }, + schema: 'orderAgg', + }, + }); + + const searchSource: any = {}; + const customMetricSpy = sinon.spy(); + const customMetric = aggConfig.params.customMetric; + + // Attach a modifyAggConfigOnSearchRequestStart with a spy to the first parameter + customMetric.type.params[0].modifyAggConfigOnSearchRequestStart = customMetricSpy; + + aggConfig.type.params.forEach(param => { + param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource); + }); + expect(customMetricSpy.calledWith(customMetric, searchSource)).toBe(true); + }); + }); + }); +}); diff --git a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.test.ts b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.test.ts new file mode 100644 index 0000000000000..f3882ca57161f --- /dev/null +++ b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.test.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IPercentileRanksAggConfig, percentileRanksMetricAgg } from './percentile_ranks'; +import { AggConfigs } from '../agg_configs'; +import { METRIC_TYPES } from './metric_agg_types'; + +jest.mock('ui/new_platform'); + +describe('AggTypesMetricsPercentileRanksProvider class', function() { + let aggConfigs: AggConfigs; + + beforeEach(() => { + const field = { + name: 'bytes', + }; + const indexPattern = { + id: '1234', + title: 'logstash-*', + fields: { + getByName: () => field, + filter: () => [field], + }, + } as any; + + aggConfigs = new AggConfigs( + indexPattern, + [ + { + id: METRIC_TYPES.PERCENTILE_RANKS, + type: METRIC_TYPES.PERCENTILE_RANKS, + schema: 'metric', + params: { + field: { + displayName: 'bytes', + format: { + convert: jest.fn(x => x), + }, + }, + customLabel: 'my custom field label', + values: [5000, 10000], + }, + }, + ], + null + ); + }); + + it('uses the custom label if it is set', function() { + const responseAggs: any = percentileRanksMetricAgg.getResponseAggs(aggConfigs + .aggs[0] as IPercentileRanksAggConfig); + + const percentileRankLabelFor5kBytes = responseAggs[0].makeLabel(); + const percentileRankLabelFor10kBytes = responseAggs[1].makeLabel(); + + expect(percentileRankLabelFor5kBytes).toBe('Percentile rank 5000 of "my custom field label"'); + expect(percentileRankLabelFor10kBytes).toBe('Percentile rank 10000 of "my custom field label"'); + }); +}); diff --git a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts index 6c069f8b70d62..8b923092772db 100644 --- a/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts +++ b/src/legacy/ui/public/agg_types/metrics/percentile_ranks.ts @@ -20,7 +20,7 @@ import { i18n } from '@kbn/i18n'; import { PercentileRanksEditor } from '../../vis/editors/default/controls/percentile_ranks'; import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; -import { getResponseAggConfigClass, IResponseAggConfig } from './get_response_agg_config_class'; +import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; @@ -30,7 +30,7 @@ import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common'; // required by the values editor -type IPercentileRanksAggConfig = IResponseAggConfig; +export type IPercentileRanksAggConfig = IResponseAggConfig; const valueProps = { makeLabel(this: IPercentileRanksAggConfig) { diff --git a/src/legacy/ui/public/agg_types/metrics/percentiles.test.ts b/src/legacy/ui/public/agg_types/metrics/percentiles.test.ts new file mode 100644 index 0000000000000..1503f43b22dc3 --- /dev/null +++ b/src/legacy/ui/public/agg_types/metrics/percentiles.test.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IPercentileAggConfig, percentilesMetricAgg } from './percentiles'; +import { AggConfigs } from '../agg_configs'; +import { METRIC_TYPES } from './metric_agg_types'; + +jest.mock('ui/new_platform'); + +describe('AggTypesMetricsPercentilesProvider class', () => { + let aggConfigs: AggConfigs; + + beforeEach(() => { + const field = { + name: 'bytes', + }; + const indexPattern = { + id: '1234', + title: 'logstash-*', + fields: { + getByName: () => field, + filter: () => [field], + }, + } as any; + + aggConfigs = new AggConfigs( + indexPattern, + [ + { + id: METRIC_TYPES.PERCENTILES, + type: METRIC_TYPES.PERCENTILES, + schema: 'metric', + params: { + field: { + displayName: 'bytes', + format: { + convert: jest.fn(x => `${x}th`), + }, + }, + customLabel: 'prince', + percents: [95], + }, + }, + ], + null + ); + }); + + it('uses the custom label if it is set', () => { + const responseAggs: any = percentilesMetricAgg.getResponseAggs(aggConfigs + .aggs[0] as IPercentileAggConfig); + + const ninetyFifthPercentileLabel = responseAggs[0].makeLabel(); + + expect(ninetyFifthPercentileLabel).toBe('95th percentile of prince'); + }); +}); diff --git a/src/legacy/ui/public/agg_types/metrics/percentiles.ts b/src/legacy/ui/public/agg_types/metrics/percentiles.ts index 21cb3939d38f7..0ac0455468472 100644 --- a/src/legacy/ui/public/agg_types/metrics/percentiles.ts +++ b/src/legacy/ui/public/agg_types/metrics/percentiles.ts @@ -23,14 +23,14 @@ import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common'; -import { getResponseAggConfigClass, IResponseAggConfig } from './get_response_agg_config_class'; +import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { getPercentileValue } from './percentiles_get_value'; import { PercentilesEditor } from '../../vis/editors/default/controls/percentiles'; // @ts-ignore import { ordinalSuffix } from '../../utils/ordinal_suffix'; -type IPercentileAggConfig = IResponseAggConfig; +export type IPercentileAggConfig = IResponseAggConfig; const valueProps = { makeLabel(this: IPercentileAggConfig) { diff --git a/src/legacy/ui/public/agg_types/metrics/percentiles_get_value.ts b/src/legacy/ui/public/agg_types/metrics/percentiles_get_value.ts index 56e1f0456d62e..c357d7bb0a903 100644 --- a/src/legacy/ui/public/agg_types/metrics/percentiles_get_value.ts +++ b/src/legacy/ui/public/agg_types/metrics/percentiles_get_value.ts @@ -18,7 +18,7 @@ */ import { find } from 'lodash'; -import { IResponseAggConfig } from './get_response_agg_config_class'; +import { IResponseAggConfig } from './lib/get_response_agg_config_class'; export const getPercentileValue = ( agg: TAggConfig, diff --git a/src/legacy/ui/public/agg_types/metrics/sibling_pipeline.test.ts b/src/legacy/ui/public/agg_types/metrics/sibling_pipeline.test.ts new file mode 100644 index 0000000000000..a3381aca6f9e7 --- /dev/null +++ b/src/legacy/ui/public/agg_types/metrics/sibling_pipeline.test.ts @@ -0,0 +1,188 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { spy } from 'sinon'; +import { bucketSumMetricAgg } from './bucket_sum'; +import { bucketAvgMetricAgg } from './bucket_avg'; +import { bucketMinMetricAgg } from './bucket_min'; +import { bucketMaxMetricAgg } from './bucket_max'; + +import { AggConfigs } from 'ui/agg_types'; +import { IMetricAggConfig, MetricAggType } from 'ui/agg_types/metrics/metric_agg_type'; + +jest.mock('../../vis/editors/default/schemas', () => { + class MockedSchemas { + all = [{}]; + } + return { + Schemas: jest.fn().mockImplementation(() => new MockedSchemas()), + }; +}); + +jest.mock('../../vis/editors/default/controls/sub_metric', () => { + return { + SubMetricParamEditor() {}, + }; +}); + +jest.mock('ui/new_platform'); + +describe('sibling pipeline aggs', () => { + const metrics = [ + { name: 'sum_bucket', title: 'Overall Sum', provider: bucketSumMetricAgg }, + { name: 'avg_bucket', title: 'Overall Average', provider: bucketAvgMetricAgg }, + { name: 'min_bucket', title: 'Overall Min', provider: bucketMinMetricAgg }, + { name: 'max_bucket', title: 'Overall Max', provider: bucketMaxMetricAgg }, + ]; + + metrics.forEach(metric => { + describe(`${metric.title} metric`, () => { + let aggDsl: Record; + let metricAgg: MetricAggType; + let aggConfig: IMetricAggConfig; + + const init = (settings?: any) => { + const field = { + name: 'field', + format: { + type: { + id: 'bytes', + }, + }, + }; + const indexPattern = { + id: '1234', + title: 'logstash-*', + fields: { + getByName: () => field, + filter: () => [field], + }, + } as any; + + const aggConfigs = new AggConfigs( + indexPattern, + [ + { + id: '1', + type: 'count', + schema: 'metric', + }, + { + id: '2', + type: metric.name, + schema: 'metric', + params: settings || { + customMetric: { + id: '5', + type: 'count', + schema: 'metric', + }, + customBucket: { + id: '6', + type: 'date_histogram', + schema: 'bucket', + params: { field: 'field', interval: '10s' }, + }, + }, + }, + ], + null + ); + + // Grab the aggConfig off the vis (we don't actually use the vis for anything else) + metricAgg = metric.provider; + aggConfig = aggConfigs.aggs[1]; + aggDsl = aggConfig.toDsl(aggConfigs); + }; + + it(`should return a label prefixed with ${metric.title} of`, () => { + init(); + + expect(metricAgg.makeLabel(aggConfig)).toEqual(`${metric.title} of Count`); + }); + + it('should set parent aggs', function() { + init(); + + expect(aggDsl[metric.name].buckets_path).toBe('2-bucket>_count'); + expect(aggDsl.parentAggs['2-bucket'].date_histogram).not.toBeUndefined(); + }); + + it('should set nested parent aggs', () => { + init({ + customMetric: { + id: '5', + type: 'avg', + schema: 'metric', + params: { field: 'field' }, + }, + customBucket: { + id: '6', + type: 'date_histogram', + schema: 'bucket', + params: { field: 'field', interval: '10s' }, + }, + }); + + expect(aggDsl[metric.name].buckets_path).toBe('2-bucket>2-metric'); + expect(aggDsl.parentAggs['2-bucket'].date_histogram).not.toBeUndefined(); + expect(aggDsl.parentAggs['2-bucket'].aggs['2-metric'].avg.field).toEqual('field'); + }); + + it('should have correct formatter', () => { + init({ + customMetric: { + id: '5', + type: 'avg', + schema: 'metric', + params: { field: 'field' }, + }, + customBucket: { + id: '6', + type: 'date_histogram', + schema: 'bucket', + params: { field: 'field', interval: '10s' }, + }, + }); + + expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes'); + }); + + it("should call modifyAggConfigOnSearchRequestStart for nested aggs' parameters", () => { + init(); + + const searchSource: any = {}; + const customMetricSpy = spy(); + const customBucketSpy = spy(); + const { customMetric, customBucket } = aggConfig.params; + + // Attach a modifyAggConfigOnSearchRequestStart with a spy to the first parameter + customMetric.type.params[0].modifyAggConfigOnSearchRequestStart = customMetricSpy; + customBucket.type.params[0].modifyAggConfigOnSearchRequestStart = customBucketSpy; + + aggConfig.type.params.forEach(param => { + param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource); + }); + + expect(customMetricSpy.calledWith(customMetric, searchSource)).toBe(true); + expect(customBucketSpy.calledWith(customBucket, searchSource)).toBe(true); + }); + }); + }); +}); diff --git a/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts b/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts new file mode 100644 index 0000000000000..ca81e8daee449 --- /dev/null +++ b/src/legacy/ui/public/agg_types/metrics/std_deviation.test.ts @@ -0,0 +1,83 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IStdDevAggConfig, stdDeviationMetricAgg } from './std_deviation'; +import { AggConfigs } from 'ui/agg_types'; +import { METRIC_TYPES } from 'ui/agg_types/metrics/metric_agg_types'; + +jest.mock('ui/new_platform'); + +describe('AggTypeMetricStandardDeviationProvider class', () => { + const getAggConfigs = (customLabel?: string) => { + const field = { + name: 'memory', + }; + const indexPattern = { + id: '1234', + title: 'logstash-*', + fields: { + getByName: () => field, + filter: () => [field], + }, + } as any; + + return new AggConfigs( + indexPattern, + [ + { + id: METRIC_TYPES.STD_DEV, + type: METRIC_TYPES.STD_DEV, + schema: 'metric', + params: { + field: { + displayName: 'memory', + }, + customLabel, + }, + }, + ], + null + ); + }; + + it('uses the custom label if it is set', () => { + const aggConfigs = getAggConfigs('custom label'); + const responseAggs: any = stdDeviationMetricAgg.getResponseAggs(aggConfigs + .aggs[0] as IStdDevAggConfig); + + const lowerStdDevLabel = responseAggs[0].makeLabel(); + const upperStdDevLabel = responseAggs[1].makeLabel(); + + expect(lowerStdDevLabel).toBe('Lower custom label'); + expect(upperStdDevLabel).toBe('Upper custom label'); + }); + + it('uses the default labels if custom label is not set', () => { + const aggConfigs = getAggConfigs(); + + const responseAggs: any = stdDeviationMetricAgg.getResponseAggs(aggConfigs + .aggs[0] as IStdDevAggConfig); + + const lowerStdDevLabel = responseAggs[0].makeLabel(); + const upperStdDevLabel = responseAggs[1].makeLabel(); + + expect(lowerStdDevLabel).toBe('Lower Standard Deviation of memory'); + expect(upperStdDevLabel).toBe('Upper Standard Deviation of memory'); + }); +}); diff --git a/src/legacy/ui/public/agg_types/metrics/std_deviation.ts b/src/legacy/ui/public/agg_types/metrics/std_deviation.ts index 89051f119c588..ebd5fceb9c751 100644 --- a/src/legacy/ui/public/agg_types/metrics/std_deviation.ts +++ b/src/legacy/ui/public/agg_types/metrics/std_deviation.ts @@ -21,7 +21,7 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; -import { getResponseAggConfigClass, IResponseAggConfig } from './get_response_agg_config_class'; +import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common'; interface ValProp { @@ -29,7 +29,7 @@ interface ValProp { title: string; } -interface IStdDevAggConfig extends IResponseAggConfig { +export interface IStdDevAggConfig extends IResponseAggConfig { keyedDetails: (customLabel: string, fieldDisplayName?: string) => { [key: string]: ValProp }; valProp: () => ValProp; } diff --git a/src/legacy/ui/public/agg_types/metrics/top_hit.test.ts b/src/legacy/ui/public/agg_types/metrics/top_hit.test.ts new file mode 100644 index 0000000000000..4ed6fcdcf641b --- /dev/null +++ b/src/legacy/ui/public/agg_types/metrics/top_hit.test.ts @@ -0,0 +1,366 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { dropRight, last } from 'lodash'; +import { topHitMetricAgg } from './top_hit'; +import { AggConfigs } from 'ui/agg_types'; +import { IMetricAggConfig } from 'ui/agg_types/metrics/metric_agg_type'; +import { KBN_FIELD_TYPES } from '../../../../../plugins/data/common'; + +jest.mock('ui/new_platform'); + +describe('Top hit metric', () => { + let aggDsl: Record; + let aggConfig: IMetricAggConfig; + + const init = ({ + fieldName = 'field', + sortOrder = 'desc', + aggregate = 'concat', + readFromDocValues = false, + fieldType = KBN_FIELD_TYPES.NUMBER, + size = 1, + }: any) => { + const field = { + name: fieldName, + displayName: fieldName, + type: fieldType, + readFromDocValues, + format: { + type: { + id: 'bytes', + }, + }, + }; + + const params = { + size, + field: fieldName, + sortField: field, + sortOrder: { + value: sortOrder, + }, + aggregate: { + value: aggregate, + }, + }; + + const indexPattern = { + id: '1234', + title: 'logstash-*', + fields: { + getByName: () => field, + filter: () => [field], + }, + flattenHit: jest.fn(x => x!._source), + } as any; + + const aggConfigs = new AggConfigs( + indexPattern, + [ + { + id: '1', + type: 'top_hits', + schema: 'metric', + params, + }, + ], + null + ); + + // Grab the aggConfig off the vis (we don't actually use the vis for anything else) + aggConfig = aggConfigs.aggs[0]; + aggDsl = aggConfig.toDsl(aggConfigs); + }; + + it('should return a label prefixed with Last if sorting in descending order', () => { + init({ fieldName: 'bytes' }); + expect(topHitMetricAgg.makeLabel(aggConfig)).toEqual('Last bytes'); + }); + + it('should return a label prefixed with First if sorting in ascending order', () => { + init({ + fieldName: 'bytes', + sortOrder: 'asc', + }); + expect(topHitMetricAgg.makeLabel(aggConfig)).toEqual('First bytes'); + }); + + it('should request the _source field', () => { + init({ field: '_source' }); + expect(aggDsl.top_hits._source).toBeTruthy(); + expect(aggDsl.top_hits.docvalue_fields).toBeUndefined(); + }); + + it('requests both source and docvalues_fields for non-text aggregatable fields', () => { + init({ fieldName: 'bytes', readFromDocValues: true }); + expect(aggDsl.top_hits._source).toBe('bytes'); + expect(aggDsl.top_hits.docvalue_fields).toEqual([ + { field: 'bytes', format: 'use_field_mapping' }, + ]); + }); + + it('requests both source and docvalues_fields for date aggregatable fields', () => { + init({ fieldName: '@timestamp', readFromDocValues: true, fieldType: KBN_FIELD_TYPES.DATE }); + + expect(aggDsl.top_hits._source).toBe('@timestamp'); + expect(aggDsl.top_hits.docvalue_fields).toEqual([{ field: '@timestamp', format: 'date_time' }]); + }); + + it('requests just source for aggregatable text fields', () => { + init({ fieldName: 'machine.os' }); + expect(aggDsl.top_hits._source).toBe('machine.os'); + expect(aggDsl.top_hits.docvalue_fields).toBeUndefined(); + }); + + describe('try to get the value from the top hit', () => { + it('should return null if there is no hit', () => { + const bucket = { + '1': { + hits: { + hits: [], + }, + }, + }; + + init({ fieldName: '@tags' }); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).toBe(null); + }); + // + it('should return undefined if the field does not appear in the source', () => { + const bucket = { + '1': { + hits: { + hits: [ + { + _source: { + bytes: 123, + }, + }, + ], + }, + }, + }; + + init({ fieldName: '@tags' }); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).toBe(undefined); + }); + + it('should return the field value from the top hit', () => { + const bucket = { + '1': { + hits: { + hits: [ + { + _source: { + '@tags': 'aaa', + }, + }, + ], + }, + }, + }; + + init({ fieldName: '@tags' }); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).toBe('aaa'); + }); + + it('should return the object if the field value is an object', () => { + const bucket = { + '1': { + hits: { + hits: [ + { + _source: { + '@tags': { + label: 'aaa', + }, + }, + }, + ], + }, + }, + }; + + init({ fieldName: '@tags' }); + + expect(topHitMetricAgg.getValue(aggConfig, bucket)).toEqual({ label: 'aaa' }); + }); + + it('should return an array if the field has more than one values', () => { + const bucket = { + '1': { + hits: { + hits: [ + { + _source: { + '@tags': ['aaa', 'bbb'], + }, + }, + ], + }, + }, + }; + + init({ fieldName: '@tags' }); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).toEqual(['aaa', 'bbb']); + }); + + it('should return undefined if the field is not in the source nor in the doc_values field', () => { + const bucket = { + '1': { + hits: { + hits: [ + { + _source: { + bytes: 12345, + }, + fields: { + bytes: 12345, + }, + }, + ], + }, + }, + }; + + init({ fieldName: 'machine.os.raw', readFromDocValues: true }); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).toBe(undefined); + }); + + describe('Multivalued field and first/last X docs', () => { + it('should return a label prefixed with Last X docs if sorting in descending order', () => { + init({ + fieldName: 'bytes', + size: 2, + }); + expect(topHitMetricAgg.makeLabel(aggConfig)).toEqual('Last 2 bytes'); + }); + + it('should return a label prefixed with First X docs if sorting in ascending order', () => { + init({ + fieldName: 'bytes', + size: 2, + sortOrder: 'asc', + }); + expect(topHitMetricAgg.makeLabel(aggConfig)).toEqual('First 2 bytes'); + }); + + [ + { + description: 'concat values with a comma', + type: 'concat', + data: [1, 2, 3], + result: [1, 2, 3], + }, + { + description: 'sum up the values', + type: 'sum', + data: [1, 2, 3], + result: 6, + }, + { + description: 'take the minimum value', + type: 'min', + data: [1, 2, 3], + result: 1, + }, + { + description: 'take the maximum value', + type: 'max', + data: [1, 2, 3], + result: 3, + }, + { + description: 'take the average value', + type: 'average', + data: [1, 2, 3], + result: 2, + }, + { + description: 'support null/undefined', + type: 'min', + data: [undefined, null], + result: null, + }, + { + description: 'support null/undefined', + type: 'max', + data: [undefined, null], + result: null, + }, + { + description: 'support null/undefined', + type: 'sum', + data: [undefined, null], + result: null, + }, + { + description: 'support null/undefined', + type: 'average', + data: [undefined, null], + result: null, + }, + ].forEach(agg => { + it(`should return the result of the ${agg.type} aggregation over the last doc - ${agg.description}`, () => { + const bucket = { + '1': { + hits: { + hits: [ + { + _source: { + bytes: agg.data, + }, + }, + ], + }, + }, + }; + + init({ fieldName: 'bytes', aggregate: agg.type }); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).toEqual(agg.result); + }); + + it(`should return the result of the ${agg.type} aggregation over the last X docs - ${agg.description}`, () => { + const bucket = { + '1': { + hits: { + hits: [ + { + _source: { + bytes: dropRight(agg.data, 1), + }, + }, + { + _source: { + bytes: last(agg.data), + }, + }, + ], + }, + }, + }; + + init({ fieldName: 'bytes', aggregate: agg.type }); + expect(topHitMetricAgg.getValue(aggConfig, bucket)).toEqual(agg.result); + }); + }); + }); + }); +}); diff --git a/src/legacy/ui/public/vis/editors/default/components/agg_params.tsx b/src/legacy/ui/public/vis/editors/default/components/agg_params.tsx index 6513c9211f18b..4f4c0bda6520a 100644 --- a/src/legacy/ui/public/vis/editors/default/components/agg_params.tsx +++ b/src/legacy/ui/public/vis/editors/default/components/agg_params.tsx @@ -21,9 +21,10 @@ import React, { useReducer, useEffect, useMemo } from 'react'; import { EuiForm, EuiAccordion, EuiSpacer, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { aggTypes, AggType, AggParam } from 'ui/agg_types'; +import { VisState } from 'ui/vis'; +import { aggTypes, AggType, AggParam, AggConfig } from 'ui/agg_types/'; import { IndexPattern } from 'ui/index_patterns'; -import { AggConfig, VisState } from '../../..'; + import { DefaultEditorAggSelect } from './agg_select'; import { DefaultEditorAggParam } from './agg_param'; import { diff --git a/src/legacy/ui/public/vis/editors/default/controls/sub_metric.tsx b/src/legacy/ui/public/vis/editors/default/controls/sub_metric.tsx index 836049eb95cab..df1640273135e 100644 --- a/src/legacy/ui/public/vis/editors/default/controls/sub_metric.tsx +++ b/src/legacy/ui/public/vis/editors/default/controls/sub_metric.tsx @@ -21,7 +21,7 @@ import React, { useEffect, useState } from 'react'; import { EuiFormLabel, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { AggParamType } from '../../../../agg_types/param_types/agg'; -import { AggConfig } from '../../..'; +import { AggConfig } from '../../../../agg_types/agg_config'; import { AggParamEditorProps, DefaultEditorAggParams, AggGroupNames } from '..'; function SubMetricParamEditor({ From 1e12e68ca71095bc2874d540c76c6af0ea809626 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Thu, 24 Oct 2019 14:23:06 +0200 Subject: [PATCH 114/191] [ML] add fullRefresh check (#49161) --- .../ml/public/timeseriesexplorer/timeseriesexplorer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js index 802772e55078c..164e5e7b5a778 100644 --- a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js @@ -1173,11 +1173,11 @@ export class TimeSeriesExplorer extends React.Component { /> )} - {(arePartitioningFieldsProvided && jobs.length > 0 && loading === false && hasResults === false) && ( + {(arePartitioningFieldsProvided && jobs.length > 0 && (fullRefresh === false || loading === false) && hasResults === false) && ( )} - {(arePartitioningFieldsProvided && jobs.length > 0 && loading === false && hasResults === true) && ( + {(arePartitioningFieldsProvided && jobs.length > 0 && (fullRefresh === false || loading === false) && hasResults === true) && ( From 2ff021b591d19473f87e65c3be102973222f83dc Mon Sep 17 00:00:00 2001 From: Robert Oskamp Date: Thu, 24 Oct 2019 14:33:19 +0200 Subject: [PATCH 115/191] [ML] Remove dependent sub suite structure from test files (#49059) This PR removes the sub suites from all ML test files, such that all test steps that are dependent on each other are executed in one big suite. --- .../anomaly_detection/multi_metric_job.ts | 551 ++++++++--------- .../anomaly_detection/population_job.ts | 580 +++++++++--------- .../anomaly_detection/saved_search_job.ts | 52 +- .../anomaly_detection/single_metric_job.ts | 527 ++++++++-------- 4 files changed, 834 insertions(+), 876 deletions(-) diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts index c4e6459e10555..06dd0df9e470c 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts @@ -82,289 +82,274 @@ export default function({ getService }: FtrProviderContext) { await ml.api.cleanMlIndices(); }); - describe('job creation', function() { - it('loads the job management page', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - }); - - it('loads the new job source selection page', async () => { - await ml.jobManagement.navigateToNewJobSourceSelection(); - }); - - it('loads the job type selection page', async () => { - await ml.jobSourceSelection.selectSource('farequote'); - }); - - it('loads the multi metric job wizard page', async () => { - await ml.jobTypeSelection.selectMultiMetricJob(); - }); - - it('displays the time range step', async () => { - await ml.jobWizardCommon.assertTimeRangeSectionExists(); - }); - - it('sets the timerange', async () => { - await ml.jobWizardCommon.clickUseFullDataButton( - 'Feb 7, 2016 @ 00:00:00.000', - 'Feb 11, 2016 @ 23:59:54.000' - ); - }); - - it('displays the event rate chart', async () => { - await ml.jobWizardCommon.assertEventRateChartExists(); - await ml.jobWizardCommon.assertEventRateChartHasData(); - }); - - it('displays the pick fields step', async () => { - await ml.jobWizardCommon.advanceToPickFieldsSection(); - }); - - it('selects detectors and displays detector previews', async () => { - for (const [index, aggAndFieldIdentifier] of aggAndFieldIdentifiers.entries()) { - await ml.jobWizardCommon.assertAggAndFieldInputExists(); - await ml.jobWizardCommon.selectAggAndField(aggAndFieldIdentifier, false); - await ml.jobWizardCommon.assertDetectorPreviewExists( - aggAndFieldIdentifier, - index, - 'LINE' - ); - } - }); - - it('inputs the split field and displays split cards', async () => { - await ml.jobWizardMultiMetric.assertSplitFieldInputExists(); - await ml.jobWizardMultiMetric.selectSplitField(splitField); - - await ml.jobWizardMultiMetric.assertDetectorSplitExists(splitField); - await ml.jobWizardMultiMetric.assertDetectorSplitFrontCardTitle('AAL'); - await ml.jobWizardMultiMetric.assertDetectorSplitNumberOfBackCards(9); - - await ml.jobWizardCommon.assertInfluencerSelection([splitField]); - }); - - it('displays the influencer field', async () => { - await ml.jobWizardCommon.assertInfluencerInputExists(); - await ml.jobWizardCommon.assertInfluencerSelection([splitField]); - }); - - it('inputs the bucket span', async () => { - await ml.jobWizardCommon.assertBucketSpanInputExists(); - await ml.jobWizardCommon.setBucketSpan(bucketSpan); - }); - - it('displays the job details step', async () => { - await ml.jobWizardCommon.advanceToJobDetailsSection(); - }); - - it('inputs the job id', async () => { - await ml.jobWizardCommon.assertJobIdInputExists(); - await ml.jobWizardCommon.setJobId(jobId); - }); - - it('inputs the job description', async () => { - await ml.jobWizardCommon.assertJobDescriptionInputExists(); - await ml.jobWizardCommon.setJobDescription(jobDescription); - }); - - it('inputs job groups', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - for (const jobGroup of jobGroups) { - await ml.jobWizardCommon.addJobGroup(jobGroup); - } - await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); - }); - - it('opens the advanced section', async () => { - await ml.jobWizardCommon.ensureAdvancedSectionOpen(); - }); - - it('displays the model plot switch', async () => { - await ml.jobWizardCommon.assertModelPlotSwitchExists(); - }); - - it('enables the dedicated index switch', async () => { - await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); - await ml.jobWizardCommon.activateDedicatedIndexSwitch(); - }); - - it('inputs the model memory limit', async () => { - await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); - await ml.jobWizardCommon.setModelMemoryLimit(memoryLimit); - }); - - it('displays the validation step', async () => { - await ml.jobWizardCommon.advanceToValidationSection(); - }); - - it('displays the summary step', async () => { - await ml.jobWizardCommon.advanceToSummarySection(); - }); - - it('creates the job and finishes processing', async () => { - await ml.jobWizardCommon.assertCreateJobButtonExists(); - await ml.jobWizardCommon.createJobAndWaitForCompletion(); - }); - - it('displays the created job in the job list', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobId); - const rows = await ml.jobTable.parseJobTable(); - expect(rows.filter(row => row.id === jobId)).to.have.length(1); - }); - - it('displays details for the created job in the job list', async () => { - await ml.jobTable.assertJobRowFields(jobId, getExpectedRow(jobId, jobGroups)); - - await ml.jobTable.assertJobRowDetailsCounts( - jobId, - getExpectedCounts(jobId), - getExpectedModelSizeStats(jobId) - ); - }); - }); - - describe('job cloning', function() { - it('clicks the clone action and loads the multi metric wizard', async () => { - await ml.jobTable.clickCloneJobAction(jobId); - await ml.jobTypeSelection.assertMultiMetricJobWizardOpen(); - }); - - it('displays the time range step', async () => { - await ml.jobWizardCommon.assertTimeRangeSectionExists(); - }); - - it('sets the timerange', async () => { - await ml.jobWizardCommon.clickUseFullDataButton( - 'Feb 7, 2016 @ 00:00:00.000', - 'Feb 11, 2016 @ 23:59:54.000' - ); - }); - - it('displays the event rate chart', async () => { - await ml.jobWizardCommon.assertEventRateChartExists(); - await ml.jobWizardCommon.assertEventRateChartHasData(); - }); - - it('displays the pick fields step', async () => { - await ml.jobWizardCommon.advanceToPickFieldsSection(); - }); - - it('pre-fills detectors and shows preview with split cards', async () => { - for (const [index, aggAndFieldIdentifier] of aggAndFieldIdentifiers.entries()) { - await ml.jobWizardCommon.assertDetectorPreviewExists( - aggAndFieldIdentifier, - index, - 'LINE' - ); - } - - await ml.jobWizardMultiMetric.assertDetectorSplitExists(splitField); - await ml.jobWizardMultiMetric.assertDetectorSplitFrontCardTitle('AAL'); - await ml.jobWizardMultiMetric.assertDetectorSplitNumberOfBackCards(9); - }); - - it('pre-fills the split field', async () => { - await ml.jobWizardMultiMetric.assertSplitFieldInputExists(); - await ml.jobWizardMultiMetric.assertSplitFieldSelection(splitField); - }); - - it('pre-fills influencers', async () => { - await ml.jobWizardCommon.assertInfluencerInputExists(); - await ml.jobWizardCommon.assertInfluencerSelection([splitField]); - }); - - it('pre-fills the bucket span', async () => { - await ml.jobWizardCommon.assertBucketSpanInputExists(); - await ml.jobWizardCommon.assertBucketSpanValue(bucketSpan); - }); - - it('displays the job details step', async () => { - await ml.jobWizardCommon.advanceToJobDetailsSection(); - }); - - it('does not pre-fill the job id', async () => { - await ml.jobWizardCommon.assertJobIdInputExists(); - await ml.jobWizardCommon.assertJobIdValue(''); - }); - - it('inputs the clone job id', async () => { - await ml.jobWizardCommon.setJobId(jobIdClone); - }); - - it('pre-fills the job description', async () => { - await ml.jobWizardCommon.assertJobDescriptionInputExists(); - await ml.jobWizardCommon.assertJobDescriptionValue(jobDescription); - }); - - it('pre-fills job groups', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); - }); - - it('inputs the clone job group', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - await ml.jobWizardCommon.addJobGroup('clone'); - await ml.jobWizardCommon.assertJobGroupSelection(jobGroupsClone); - }); - - it('opens the advanced section', async () => { - await ml.jobWizardCommon.ensureAdvancedSectionOpen(); - }); - - it('pre-fills the model plot switch', async () => { - await ml.jobWizardCommon.assertModelPlotSwitchExists(); - await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(false); - }); - - it('pre-fills the dedicated index switch', async () => { - await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); - await ml.jobWizardCommon.assertDedicatedIndexSwitchCheckedState(true); - }); - - it('pre-fills the model memory limit', async () => { - await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); - await ml.jobWizardCommon.assertModelMemoryLimitValue(memoryLimit); - }); - - it('displays the validation step', async () => { - await ml.jobWizardCommon.advanceToValidationSection(); - }); - - it('displays the summary step', async () => { - await ml.jobWizardCommon.advanceToSummarySection(); - }); - - it('creates the job and finishes processing', async () => { - await ml.jobWizardCommon.assertCreateJobButtonExists(); - await ml.jobWizardCommon.createJobAndWaitForCompletion(); - }); - - it('displays the created job in the job list', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobIdClone); - const rows = await ml.jobTable.parseJobTable(); - expect(rows.filter(row => row.id === jobIdClone)).to.have.length(1); - }); - - it('displays details for the created job in the job list', async () => { - await ml.jobTable.assertJobRowFields( - jobIdClone, - getExpectedRow(jobIdClone, jobGroupsClone) - ); - - await ml.jobTable.assertJobRowDetailsCounts( - jobIdClone, - getExpectedCounts(jobIdClone), - getExpectedModelSizeStats(jobIdClone) - ); - }); + it('job creation loads the job management page', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + }); + + it('job creation loads the new job source selection page', async () => { + await ml.jobManagement.navigateToNewJobSourceSelection(); + }); + + it('job creation loads the job type selection page', async () => { + await ml.jobSourceSelection.selectSource('farequote'); + }); + + it('job creation loads the multi metric job wizard page', async () => { + await ml.jobTypeSelection.selectMultiMetricJob(); + }); + + it('job creation displays the time range step', async () => { + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + }); + + it('job creation sets the timerange', async () => { + await ml.jobWizardCommon.clickUseFullDataButton( + 'Feb 7, 2016 @ 00:00:00.000', + 'Feb 11, 2016 @ 23:59:54.000' + ); + }); + + it('job creation displays the event rate chart', async () => { + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + }); + + it('job creation displays the pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + }); + + it('job creation selects detectors and displays detector previews', async () => { + for (const [index, aggAndFieldIdentifier] of aggAndFieldIdentifiers.entries()) { + await ml.jobWizardCommon.assertAggAndFieldInputExists(); + await ml.jobWizardCommon.selectAggAndField(aggAndFieldIdentifier, false); + await ml.jobWizardCommon.assertDetectorPreviewExists(aggAndFieldIdentifier, index, 'LINE'); + } + }); + + it('job creation inputs the split field and displays split cards', async () => { + await ml.jobWizardMultiMetric.assertSplitFieldInputExists(); + await ml.jobWizardMultiMetric.selectSplitField(splitField); + + await ml.jobWizardMultiMetric.assertDetectorSplitExists(splitField); + await ml.jobWizardMultiMetric.assertDetectorSplitFrontCardTitle('AAL'); + await ml.jobWizardMultiMetric.assertDetectorSplitNumberOfBackCards(9); + + await ml.jobWizardCommon.assertInfluencerSelection([splitField]); + }); + + it('job creation displays the influencer field', async () => { + await ml.jobWizardCommon.assertInfluencerInputExists(); + await ml.jobWizardCommon.assertInfluencerSelection([splitField]); + }); + + it('job creation inputs the bucket span', async () => { + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.setBucketSpan(bucketSpan); + }); + + it('job creation displays the job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + }); + + it('job creation inputs the job id', async () => { + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.setJobId(jobId); + }); + + it('job creation inputs the job description', async () => { + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.setJobDescription(jobDescription); + }); + + it('job creation inputs job groups', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + for (const jobGroup of jobGroups) { + await ml.jobWizardCommon.addJobGroup(jobGroup); + } + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + }); + + it('job creation opens the advanced section', async () => { + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + }); + + it('job creation displays the model plot switch', async () => { + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + }); + + it('job creation enables the dedicated index switch', async () => { + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.activateDedicatedIndexSwitch(); + }); + + it('job creation inputs the model memory limit', async () => { + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.setModelMemoryLimit(memoryLimit); + }); + + it('job creation displays the validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + }); + + it('job creation displays the summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job creation creates the job and finishes processing', async () => { + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + }); + + it('job creation displays the created job in the job list', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobId); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobId)).to.have.length(1); + }); + + it('job creation displays details for the created job in the job list', async () => { + await ml.jobTable.assertJobRowFields(jobId, getExpectedRow(jobId, jobGroups)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobId, + getExpectedCounts(jobId), + getExpectedModelSizeStats(jobId) + ); + }); + + it('job cloning clicks the clone action and loads the multi metric wizard', async () => { + await ml.jobTable.clickCloneJobAction(jobId); + await ml.jobTypeSelection.assertMultiMetricJobWizardOpen(); + }); + + it('job cloning displays the time range step', async () => { + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + }); + + it('job cloning sets the timerange', async () => { + await ml.jobWizardCommon.clickUseFullDataButton( + 'Feb 7, 2016 @ 00:00:00.000', + 'Feb 11, 2016 @ 23:59:54.000' + ); + }); + + it('job cloning displays the event rate chart', async () => { + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + }); + + it('job cloning displays the pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + }); + + it('job cloning pre-fills detectors and shows preview with split cards', async () => { + for (const [index, aggAndFieldIdentifier] of aggAndFieldIdentifiers.entries()) { + await ml.jobWizardCommon.assertDetectorPreviewExists(aggAndFieldIdentifier, index, 'LINE'); + } + + await ml.jobWizardMultiMetric.assertDetectorSplitExists(splitField); + await ml.jobWizardMultiMetric.assertDetectorSplitFrontCardTitle('AAL'); + await ml.jobWizardMultiMetric.assertDetectorSplitNumberOfBackCards(9); + }); + + it('job cloning pre-fills the split field', async () => { + await ml.jobWizardMultiMetric.assertSplitFieldInputExists(); + await ml.jobWizardMultiMetric.assertSplitFieldSelection(splitField); + }); + + it('job cloning pre-fills influencers', async () => { + await ml.jobWizardCommon.assertInfluencerInputExists(); + await ml.jobWizardCommon.assertInfluencerSelection([splitField]); + }); + + it('job cloning pre-fills the bucket span', async () => { + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.assertBucketSpanValue(bucketSpan); + }); + + it('job cloning displays the job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + }); + + it('job cloning does not pre-fill the job id', async () => { + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.assertJobIdValue(''); + }); + + it('job cloning inputs the clone job id', async () => { + await ml.jobWizardCommon.setJobId(jobIdClone); + }); + + it('job cloning pre-fills the job description', async () => { + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.assertJobDescriptionValue(jobDescription); + }); + + it('job cloning pre-fills job groups', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + }); + + it('job cloning inputs the clone job group', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.addJobGroup('clone'); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroupsClone); + }); + + it('job cloning opens the advanced section', async () => { + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + }); + + it('job cloning pre-fills the model plot switch', async () => { + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(false); + }); + + it('job cloning pre-fills the dedicated index switch', async () => { + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.assertDedicatedIndexSwitchCheckedState(true); + }); + + it('job cloning pre-fills the model memory limit', async () => { + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.assertModelMemoryLimitValue(memoryLimit); + }); + + it('job cloning displays the validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + }); + + it('job cloning displays the summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job cloning creates the job and finishes processing', async () => { + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + }); + + it('job cloning displays the created job in the job list', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobIdClone); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobIdClone)).to.have.length(1); + }); + + it('job cloning displays details for the created job in the job list', async () => { + await ml.jobTable.assertJobRowFields(jobIdClone, getExpectedRow(jobIdClone, jobGroupsClone)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobIdClone, + getExpectedCounts(jobIdClone), + getExpectedModelSizeStats(jobIdClone) + ); }); }); } diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts index 706a3c946a261..cd88a9bba1769 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts @@ -96,314 +96,296 @@ export default function({ getService }: FtrProviderContext) { await ml.api.cleanMlIndices(); }); - describe('job creation', function() { - it('loads the job management page', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - }); - - it('loads the new job source selection page', async () => { - await ml.jobManagement.navigateToNewJobSourceSelection(); - }); - - it('loads the job type selection page', async () => { - await ml.jobSourceSelection.selectSource('ecommerce'); - }); - - it('loads the population job wizard page', async () => { - await ml.jobTypeSelection.selectPopulationJob(); - }); - - it('displays the time range step', async () => { - await ml.jobWizardCommon.assertTimeRangeSectionExists(); - }); - - it('sets the timerange', async () => { - await ml.jobWizardCommon.clickUseFullDataButton( - 'Jun 12, 2019 @ 00:04:19.000', - 'Jul 12, 2019 @ 23:45:36.000' - ); - }); - - it('displays the event rate chart', async () => { - await ml.jobWizardCommon.assertEventRateChartExists(); - await ml.jobWizardCommon.assertEventRateChartHasData(); - }); - - it('displays the pick fields step', async () => { - await ml.jobWizardCommon.advanceToPickFieldsSection(); - }); - - it('selects the population field', async () => { - await ml.jobWizardPopulation.assertPopulationFieldInputExists(); - await ml.jobWizardPopulation.selectPopulationField(populationField); - }); - - it('selects detectors and displays detector previews', async () => { - for (const [index, detector] of detectors.entries()) { - await ml.jobWizardCommon.assertAggAndFieldInputExists(); - await ml.jobWizardCommon.selectAggAndField(detector.identifier, false); - await ml.jobWizardCommon.assertDetectorPreviewExists( - detector.identifier, - index, - 'SCATTER' - ); - } - }); - - it('inputs detector split fields and displays split cards', async () => { - for (const [index, detector] of detectors.entries()) { - await ml.jobWizardPopulation.assertDetectorSplitFieldInputExists(index); - await ml.jobWizardPopulation.selectDetectorSplitField(index, detector.splitField); - - await ml.jobWizardPopulation.assertDetectorSplitExists(index); - await ml.jobWizardPopulation.assertDetectorSplitFrontCardTitle( - index, - detector.frontCardTitle - ); - await ml.jobWizardPopulation.assertDetectorSplitNumberOfBackCards( - index, - detector.numberOfBackCards - ); - } - }); - - it('displays the influencer field', async () => { - await ml.jobWizardCommon.assertInfluencerInputExists(); - await ml.jobWizardCommon.assertInfluencerSelection( - [populationField].concat(detectors.map(detector => detector.splitField)) + it('job creation loads the job management page', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + }); + + it('job creation loads the new job source selection page', async () => { + await ml.jobManagement.navigateToNewJobSourceSelection(); + }); + + it('job creation loads the job type selection page', async () => { + await ml.jobSourceSelection.selectSource('ecommerce'); + }); + + it('job creation loads the population job wizard page', async () => { + await ml.jobTypeSelection.selectPopulationJob(); + }); + + it('job creation displays the time range step', async () => { + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + }); + + it('job creation sets the timerange', async () => { + await ml.jobWizardCommon.clickUseFullDataButton( + 'Jun 12, 2019 @ 00:04:19.000', + 'Jul 12, 2019 @ 23:45:36.000' + ); + }); + + it('job creation displays the event rate chart', async () => { + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + }); + + it('job creation displays the pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + }); + + it('job creation selects the population field', async () => { + await ml.jobWizardPopulation.assertPopulationFieldInputExists(); + await ml.jobWizardPopulation.selectPopulationField(populationField); + }); + + it('job creation selects detectors and displays detector previews', async () => { + for (const [index, detector] of detectors.entries()) { + await ml.jobWizardCommon.assertAggAndFieldInputExists(); + await ml.jobWizardCommon.selectAggAndField(detector.identifier, false); + await ml.jobWizardCommon.assertDetectorPreviewExists(detector.identifier, index, 'SCATTER'); + } + }); + + it('job creation inputs detector split fields and displays split cards', async () => { + for (const [index, detector] of detectors.entries()) { + await ml.jobWizardPopulation.assertDetectorSplitFieldInputExists(index); + await ml.jobWizardPopulation.selectDetectorSplitField(index, detector.splitField); + + await ml.jobWizardPopulation.assertDetectorSplitExists(index); + await ml.jobWizardPopulation.assertDetectorSplitFrontCardTitle( + index, + detector.frontCardTitle ); - }); - - it('inputs the bucket span', async () => { - await ml.jobWizardCommon.assertBucketSpanInputExists(); - await ml.jobWizardCommon.setBucketSpan(bucketSpan); - }); - - it('displays the job details step', async () => { - await ml.jobWizardCommon.advanceToJobDetailsSection(); - }); - - it('inputs the job id', async () => { - await ml.jobWizardCommon.assertJobIdInputExists(); - await ml.jobWizardCommon.setJobId(jobId); - }); - - it('inputs the job description', async () => { - await ml.jobWizardCommon.assertJobDescriptionInputExists(); - await ml.jobWizardCommon.setJobDescription(jobDescription); - }); - - it('inputs job groups', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - for (const jobGroup of jobGroups) { - await ml.jobWizardCommon.addJobGroup(jobGroup); - } - await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); - }); - - it('opens the advanced section', async () => { - await ml.jobWizardCommon.ensureAdvancedSectionOpen(); - }); - - it('displays the model plot switch', async () => { - await ml.jobWizardCommon.assertModelPlotSwitchExists(); - }); - - it('enables the dedicated index switch', async () => { - await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); - await ml.jobWizardCommon.activateDedicatedIndexSwitch(); - }); - - it('inputs the model memory limit', async () => { - await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); - await ml.jobWizardCommon.setModelMemoryLimit(memoryLimit); - }); - - it('displays the validation step', async () => { - await ml.jobWizardCommon.advanceToValidationSection(); - }); - - it('displays the summary step', async () => { - await ml.jobWizardCommon.advanceToSummarySection(); - }); - - it('creates the job and finishes processing', async () => { - await ml.jobWizardCommon.assertCreateJobButtonExists(); - await ml.jobWizardCommon.createJobAndWaitForCompletion(); - }); - - it('displays the created job in the job list', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobId); - const rows = await ml.jobTable.parseJobTable(); - expect(rows.filter(row => row.id === jobId)).to.have.length(1); - }); - - it('displays details for the created job in the job list', async () => { - await ml.jobTable.assertJobRowFields(jobId, getExpectedRow(jobId, jobGroups)); - - await ml.jobTable.assertJobRowDetailsCounts( - jobId, - getExpectedCounts(jobId), - getExpectedModelSizeStats(jobId) + await ml.jobWizardPopulation.assertDetectorSplitNumberOfBackCards( + index, + detector.numberOfBackCards ); - }); + } }); - describe('job cloning', function() { - it('clicks the clone action and loads the population wizard', async () => { - await ml.jobTable.clickCloneJobAction(jobId); - await ml.jobTypeSelection.assertPopulationJobWizardOpen(); - }); + it('job creation displays the influencer field', async () => { + await ml.jobWizardCommon.assertInfluencerInputExists(); + await ml.jobWizardCommon.assertInfluencerSelection( + [populationField].concat(detectors.map(detector => detector.splitField)) + ); + }); - it('displays the time range step', async () => { - await ml.jobWizardCommon.assertTimeRangeSectionExists(); - }); + it('job creation inputs the bucket span', async () => { + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.setBucketSpan(bucketSpan); + }); - it('sets the timerange', async () => { - await ml.jobWizardCommon.clickUseFullDataButton( - 'Jun 12, 2019 @ 00:04:19.000', - 'Jul 12, 2019 @ 23:45:36.000' - ); - }); - - it('displays the event rate chart', async () => { - await ml.jobWizardCommon.assertEventRateChartExists(); - await ml.jobWizardCommon.assertEventRateChartHasData(); - }); - - it('displays the pick fields step', async () => { - await ml.jobWizardCommon.advanceToPickFieldsSection(); - }); - - it('pre-fills the population field', async () => { - await ml.jobWizardPopulation.assertPopulationFieldInputExists(); - await ml.jobWizardPopulation.assertPopulationFieldSelection(populationField); - }); - - it('pre-fills detectors and shows preview with split cards', async () => { - for (const [index, detector] of detectors.entries()) { - await ml.jobWizardCommon.assertDetectorPreviewExists( - detector.identifier, - index, - 'SCATTER' - ); - - await ml.jobWizardPopulation.assertDetectorSplitFieldSelection( - index, - detector.splitField - ); - await ml.jobWizardPopulation.assertDetectorSplitExists(index); - await ml.jobWizardPopulation.assertDetectorSplitFrontCardTitle( - index, - detector.frontCardTitle - ); - await ml.jobWizardPopulation.assertDetectorSplitNumberOfBackCards( - index, - detector.numberOfBackCards - ); - } - }); - - it('pre-fills influencers', async () => { - await ml.jobWizardCommon.assertInfluencerInputExists(); - await ml.jobWizardCommon.assertInfluencerSelection( - [populationField].concat(detectors.map(detector => detector.splitField)) + it('job creation displays the job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + }); + + it('job creation inputs the job id', async () => { + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.setJobId(jobId); + }); + + it('job creation inputs the job description', async () => { + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.setJobDescription(jobDescription); + }); + + it('job creation inputs job groups', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + for (const jobGroup of jobGroups) { + await ml.jobWizardCommon.addJobGroup(jobGroup); + } + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + }); + + it('job creation opens the advanced section', async () => { + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + }); + + it('job creation displays the model plot switch', async () => { + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + }); + + it('job creation enables the dedicated index switch', async () => { + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.activateDedicatedIndexSwitch(); + }); + + it('job creation inputs the model memory limit', async () => { + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.setModelMemoryLimit(memoryLimit); + }); + + it('job creation displays the validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + }); + + it('job creation displays the summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job creation creates the job and finishes processing', async () => { + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + }); + + it('job creation displays the created job in the job list', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobId); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobId)).to.have.length(1); + }); + + it('job creation displays details for the created job in the job list', async () => { + await ml.jobTable.assertJobRowFields(jobId, getExpectedRow(jobId, jobGroups)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobId, + getExpectedCounts(jobId), + getExpectedModelSizeStats(jobId) + ); + }); + + it('job cloning clicks the clone action and loads the population wizard', async () => { + await ml.jobTable.clickCloneJobAction(jobId); + await ml.jobTypeSelection.assertPopulationJobWizardOpen(); + }); + + it('job cloning displays the time range step', async () => { + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + }); + + it('job cloning sets the timerange', async () => { + await ml.jobWizardCommon.clickUseFullDataButton( + 'Jun 12, 2019 @ 00:04:19.000', + 'Jul 12, 2019 @ 23:45:36.000' + ); + }); + + it('job cloning displays the event rate chart', async () => { + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + }); + + it('job cloning displays the pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + }); + + it('job cloning pre-fills the population field', async () => { + await ml.jobWizardPopulation.assertPopulationFieldInputExists(); + await ml.jobWizardPopulation.assertPopulationFieldSelection(populationField); + }); + + it('job cloning pre-fills detectors and shows preview with split cards', async () => { + for (const [index, detector] of detectors.entries()) { + await ml.jobWizardCommon.assertDetectorPreviewExists(detector.identifier, index, 'SCATTER'); + + await ml.jobWizardPopulation.assertDetectorSplitFieldSelection(index, detector.splitField); + await ml.jobWizardPopulation.assertDetectorSplitExists(index); + await ml.jobWizardPopulation.assertDetectorSplitFrontCardTitle( + index, + detector.frontCardTitle ); - }); - - it('pre-fills the bucket span', async () => { - await ml.jobWizardCommon.assertBucketSpanInputExists(); - await ml.jobWizardCommon.assertBucketSpanValue(bucketSpan); - }); - - it('displays the job details step', async () => { - await ml.jobWizardCommon.advanceToJobDetailsSection(); - }); - - it('does not pre-fill the job id', async () => { - await ml.jobWizardCommon.assertJobIdInputExists(); - await ml.jobWizardCommon.assertJobIdValue(''); - }); - - it('inputs the clone job id', async () => { - await ml.jobWizardCommon.setJobId(jobIdClone); - }); - - it('pre-fills the job description', async () => { - await ml.jobWizardCommon.assertJobDescriptionInputExists(); - await ml.jobWizardCommon.assertJobDescriptionValue(jobDescription); - }); - - it('pre-fills job groups', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); - }); - - it('inputs the clone job group', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - await ml.jobWizardCommon.addJobGroup('clone'); - await ml.jobWizardCommon.assertJobGroupSelection(jobGroupsClone); - }); - - it('opens the advanced section', async () => { - await ml.jobWizardCommon.ensureAdvancedSectionOpen(); - }); - - it('pre-fills the model plot switch', async () => { - await ml.jobWizardCommon.assertModelPlotSwitchExists(); - await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(false); - }); - - it('pre-fills the dedicated index switch', async () => { - await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); - await ml.jobWizardCommon.assertDedicatedIndexSwitchCheckedState(true); - }); - - it('pre-fills the model memory limit', async () => { - await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); - await ml.jobWizardCommon.assertModelMemoryLimitValue(memoryLimit); - }); - - it('displays the validation step', async () => { - await ml.jobWizardCommon.advanceToValidationSection(); - }); - - it('displays the summary step', async () => { - await ml.jobWizardCommon.advanceToSummarySection(); - }); - - it('creates the job and finishes processing', async () => { - await ml.jobWizardCommon.assertCreateJobButtonExists(); - await ml.jobWizardCommon.createJobAndWaitForCompletion(); - }); - - it('displays the created job in the job list', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobIdClone); - const rows = await ml.jobTable.parseJobTable(); - expect(rows.filter(row => row.id === jobIdClone)).to.have.length(1); - }); - - it('displays details for the created job in the job list', async () => { - await ml.jobTable.assertJobRowFields( - jobIdClone, - getExpectedRow(jobIdClone, jobGroupsClone) + await ml.jobWizardPopulation.assertDetectorSplitNumberOfBackCards( + index, + detector.numberOfBackCards ); + } + }); - await ml.jobTable.assertJobRowDetailsCounts( - jobIdClone, - getExpectedCounts(jobIdClone), - getExpectedModelSizeStats(jobIdClone) - ); - }); + it('job cloning pre-fills influencers', async () => { + await ml.jobWizardCommon.assertInfluencerInputExists(); + await ml.jobWizardCommon.assertInfluencerSelection( + [populationField].concat(detectors.map(detector => detector.splitField)) + ); + }); + + it('job cloning pre-fills the bucket span', async () => { + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.assertBucketSpanValue(bucketSpan); + }); + + it('job cloning displays the job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + }); + + it('job cloning does not pre-fill the job id', async () => { + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.assertJobIdValue(''); + }); + + it('job cloning inputs the clone job id', async () => { + await ml.jobWizardCommon.setJobId(jobIdClone); + }); + + it('job cloning pre-fills the job description', async () => { + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.assertJobDescriptionValue(jobDescription); + }); + + it('job cloning pre-fills job groups', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + }); + + it('job cloning inputs the clone job group', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.addJobGroup('clone'); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroupsClone); + }); + + it('job cloning opens the advanced section', async () => { + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + }); + + it('job cloning pre-fills the model plot switch', async () => { + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(false); + }); + + it('job cloning pre-fills the dedicated index switch', async () => { + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.assertDedicatedIndexSwitchCheckedState(true); + }); + + it('job cloning pre-fills the model memory limit', async () => { + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.assertModelMemoryLimitValue(memoryLimit); + }); + + it('job cloning displays the validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + }); + + it('job cloning displays the summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job cloning creates the job and finishes processing', async () => { + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + }); + + it('job cloning displays the created job in the job list', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobIdClone); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobIdClone)).to.have.length(1); + }); + + it('job cloning displays details for the created job in the job list', async () => { + await ml.jobTable.assertJobRowFields(jobIdClone, getExpectedRow(jobIdClone, jobGroupsClone)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobIdClone, + getExpectedCounts(jobIdClone), + getExpectedModelSizeStats(jobIdClone) + ); }); }); } diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts index 9591cdd3ff561..2cca37a944563 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts @@ -283,45 +283,45 @@ export default function({ getService }: FtrProviderContext) { }); for (const testData of testDataList) { - describe(`job creation ${testData.suiteTitle}`, function() { - it('loads the job management page', async () => { + describe(` ${testData.suiteTitle}`, function() { + it('job creation loads the job management page', async () => { await ml.navigation.navigateToMl(); await ml.navigation.navigateToJobManagement(); }); - it('loads the new job source selection page', async () => { + it('job creation loads the new job source selection page', async () => { await ml.jobManagement.navigateToNewJobSourceSelection(); }); - it('loads the job type selection page', async () => { + it('job creation loads the job type selection page', async () => { await ml.jobSourceSelection.selectSource(testData.jobSource); }); - it('loads the multi metric job wizard page', async () => { + it('job creation loads the multi metric job wizard page', async () => { await ml.jobTypeSelection.selectMultiMetricJob(); }); - it('displays the time range step', async () => { + it('job creation displays the time range step', async () => { await ml.jobWizardCommon.assertTimeRangeSectionExists(); }); - it('sets the timerange', async () => { + it('job creation sets the timerange', async () => { await ml.jobWizardCommon.clickUseFullDataButton( 'Feb 7, 2016 @ 00:00:00.000', 'Feb 11, 2016 @ 23:59:54.000' ); }); - it('displays the event rate chart', async () => { + it('job creation displays the event rate chart', async () => { await ml.jobWizardCommon.assertEventRateChartExists(); await ml.jobWizardCommon.assertEventRateChartHasData(); }); - it('displays the pick fields step', async () => { + it('job creation displays the pick fields step', async () => { await ml.jobWizardCommon.advanceToPickFieldsSection(); }); - it('selects detectors and displays detector previews', async () => { + it('job creation selects detectors and displays detector previews', async () => { for (const [index, aggAndFieldIdentifier] of testData.aggAndFieldIdentifiers.entries()) { await ml.jobWizardCommon.assertAggAndFieldInputExists(); await ml.jobWizardCommon.selectAggAndField(aggAndFieldIdentifier, false); @@ -333,7 +333,7 @@ export default function({ getService }: FtrProviderContext) { } }); - it('inputs the split field and displays split cards', async () => { + it('job creation inputs the split field and displays split cards', async () => { await ml.jobWizardMultiMetric.assertSplitFieldInputExists(); await ml.jobWizardMultiMetric.selectSplitField(testData.splitField); @@ -348,31 +348,31 @@ export default function({ getService }: FtrProviderContext) { await ml.jobWizardCommon.assertInfluencerSelection([testData.splitField]); }); - it('displays the influencer field', async () => { + it('job creation displays the influencer field', async () => { await ml.jobWizardCommon.assertInfluencerInputExists(); await ml.jobWizardCommon.assertInfluencerSelection([testData.splitField]); }); - it('inputs the bucket span', async () => { + it('job creation inputs the bucket span', async () => { await ml.jobWizardCommon.assertBucketSpanInputExists(); await ml.jobWizardCommon.setBucketSpan(testData.bucketSpan); }); - it('displays the job details step', async () => { + it('job creation displays the job details step', async () => { await ml.jobWizardCommon.advanceToJobDetailsSection(); }); - it('inputs the job id', async () => { + it('job creation inputs the job id', async () => { await ml.jobWizardCommon.assertJobIdInputExists(); await ml.jobWizardCommon.setJobId(testData.jobId); }); - it('inputs the job description', async () => { + it('job creation inputs the job description', async () => { await ml.jobWizardCommon.assertJobDescriptionInputExists(); await ml.jobWizardCommon.setJobDescription(testData.jobDescription); }); - it('inputs job groups', async () => { + it('job creation inputs job groups', async () => { await ml.jobWizardCommon.assertJobGroupInputExists(); for (const jobGroup of testData.jobGroups) { await ml.jobWizardCommon.addJobGroup(jobGroup); @@ -380,38 +380,38 @@ export default function({ getService }: FtrProviderContext) { await ml.jobWizardCommon.assertJobGroupSelection(testData.jobGroups); }); - it('opens the advanced section', async () => { + it('job creation opens the advanced section', async () => { await ml.jobWizardCommon.ensureAdvancedSectionOpen(); }); - it('displays the model plot switch', async () => { + it('job creation displays the model plot switch', async () => { await ml.jobWizardCommon.assertModelPlotSwitchExists(); }); - it('enables the dedicated index switch', async () => { + it('job creation enables the dedicated index switch', async () => { await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); await ml.jobWizardCommon.activateDedicatedIndexSwitch(); }); - it('inputs the model memory limit', async () => { + it('job creation inputs the model memory limit', async () => { await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); await ml.jobWizardCommon.setModelMemoryLimit(testData.memoryLimit); }); - it('displays the validation step', async () => { + it('job creation displays the validation step', async () => { await ml.jobWizardCommon.advanceToValidationSection(); }); - it('displays the summary step', async () => { + it('job creation displays the summary step', async () => { await ml.jobWizardCommon.advanceToSummarySection(); }); - it('creates the job and finishes processing', async () => { + it('job creation creates the job and finishes processing', async () => { await ml.jobWizardCommon.assertCreateJobButtonExists(); await ml.jobWizardCommon.createJobAndWaitForCompletion(); }); - it('displays the created job in the job list', async () => { + it('job creation displays the created job in the job list', async () => { await ml.navigation.navigateToMl(); await ml.navigation.navigateToJobManagement(); @@ -421,7 +421,7 @@ export default function({ getService }: FtrProviderContext) { expect(rows.filter(row => row.id === testData.jobId)).to.have.length(1); }); - it('displays details for the created job in the job list', async () => { + it('job creation displays details for the created job in the job list', async () => { await ml.jobTable.assertJobRowFields(testData.jobId, { id: testData.jobId, description: testData.jobDescription, diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts index 7da395d42ffdc..6e640f7d173d5 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts @@ -81,274 +81,265 @@ export default function({ getService }: FtrProviderContext) { await ml.api.cleanMlIndices(); }); - describe('job creation', function() { - it('loads the job management page', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - }); - - it('loads the new job source selection page', async () => { - await ml.jobManagement.navigateToNewJobSourceSelection(); - }); - - it('loads the job type selection page', async () => { - await ml.jobSourceSelection.selectSource('farequote'); - }); - - it('loads the single metric job wizard page', async () => { - await ml.jobTypeSelection.selectSingleMetricJob(); - }); - - it('displays the time range step', async () => { - await ml.jobWizardCommon.assertTimeRangeSectionExists(); - }); - - it('sets the timerange', async () => { - await ml.jobWizardCommon.clickUseFullDataButton( - 'Feb 7, 2016 @ 00:00:00.000', - 'Feb 11, 2016 @ 23:59:54.000' - ); - }); - - it('displays the event rate chart', async () => { - await ml.jobWizardCommon.assertEventRateChartExists(); - await ml.jobWizardCommon.assertEventRateChartHasData(); - }); - - it('displays the pick fields step', async () => { - await ml.jobWizardCommon.advanceToPickFieldsSection(); - }); - - it('selects field and aggregation', async () => { - await ml.jobWizardCommon.assertAggAndFieldInputExists(); - await ml.jobWizardCommon.selectAggAndField(aggAndFieldIdentifier, true); - await ml.jobWizardCommon.assertAnomalyChartExists('LINE'); - }); - - it('inputs the bucket span', async () => { - await ml.jobWizardCommon.assertBucketSpanInputExists(); - await ml.jobWizardCommon.setBucketSpan(bucketSpan); - }); - - it('displays the job details step', async () => { - await ml.jobWizardCommon.advanceToJobDetailsSection(); - }); - - it('inputs the job id', async () => { - await ml.jobWizardCommon.assertJobIdInputExists(); - await ml.jobWizardCommon.setJobId(jobId); - }); - - it('inputs the job description', async () => { - await ml.jobWizardCommon.assertJobDescriptionInputExists(); - await ml.jobWizardCommon.setJobDescription(jobDescription); - }); - - it('inputs job groups', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - for (const jobGroup of jobGroups) { - await ml.jobWizardCommon.addJobGroup(jobGroup); - } - await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); - }); - - it('opens the advanced section', async () => { - await ml.jobWizardCommon.ensureAdvancedSectionOpen(); - }); - - it('displays the model plot switch', async () => { - await ml.jobWizardCommon.assertModelPlotSwitchExists(); - }); - - it('enables the dedicated index switch', async () => { - await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); - await ml.jobWizardCommon.activateDedicatedIndexSwitch(); - }); - - it('inputs the model memory limit', async () => { - await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); - await ml.jobWizardCommon.setModelMemoryLimit(memoryLimit); - }); - - it('displays the validation step', async () => { - await ml.jobWizardCommon.advanceToValidationSection(); - }); - - it('displays the summary step', async () => { - await ml.jobWizardCommon.advanceToSummarySection(); - }); - - it('creates the job and finishes processing', async () => { - await ml.jobWizardCommon.assertCreateJobButtonExists(); - await ml.jobWizardCommon.createJobAndWaitForCompletion(); - }); - - it('displays the created job in the job list', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobId); - const rows = await ml.jobTable.parseJobTable(); - expect(rows.filter(row => row.id === jobId)).to.have.length(1); - }); - - it('displays details for the created job in the job list', async () => { - await ml.jobTable.assertJobRowFields(jobId, getExpectedRow(jobId, jobGroups)); - - await ml.jobTable.assertJobRowDetailsCounts( - jobId, - getExpectedCounts(jobId), - getExpectedModelSizeStats(jobId) - ); - }); - }); - - describe('job cloning', function() { - it('clicks the clone action and loads the single metric wizard', async () => { - await ml.jobTable.clickCloneJobAction(jobId); - await ml.jobTypeSelection.assertSingleMetricJobWizardOpen(); - }); - - it('displays the time range step', async () => { - await ml.jobWizardCommon.assertTimeRangeSectionExists(); - }); - - it('sets the timerange', async () => { - await ml.jobWizardCommon.clickUseFullDataButton( - 'Feb 7, 2016 @ 00:00:00.000', - 'Feb 11, 2016 @ 23:59:54.000' - ); - }); - - it('displays the event rate chart', async () => { - await ml.jobWizardCommon.assertEventRateChartExists(); - await ml.jobWizardCommon.assertEventRateChartHasData(); - }); - - it('displays the pick fields step', async () => { - await ml.jobWizardCommon.advanceToPickFieldsSection(); - }); - - it('pre-fills field and aggregation', async () => { - await ml.jobWizardCommon.assertAggAndFieldInputExists(); - await ml.jobWizardCommon.assertAggAndFieldSelection([aggAndFieldIdentifier]); - await ml.jobWizardCommon.assertAnomalyChartExists('LINE'); - }); - - it('pre-fills the bucket span', async () => { - await ml.jobWizardCommon.assertBucketSpanInputExists(); - await ml.jobWizardCommon.assertBucketSpanValue(bucketSpan); - }); - - it('displays the job details step', async () => { - await ml.jobWizardCommon.advanceToJobDetailsSection(); - }); - - it('does not pre-fill the job id', async () => { - await ml.jobWizardCommon.assertJobIdInputExists(); - await ml.jobWizardCommon.assertJobIdValue(''); - }); - - it('inputs the clone job id', async () => { - await ml.jobWizardCommon.setJobId(jobIdClone); - }); - - it('pre-fills the job description', async () => { - await ml.jobWizardCommon.assertJobDescriptionInputExists(); - await ml.jobWizardCommon.assertJobDescriptionValue(jobDescription); - }); - - it('pre-fills job groups', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); - }); - - it('inputs the clone job group', async () => { - await ml.jobWizardCommon.assertJobGroupInputExists(); - await ml.jobWizardCommon.addJobGroup('clone'); - await ml.jobWizardCommon.assertJobGroupSelection(jobGroupsClone); - }); - - it('opens the advanced section', async () => { - await ml.jobWizardCommon.ensureAdvancedSectionOpen(); - }); - - it('pre-fills the model plot switch', async () => { - await ml.jobWizardCommon.assertModelPlotSwitchExists(); - await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(true); - }); - - it('pre-fills the dedicated index switch', async () => { - await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); - await ml.jobWizardCommon.assertDedicatedIndexSwitchCheckedState(true); - }); - - it('pre-fills the model memory limit', async () => { - await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); - await ml.jobWizardCommon.assertModelMemoryLimitValue(memoryLimit); - }); - - it('displays the validation step', async () => { - await ml.jobWizardCommon.advanceToValidationSection(); - }); - - it('displays the summary step', async () => { - await ml.jobWizardCommon.advanceToSummarySection(); - }); - - it('creates the job and finishes processing', async () => { - await ml.jobWizardCommon.assertCreateJobButtonExists(); - await ml.jobWizardCommon.createJobAndWaitForCompletion(); - }); - - it('displays the created job in the job list', async () => { - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobIdClone); - const rows = await ml.jobTable.parseJobTable(); - expect(rows.filter(row => row.id === jobIdClone)).to.have.length(1); - }); - - it('displays details for the created job in the job list', async () => { - await ml.jobTable.assertJobRowFields( - jobIdClone, - getExpectedRow(jobIdClone, jobGroupsClone) - ); - - await ml.jobTable.assertJobRowDetailsCounts( - jobIdClone, - getExpectedCounts(jobIdClone), - getExpectedModelSizeStats(jobIdClone) - ); - }); - }); - - describe('job deletion', function() { - it('has results for the job before deletion', async () => { - await ml.api.assertJobResultsExist(jobIdClone); - }); - - it('triggers the delete action', async () => { - await ml.jobTable.clickDeleteJobAction(jobIdClone); - }); - - it('confirms the delete modal', async () => { - await ml.jobTable.confirmDeleteJobModal(); - }); - - it('does not display the deleted job in the job list any more', async () => { - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobIdClone); - const rows = await ml.jobTable.parseJobTable(); - expect(rows.filter(row => row.id === jobIdClone)).to.have.length(0); - }); - - it('does not have results for the deleted job any more', async () => { - await ml.api.assertNoJobResultsExist(jobIdClone); - }); + it('job creation loads the job management page', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + }); + + it('job creation loads the new job source selection page', async () => { + await ml.jobManagement.navigateToNewJobSourceSelection(); + }); + + it('job creation loads the job type selection page', async () => { + await ml.jobSourceSelection.selectSource('farequote'); + }); + + it('job creation loads the single metric job wizard page', async () => { + await ml.jobTypeSelection.selectSingleMetricJob(); + }); + + it('job creation displays the time range step', async () => { + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + }); + + it('job creation sets the timerange', async () => { + await ml.jobWizardCommon.clickUseFullDataButton( + 'Feb 7, 2016 @ 00:00:00.000', + 'Feb 11, 2016 @ 23:59:54.000' + ); + }); + + it('job creation displays the event rate chart', async () => { + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + }); + + it('job creation displays the pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + }); + + it('job creation selects field and aggregation', async () => { + await ml.jobWizardCommon.assertAggAndFieldInputExists(); + await ml.jobWizardCommon.selectAggAndField(aggAndFieldIdentifier, true); + await ml.jobWizardCommon.assertAnomalyChartExists('LINE'); + }); + + it('job creation inputs the bucket span', async () => { + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.setBucketSpan(bucketSpan); + }); + + it('job creation displays the job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + }); + + it('job creation inputs the job id', async () => { + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.setJobId(jobId); + }); + + it('job creation inputs the job description', async () => { + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.setJobDescription(jobDescription); + }); + + it('job creation inputs job groups', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + for (const jobGroup of jobGroups) { + await ml.jobWizardCommon.addJobGroup(jobGroup); + } + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + }); + + it('job creation opens the advanced section', async () => { + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + }); + + it('job creation displays the model plot switch', async () => { + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + }); + + it('job creation enables the dedicated index switch', async () => { + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.activateDedicatedIndexSwitch(); + }); + + it('job creation inputs the model memory limit', async () => { + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.setModelMemoryLimit(memoryLimit); + }); + + it('job creation displays the validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + }); + + it('job creation displays the summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job creation creates the job and finishes processing', async () => { + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + }); + + it('job creation displays the created job in the job list', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobId); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobId)).to.have.length(1); + }); + + it('job creation displays details for the created job in the job list', async () => { + await ml.jobTable.assertJobRowFields(jobId, getExpectedRow(jobId, jobGroups)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobId, + getExpectedCounts(jobId), + getExpectedModelSizeStats(jobId) + ); + }); + + it('job cloning clicks the clone action and loads the single metric wizard', async () => { + await ml.jobTable.clickCloneJobAction(jobId); + await ml.jobTypeSelection.assertSingleMetricJobWizardOpen(); + }); + + it('job cloning displays the time range step', async () => { + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + }); + + it('job cloning sets the timerange', async () => { + await ml.jobWizardCommon.clickUseFullDataButton( + 'Feb 7, 2016 @ 00:00:00.000', + 'Feb 11, 2016 @ 23:59:54.000' + ); + }); + + it('job cloning displays the event rate chart', async () => { + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + }); + + it('job cloning displays the pick fields step', async () => { + await ml.jobWizardCommon.advanceToPickFieldsSection(); + }); + + it('job cloning pre-fills field and aggregation', async () => { + await ml.jobWizardCommon.assertAggAndFieldInputExists(); + await ml.jobWizardCommon.assertAggAndFieldSelection([aggAndFieldIdentifier]); + await ml.jobWizardCommon.assertAnomalyChartExists('LINE'); + }); + + it('job cloning pre-fills the bucket span', async () => { + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.assertBucketSpanValue(bucketSpan); + }); + + it('job cloning displays the job details step', async () => { + await ml.jobWizardCommon.advanceToJobDetailsSection(); + }); + + it('job cloning does not pre-fill the job id', async () => { + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.assertJobIdValue(''); + }); + + it('job cloning inputs the clone job id', async () => { + await ml.jobWizardCommon.setJobId(jobIdClone); + }); + + it('job cloning pre-fills the job description', async () => { + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.assertJobDescriptionValue(jobDescription); + }); + + it('job cloning pre-fills job groups', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + }); + + it('job cloning inputs the clone job group', async () => { + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.addJobGroup('clone'); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroupsClone); + }); + + it('job cloning opens the advanced section', async () => { + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + }); + + it('job cloning pre-fills the model plot switch', async () => { + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(true); + }); + + it('job cloning pre-fills the dedicated index switch', async () => { + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.assertDedicatedIndexSwitchCheckedState(true); + }); + + it('job cloning pre-fills the model memory limit', async () => { + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.assertModelMemoryLimitValue(memoryLimit); + }); + + it('job cloning displays the validation step', async () => { + await ml.jobWizardCommon.advanceToValidationSection(); + }); + + it('job cloning displays the summary step', async () => { + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job cloning creates the job and finishes processing', async () => { + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + }); + + it('job cloning displays the created job in the job list', async () => { + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobIdClone); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobIdClone)).to.have.length(1); + }); + + it('job cloning displays details for the created job in the job list', async () => { + await ml.jobTable.assertJobRowFields(jobIdClone, getExpectedRow(jobIdClone, jobGroupsClone)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobIdClone, + getExpectedCounts(jobIdClone), + getExpectedModelSizeStats(jobIdClone) + ); + }); + + it('job deletion has results for the job before deletion', async () => { + await ml.api.assertJobResultsExist(jobIdClone); + }); + + it('job deletion triggers the delete action', async () => { + await ml.jobTable.clickDeleteJobAction(jobIdClone); + }); + + it('job deletion confirms the delete modal', async () => { + await ml.jobTable.confirmDeleteJobModal(); + }); + + it('job deletion does not display the deleted job in the job list any more', async () => { + await ml.jobTable.waitForJobsToLoad(); + await ml.jobTable.filterWithSearchString(jobIdClone); + const rows = await ml.jobTable.parseJobTable(); + expect(rows.filter(row => row.id === jobIdClone)).to.have.length(0); + }); + + it('job deletion does not have results for the deleted job any more', async () => { + await ml.api.assertNoJobResultsExist(jobIdClone); }); }); } From 8a529f11ab42ac29f8199058d6164c27b1d6ae9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20Zolt=C3=A1n=20Szab=C3=B3?= Date: Thu, 24 Oct 2019 14:39:29 +0200 Subject: [PATCH 116/191] [DOCS] Adds list of privileges to file data viz (#49156) --- docs/user/ml/index.asciidoc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/user/ml/index.asciidoc b/docs/user/ml/index.asciidoc index f4802592f0e07..a5f14ed2cf944 100644 --- a/docs/user/ml/index.asciidoc +++ b/docs/user/ml/index.asciidoc @@ -18,7 +18,16 @@ image::user/ml/images/ml-data-visualizer-sample.jpg[Data Visualizer for sample f experimental[] You can also upload a CSV, NDJSON, or log file (up to 100 MB in size). The *Data Visualizer* identifies the file format and field mappings. You -can then optionally import that data into an {es} index. +can then optionally import that data into an {es} index. + +You need the following permissions to use the Data Visualizer with file upload: + +* cluster privileges: `monitor`, `manage_index_pipelines` +* index privileges: `read`, `manage`, `index` + +For more information, see {ref}/security-privileges.html[Security privileges] +and {ref}/built-in-roles.html[Built-in roles]. + [float] [[xpack-ml-anomalies]] From d045cc35b740f7f5b779f000d4682dd4f901c2a1 Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Thu, 24 Oct 2019 06:23:32 -0700 Subject: [PATCH 117/191] Removing unused lodash per-method packages (#49131) --- x-pack/package.json | 4 ---- yarn.lock | 20 -------------------- 2 files changed, 24 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index bb77508f769b2..f58496361b482 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -284,11 +284,7 @@ "jsts": "^1.6.2", "lodash": "npm:@elastic/lodash@3.10.1-kibana3", "lodash.keyby": "^4.6.0", - "lodash.lowercase": "^4.3.0", "lodash.mean": "^4.1.0", - "lodash.omitby": "^4.6.0", - "lodash.orderby": "4.6.0", - "lodash.pickby": "^4.6.0", "lodash.topath": "^4.5.2", "lodash.uniqby": "^4.7.0", "lz-string": "^1.4.4", diff --git a/yarn.lock b/yarn.lock index 2513a0d34ed2a..744ea2c22a44a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18361,11 +18361,6 @@ lodash.keyby@^4.6.0: resolved "https://registry.yarnpkg.com/lodash.keyby/-/lodash.keyby-4.6.0.tgz#7f6a1abda93fd24e22728a4d361ed8bcba5a4354" integrity sha1-f2oavak/0k4icopNNh7YvLpaQ1Q= -lodash.lowercase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz#46515aced4acb0b7093133333af068e4c3b14e9d" - integrity sha1-RlFaztSssLcJMTMzOvBo5MOxTp0= - lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" @@ -18396,21 +18391,11 @@ lodash.omit@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" integrity sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA= -lodash.omitby@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.omitby/-/lodash.omitby-4.6.0.tgz#5c15ff4754ad555016b53c041311e8f079204791" - integrity sha1-XBX/R1StVVAWtTwEExHo8HkgR5E= - lodash.once@^4.0.0, lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= -lodash.orderby@4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.orderby/-/lodash.orderby-4.6.0.tgz#e697f04ce5d78522f54d9338b32b81a3393e4eb3" - integrity sha1-5pfwTOXXhSL1TZM4syuBozk+TrM= - lodash.pad@^4.1.0: version "4.5.1" resolved "https://registry.yarnpkg.com/lodash.pad/-/lodash.pad-4.5.1.tgz#4330949a833a7c8da22cc20f6a26c4d59debba70" @@ -18436,11 +18421,6 @@ lodash.pick@^4.2.1, lodash.pick@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= -lodash.pickby@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" - integrity sha1-feoh2MGNdwOifHBMFdO4SmfjOv8= - lodash.reduce@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" From a859577b40ff1da48f19651657df467b3703e135 Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 24 Oct 2019 06:29:43 -0700 Subject: [PATCH 118/191] Remove rimraf (#48985) * Update dependency del to v5 * unify del/rimraf usage with del v5 * update yarn.lock * update kbn-pm distributable * remove poorly transformed code * force some deletes from tmp * mock less of the fs module * force tmp deletion in a few more suites * please make this the last force --- package.json | 4 +- packages/kbn-es-query/package.json | 2 +- packages/kbn-es/package.json | 2 +- packages/kbn-i18n/package.json | 2 +- packages/kbn-interpreter/package.json | 2 +- packages/kbn-plugin-helpers/package.json | 2 +- packages/kbn-pm/dist/index.js | 12208 +++++++++++++--- packages/kbn-pm/package.json | 2 +- packages/kbn-pm/src/utils/projects.test.ts | 8 +- packages/kbn-test/package.json | 2 +- packages/kbn-utility-types/package.json | 3 +- renovate.json5 | 8 - .../reload_logging_config.test.js | 4 +- src/cli_plugin/install/cleanup.js | 8 +- src/cli_plugin/install/cleanup.test.js | 26 +- src/cli_plugin/install/download.test.js | 6 +- src/cli_plugin/install/install.js | 4 +- src/cli_plugin/install/kibana.test.js | 22 +- src/cli_plugin/install/pack.test.js | 6 +- src/cli_plugin/install/zip.test.js | 4 +- src/cli_plugin/list/list.test.js | 6 +- src/cli_plugin/remove/remove.js | 4 +- src/cli_plugin/remove/remove.test.js | 6 +- .../dynamic_dll_plugin/dll_compiler.js | 5 +- tasks/docker_docs.js | 4 +- .../code/server/__tests__/clone_worker.ts | 12 +- .../code/server/__tests__/commit_indexer.ts | 12 +- .../code/server/__tests__/git_operations.ts | 4 +- .../__tests__/lsp_incremental_indexer.ts | 12 +- .../code/server/__tests__/lsp_indexer.ts | 22 +- .../server/__tests__/repository_service.ts | 5 +- .../server/__tests__/workspace_handler.ts | 4 +- .../code/server/lsp/controller.test.ts | 4 +- .../code/server/lsp/install_manager.test.ts | 4 +- .../code/server/lsp/request_expander.test.ts | 8 +- .../code/server/lsp/test_repo_manager.ts | 21 +- .../code/server/lsp/workspace_handler.test.ts | 4 +- .../legacy/plugins/code/server/test_utils.ts | 23 +- .../browsers/chromium/driver_factory/index.ts | 10 +- .../server/browsers/download/clean.ts | 5 +- x-pack/package.json | 4 +- yarn.lock | 18 +- 42 files changed, 9902 insertions(+), 2620 deletions(-) diff --git a/package.json b/package.json index a0a98e0f75b04..63f780fe21da1 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "custom-event-polyfill": "^0.3.0", "d3": "3.5.17", "d3-cloud": "1.2.5", - "del": "^4.1.1", + "del": "^5.1.0", "elasticsearch": "^16.4.0", "elasticsearch-browser": "^16.4.0", "encode-uri-query": "1.0.1", @@ -233,7 +233,6 @@ "request": "^2.88.0", "reselect": "^3.0.1", "resize-observer-polyfill": "^1.5.0", - "rimraf": "2.7.1", "rison-node": "1.0.2", "rxjs": "^6.2.1", "script-loader": "0.7.2", @@ -341,7 +340,6 @@ "@types/redux": "^3.6.31", "@types/redux-actions": "^2.2.1", "@types/request": "^2.48.2", - "@types/rimraf": "^2.0.2", "@types/selenium-webdriver": "^4.0.3", "@types/semver": "^5.5.0", "@types/sinon": "^7.0.13", diff --git a/packages/kbn-es-query/package.json b/packages/kbn-es-query/package.json index 5ef1b6e125413..beeaa258a06f2 100644 --- a/packages/kbn-es-query/package.json +++ b/packages/kbn-es-query/package.json @@ -21,7 +21,7 @@ "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@kbn/expect": "1.0.0", - "del": "^4.1.1", + "del": "^5.1.0", "getopts": "^2.2.4", "supports-color": "^7.0.0" } diff --git a/packages/kbn-es/package.json b/packages/kbn-es/package.json index cf98f6062dddc..cb501dab3ddb7 100644 --- a/packages/kbn-es/package.json +++ b/packages/kbn-es/package.json @@ -10,7 +10,7 @@ "abort-controller": "^2.0.3", "chalk": "^2.4.2", "dedent": "^0.7.0", - "del": "^4.1.1", + "del": "^5.1.0", "execa": "^3.2.0", "getopts": "^2.2.4", "glob": "^7.1.2", diff --git a/packages/kbn-i18n/package.json b/packages/kbn-i18n/package.json index dff8a3f2f4b78..8a88626bffbe8 100644 --- a/packages/kbn-i18n/package.json +++ b/packages/kbn-i18n/package.json @@ -18,7 +18,7 @@ "@kbn/dev-utils": "1.0.0", "@types/intl-relativeformat": "^2.1.0", "@types/react-intl": "^2.3.15", - "del": "^4.1.1", + "del": "^5.1.0", "getopts": "^2.2.4", "supports-color": "^7.0.0", "typescript": "3.5.3" diff --git a/packages/kbn-interpreter/package.json b/packages/kbn-interpreter/package.json index f2aa2e1ced9cd..27ef70d871856 100644 --- a/packages/kbn-interpreter/package.json +++ b/packages/kbn-interpreter/package.json @@ -24,7 +24,7 @@ "babel-loader": "^8.0.6", "copy-webpack-plugin": "^5.0.4", "css-loader": "2.1.1", - "del": "^4.1.1", + "del": "^5.1.0", "getopts": "^2.2.4", "pegjs": "0.10.0", "sass-loader": "^7.3.1", diff --git a/packages/kbn-plugin-helpers/package.json b/packages/kbn-plugin-helpers/package.json index 1b8247c3f756c..68af0aa791c8e 100644 --- a/packages/kbn-plugin-helpers/package.json +++ b/packages/kbn-plugin-helpers/package.json @@ -16,7 +16,7 @@ "@babel/core": "^7.5.5", "argv-split": "^2.0.1", "commander": "^3.0.0", - "del": "^4.1.1", + "del": "^5.1.0", "execa": "^3.2.0", "globby": "^8.0.1", "gulp-babel": "^8.0.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 3834ad4c92d55..2a8c22ed29a79 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(412); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(483); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); @@ -152,7 +152,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(402); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(474); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -2503,8 +2503,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); /* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(173); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(200); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(201); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(272); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(273); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -23214,7 +23214,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(174); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(189); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(261); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); @@ -23319,74 +23319,125 @@ const CleanCommand = { "use strict"; +const {promisify} = __webpack_require__(29); const path = __webpack_require__(16); const globby = __webpack_require__(175); -const isPathCwd = __webpack_require__(182); -const isPathInCwd = __webpack_require__(183); -const pify = __webpack_require__(186); -const rimraf = __webpack_require__(187); -const pMap = __webpack_require__(188); - -const rimrafP = pify(rimraf); - -function safeCheck(file) { +const isGlob = __webpack_require__(187); +const slash = __webpack_require__(248); +const gracefulFs = __webpack_require__(250); +const isPathCwd = __webpack_require__(254); +const isPathInside = __webpack_require__(255); +const rimraf = __webpack_require__(256); +const pMap = __webpack_require__(257); + +const rimrafP = promisify(rimraf); + +const rimrafOptions = { + glob: false, + unlink: gracefulFs.unlink, + unlinkSync: gracefulFs.unlinkSync, + chmod: gracefulFs.chmod, + chmodSync: gracefulFs.chmodSync, + stat: gracefulFs.stat, + statSync: gracefulFs.statSync, + lstat: gracefulFs.lstat, + lstatSync: gracefulFs.lstatSync, + rmdir: gracefulFs.rmdir, + rmdirSync: gracefulFs.rmdirSync, + readdir: gracefulFs.readdir, + readdirSync: gracefulFs.readdirSync +}; + +function safeCheck(file, cwd) { if (isPathCwd(file)) { throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.'); } - if (!isPathInCwd(file)) { - throw new Error('Cannot delete files/folders outside the current working directory. Can be overridden with the `force` option.'); + if (!isPathInside(file, cwd)) { + throw new Error('Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.'); } } -const del = (patterns, options) => { - options = Object.assign({}, options); +function normalizePatterns(patterns) { + patterns = Array.isArray(patterns) ? patterns : [patterns]; + + patterns = patterns.map(pattern => { + if (process.platform === 'win32' && isGlob(pattern) === false) { + return slash(pattern); + } + + return pattern; + }); + + return patterns; +} + +module.exports = async (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { + options = { + expandDirectories: false, + onlyFiles: false, + followSymbolicLinks: false, + cwd, + ...options + }; + + patterns = normalizePatterns(patterns); + + const files = (await globby(patterns, options)) + .sort((a, b) => b.localeCompare(a)); - const {force, dryRun} = options; - delete options.force; - delete options.dryRun; + const mapper = async file => { + file = path.resolve(cwd, file); - const mapper = file => { if (!force) { - safeCheck(file); + safeCheck(file, cwd); } - file = path.resolve(options.cwd || '', file); - - if (dryRun) { - return file; + if (!dryRun) { + await rimrafP(file, rimrafOptions); } - return rimrafP(file, {glob: false}).then(() => file); + return file; }; - return globby(patterns, options).then(files => pMap(files, mapper, options)); + const removedFiles = await pMap(files, mapper, options); + + removedFiles.sort((a, b) => a.localeCompare(b)); + + return removedFiles; }; -module.exports = del; -// TODO: Remove this for the next major release -module.exports.default = del; +module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => { + options = { + expandDirectories: false, + onlyFiles: false, + followSymbolicLinks: false, + cwd, + ...options + }; -module.exports.sync = (patterns, options) => { - options = Object.assign({}, options); + patterns = normalizePatterns(patterns); + + const files = globby.sync(patterns, options) + .sort((a, b) => b.localeCompare(a)); - const {force, dryRun} = options; - delete options.force; - delete options.dryRun; + const removedFiles = files.map(file => { + file = path.resolve(cwd, file); - return globby.sync(patterns, options).map(file => { if (!force) { - safeCheck(file); + safeCheck(file, cwd); } - file = path.resolve(options.cwd || '', file); - if (!dryRun) { - rimraf.sync(file, {glob: false}); + rimraf.sync(file, rimrafOptions); } return file; }); + + removedFiles.sort((a, b) => a.localeCompare(b)); + + return removedFiles; }; @@ -23396,836 +23447,8056 @@ module.exports.sync = (patterns, options) => { "use strict"; -var Promise = __webpack_require__(176); -var arrayUnion = __webpack_require__(178); -var objectAssign = __webpack_require__(180); -var glob = __webpack_require__(37); -var pify = __webpack_require__(181); +const fs = __webpack_require__(23); +const arrayUnion = __webpack_require__(176); +const merge2 = __webpack_require__(177); +const glob = __webpack_require__(37); +const fastGlob = __webpack_require__(178); +const dirGlob = __webpack_require__(244); +const gitignore = __webpack_require__(246); +const {FilterStream, UniqueStream} = __webpack_require__(249); + +const DEFAULT_FILTER = () => false; -var globP = pify(glob, Promise).bind(glob); +const isNegative = pattern => pattern[0] === '!'; -function isNegative(pattern) { - return pattern[0] === '!'; -} +const assertPatternsInput = patterns => { + if (!patterns.every(pattern => typeof pattern === 'string')) { + throw new TypeError('Patterns must be a string or an array of strings'); + } +}; -function isString(value) { - return typeof value === 'string'; -} +const checkCwdOption = (options = {}) => { + if (!options.cwd) { + return; + } -function assertPatternsInput(patterns) { - if (!patterns.every(isString)) { - throw new TypeError('patterns must be a string or an array of strings'); + let stat; + try { + stat = fs.statSync(options.cwd); + } catch (_) { + return; } -} -function generateGlobTasks(patterns, opts) { - patterns = [].concat(patterns); + if (!stat.isDirectory()) { + throw new Error('The `cwd` option must be a path to a directory'); + } +}; + +const getPathString = p => p.stats instanceof fs.Stats ? p.path : p; + +const generateGlobTasks = (patterns, taskOptions) => { + patterns = arrayUnion([].concat(patterns)); assertPatternsInput(patterns); + checkCwdOption(taskOptions); - var globTasks = []; + const globTasks = []; - opts = objectAssign({ - cache: Object.create(null), - statCache: Object.create(null), - realpathCache: Object.create(null), - symlinks: Object.create(null), - ignore: [] - }, opts); + taskOptions = { + ignore: [], + expandDirectories: true, + ...taskOptions + }; - patterns.forEach(function (pattern, i) { + for (const [index, pattern] of patterns.entries()) { if (isNegative(pattern)) { - return; + continue; } - var ignore = patterns.slice(i).filter(isNegative).map(function (pattern) { - return pattern.slice(1); - }); + const ignore = patterns + .slice(index) + .filter(isNegative) + .map(pattern => pattern.slice(1)); - globTasks.push({ - pattern: pattern, - opts: objectAssign({}, opts, { - ignore: opts.ignore.concat(ignore) - }) - }); - }); + const options = { + ...taskOptions, + ignore: taskOptions.ignore.concat(ignore) + }; + + globTasks.push({pattern, options}); + } return globTasks; -} +}; -module.exports = function (patterns, opts) { - var globTasks; +const globDirs = (task, fn) => { + let options = {}; + if (task.options.cwd) { + options.cwd = task.options.cwd; + } - try { - globTasks = generateGlobTasks(patterns, opts); - } catch (err) { - return Promise.reject(err); + if (Array.isArray(task.options.expandDirectories)) { + options = { + ...options, + files: task.options.expandDirectories + }; + } else if (typeof task.options.expandDirectories === 'object') { + options = { + ...options, + ...task.options.expandDirectories + }; } - return Promise.all(globTasks.map(function (task) { - return globP(task.pattern, task.opts); - })).then(function (paths) { - return arrayUnion.apply(null, paths); - }); + return fn(task.pattern, options); }; -module.exports.sync = function (patterns, opts) { - var globTasks = generateGlobTasks(patterns, opts); +const getPattern = (task, fn) => task.options.expandDirectories ? globDirs(task, fn) : [task.pattern]; - return globTasks.reduce(function (matches, task) { - return arrayUnion(matches, glob.sync(task.pattern, task.opts)); - }, []); +const getFilterSync = options => { + return options && options.gitignore ? + gitignore.sync({cwd: options.cwd, ignore: options.ignore}) : + DEFAULT_FILTER; }; -module.exports.generateGlobTasks = generateGlobTasks; +const globToTask = task => glob => { + const {options} = task; + if (options.ignore && Array.isArray(options.ignore) && options.expandDirectories) { + options.ignore = dirGlob.sync(options.ignore); + } -module.exports.hasMagic = function (patterns, opts) { - return [].concat(patterns).some(function (pattern) { - return glob.hasMagic(pattern, opts); - }); + return { + pattern: glob, + options + }; }; +module.exports = async (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); -/***/ }), -/* 176 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - + const getFilter = async () => { + return options && options.gitignore ? + gitignore({cwd: options.cwd, ignore: options.ignore}) : + DEFAULT_FILTER; + }; -module.exports = typeof Promise === 'function' ? Promise : __webpack_require__(177); + const getTasks = async () => { + const tasks = await Promise.all(globTasks.map(async task => { + const globs = await getPattern(task, dirGlob); + return Promise.all(globs.map(globToTask(task))); + })); + return arrayUnion(...tasks); + }; -/***/ }), -/* 177 */ -/***/ (function(module, exports, __webpack_require__) { + const [filter, tasks] = await Promise.all([getFilter(), getTasks()]); + const paths = await Promise.all(tasks.map(task => fastGlob(task.pattern, task.options))); -"use strict"; + return arrayUnion(...paths).filter(path_ => !filter(getPathString(path_))); +}; +module.exports.sync = (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); -var PENDING = 'pending'; -var SETTLED = 'settled'; -var FULFILLED = 'fulfilled'; -var REJECTED = 'rejected'; -var NOOP = function () {}; -var isNode = typeof global !== 'undefined' && typeof global.process !== 'undefined' && typeof global.process.emit === 'function'; + const tasks = globTasks.reduce((tasks, task) => { + const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); + return tasks.concat(newTask); + }, []); -var asyncSetTimer = typeof setImmediate === 'undefined' ? setTimeout : setImmediate; -var asyncQueue = []; -var asyncTimer; + const filter = getFilterSync(options); -function asyncFlush() { - // run promise callbacks - for (var i = 0; i < asyncQueue.length; i++) { - asyncQueue[i][0](asyncQueue[i][1]); - } + return tasks.reduce( + (matches, task) => arrayUnion(matches, fastGlob.sync(task.pattern, task.options)), + [] + ).filter(path_ => !filter(path_)); +}; - // reset async asyncQueue - asyncQueue = []; - asyncTimer = false; -} +module.exports.stream = (patterns, options) => { + const globTasks = generateGlobTasks(patterns, options); -function asyncCall(callback, arg) { - asyncQueue.push([callback, arg]); + const tasks = globTasks.reduce((tasks, task) => { + const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); + return tasks.concat(newTask); + }, []); - if (!asyncTimer) { - asyncTimer = true; - asyncSetTimer(asyncFlush, 0); - } -} + const filter = getFilterSync(options); + const filterStream = new FilterStream(p => !filter(p)); + const uniqueStream = new UniqueStream(); -function invokeResolver(resolver, promise) { - function resolvePromise(value) { - resolve(promise, value); - } + return merge2(tasks.map(task => fastGlob.stream(task.pattern, task.options))) + .pipe(filterStream) + .pipe(uniqueStream); +}; - function rejectPromise(reason) { - reject(promise, reason); - } +module.exports.generateGlobTasks = generateGlobTasks; - try { - resolver(resolvePromise, rejectPromise); - } catch (e) { - rejectPromise(e); - } -} +module.exports.hasMagic = (patterns, options) => [] + .concat(patterns) + .some(pattern => glob.hasMagic(pattern, options)); -function invokeCallback(subscriber) { - var owner = subscriber.owner; - var settled = owner._state; - var value = owner._data; - var callback = subscriber[settled]; - var promise = subscriber.then; +module.exports.gitignore = gitignore; - if (typeof callback === 'function') { - settled = FULFILLED; - try { - value = callback(value); - } catch (e) { - reject(promise, e); - } - } - if (!handleThenable(promise, value)) { - if (settled === FULFILLED) { - resolve(promise, value); - } +/***/ }), +/* 176 */ +/***/ (function(module, exports, __webpack_require__) { - if (settled === REJECTED) { - reject(promise, value); - } - } -} +"use strict"; -function handleThenable(promise, value) { - var resolved; - try { - if (promise === value) { - throw new TypeError('A promises callback cannot return that same promise.'); - } +module.exports = (...arguments_) => { + return [...new Set([].concat(...arguments_))]; +}; - if (value && (typeof value === 'function' || typeof value === 'object')) { - // then should be retrieved only once - var then = value.then; - if (typeof then === 'function') { - then.call(value, function (val) { - if (!resolved) { - resolved = true; +/***/ }), +/* 177 */ +/***/ (function(module, exports, __webpack_require__) { - if (value === val) { - fulfill(promise, val); - } else { - resolve(promise, val); - } - } - }, function (reason) { - if (!resolved) { - resolved = true; +"use strict"; - reject(promise, reason); - } - }); +/* + * merge2 + * https://github.com/teambition/merge2 + * + * Copyright (c) 2014-2016 Teambition + * Licensed under the MIT license. + */ +const Stream = __webpack_require__(28) +const PassThrough = Stream.PassThrough +const slice = Array.prototype.slice - return true; - } - } - } catch (e) { - if (!resolved) { - reject(promise, e); - } +module.exports = merge2 - return true; - } +function merge2 () { + const streamsQueue = [] + let merging = false + const args = slice.call(arguments) + let options = args[args.length - 1] - return false; -} + if (options && !Array.isArray(options) && options.pipe == null) args.pop() + else options = {} -function resolve(promise, value) { - if (promise === value || !handleThenable(promise, value)) { - fulfill(promise, value); - } -} + const doEnd = options.end !== false + if (options.objectMode == null) options.objectMode = true + if (options.highWaterMark == null) options.highWaterMark = 64 * 1024 + const mergedStream = PassThrough(options) -function fulfill(promise, value) { - if (promise._state === PENDING) { - promise._state = SETTLED; - promise._data = value; + function addStream () { + for (let i = 0, len = arguments.length; i < len; i++) { + streamsQueue.push(pauseStreams(arguments[i], options)) + } + mergeStream() + return this + } - asyncCall(publishFulfillment, promise); - } -} + function mergeStream () { + if (merging) return + merging = true -function reject(promise, reason) { - if (promise._state === PENDING) { - promise._state = SETTLED; - promise._data = reason; + let streams = streamsQueue.shift() + if (!streams) { + process.nextTick(endStream) + return + } + if (!Array.isArray(streams)) streams = [streams] - asyncCall(publishRejection, promise); - } -} + let pipesCount = streams.length + 1 -function publish(promise) { - promise._then = promise._then.forEach(invokeCallback); -} + function next () { + if (--pipesCount > 0) return + merging = false + mergeStream() + } -function publishFulfillment(promise) { - promise._state = FULFILLED; - publish(promise); -} + function pipe (stream) { + function onend () { + stream.removeListener('merge2UnpipeEnd', onend) + stream.removeListener('end', onend) + next() + } + // skip ended stream + if (stream._readableState.endEmitted) return next() -function publishRejection(promise) { - promise._state = REJECTED; - publish(promise); - if (!promise._handled && isNode) { - global.process.emit('unhandledRejection', promise._data, promise); - } -} + stream.on('merge2UnpipeEnd', onend) + stream.on('end', onend) + stream.pipe(mergedStream, { end: false }) + // compatible for old stream + stream.resume() + } -function notifyRejectionHandled(promise) { - global.process.emit('rejectionHandled', promise); -} + for (let i = 0; i < streams.length; i++) pipe(streams[i]) -/** - * @class - */ -function Promise(resolver) { - if (typeof resolver !== 'function') { - throw new TypeError('Promise resolver ' + resolver + ' is not a function'); - } + next() + } - if (this instanceof Promise === false) { - throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.'); - } + function endStream () { + merging = false + // emit 'queueDrain' when all streams merged. + mergedStream.emit('queueDrain') + return doEnd && mergedStream.end() + } - this._then = []; + mergedStream.setMaxListeners(0) + mergedStream.add = addStream + mergedStream.on('unpipe', function (stream) { + stream.emit('merge2UnpipeEnd') + }) - invokeResolver(resolver, this); + if (args.length) addStream.apply(null, args) + return mergedStream } -Promise.prototype = { - constructor: Promise, - - _state: PENDING, - _then: null, - _data: undefined, - _handled: false, - - then: function (onFulfillment, onRejection) { - var subscriber = { - owner: this, - then: new this.constructor(NOOP), - fulfilled: onFulfillment, - rejected: onRejection - }; - - if ((onRejection || onFulfillment) && !this._handled) { - this._handled = true; - if (this._state === REJECTED && isNode) { - asyncCall(notifyRejectionHandled, this); - } - } - - if (this._state === FULFILLED || this._state === REJECTED) { - // already resolved, call callback async - asyncCall(invokeCallback, subscriber); - } else { - // subscribe - this._then.push(subscriber); - } - - return subscriber.then; - }, - - catch: function (onRejection) { - return this.then(null, onRejection); - } -}; - -Promise.all = function (promises) { - if (!Array.isArray(promises)) { - throw new TypeError('You must pass an array to Promise.all().'); - } +// check and pause streams for pipe. +function pauseStreams (streams, options) { + if (!Array.isArray(streams)) { + // Backwards-compat with old-style streams + if (!streams._readableState && streams.pipe) streams = streams.pipe(PassThrough(options)) + if (!streams._readableState || !streams.pause || !streams.pipe) { + throw new Error('Only readable stream can be merged.') + } + streams.pause() + } else { + for (let i = 0, len = streams.length; i < len; i++) streams[i] = pauseStreams(streams[i], options) + } + return streams +} - return new Promise(function (resolve, reject) { - var results = []; - var remaining = 0; - function resolver(index) { - remaining++; - return function (value) { - results[index] = value; - if (!--remaining) { - resolve(results); - } - }; - } +/***/ }), +/* 178 */ +/***/ (function(module, exports, __webpack_require__) { - for (var i = 0, promise; i < promises.length; i++) { - promise = promises[i]; +"use strict"; + +const taskManager = __webpack_require__(179); +const async_1 = __webpack_require__(207); +const stream_1 = __webpack_require__(240); +const sync_1 = __webpack_require__(241); +const settings_1 = __webpack_require__(243); +const utils = __webpack_require__(180); +function FastGlob(source, options) { + try { + assertPatternsInput(source); + } + catch (error) { + return Promise.reject(error); + } + const works = getWorks(source, async_1.default, options); + return Promise.all(works).then(utils.array.flatten); +} +(function (FastGlob) { + function sync(source, options) { + assertPatternsInput(source); + const works = getWorks(source, sync_1.default, options); + return utils.array.flatten(works); + } + FastGlob.sync = sync; + function stream(source, options) { + assertPatternsInput(source); + const works = getWorks(source, stream_1.default, options); + /** + * The stream returned by the provider cannot work with an asynchronous iterator. + * To support asynchronous iterators, regardless of the number of tasks, we always multiplex streams. + * This affects performance (+25%). I don't see best solution right now. + */ + return utils.stream.merge(works); + } + FastGlob.stream = stream; + function generateTasks(source, options) { + assertPatternsInput(source); + const patterns = [].concat(source); + const settings = new settings_1.default(options); + return taskManager.generate(patterns, settings); + } + FastGlob.generateTasks = generateTasks; +})(FastGlob || (FastGlob = {})); +function getWorks(source, _Provider, options) { + const patterns = [].concat(source); + const settings = new settings_1.default(options); + const tasks = taskManager.generate(patterns, settings); + const provider = new _Provider(settings); + return tasks.map(provider.read, provider); +} +function assertPatternsInput(source) { + if ([].concat(source).every(isString)) { + return; + } + throw new TypeError('Patterns must be a string or an array of strings'); +} +function isString(source) { + /* tslint:disable-next-line strict-type-predicates */ + return typeof source === 'string'; +} +module.exports = FastGlob; - if (promise && typeof promise.then === 'function') { - promise.then(resolver(i), reject); - } else { - results[i] = promise; - } - } - if (!remaining) { - resolve(results); - } - }); -}; +/***/ }), +/* 179 */ +/***/ (function(module, exports, __webpack_require__) { -Promise.race = function (promises) { - if (!Array.isArray(promises)) { - throw new TypeError('You must pass an array to Promise.race().'); - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(180); +function generate(patterns, settings) { + const positivePatterns = getPositivePatterns(patterns); + const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); + /** + * When the `caseSensitiveMatch` option is disabled, all patterns must be marked as dynamic, because we cannot check + * filepath directly (without read directory). + */ + const staticPatterns = !settings.caseSensitiveMatch ? [] : positivePatterns.filter(utils.pattern.isStaticPattern); + const dynamicPatterns = !settings.caseSensitiveMatch ? positivePatterns : positivePatterns.filter(utils.pattern.isDynamicPattern); + const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false); + const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true); + return staticTasks.concat(dynamicTasks); +} +exports.generate = generate; +function convertPatternsToTasks(positive, negative, dynamic) { + const positivePatternsGroup = groupPatternsByBaseDirectory(positive); + // When we have a global group – there is no reason to divide the patterns into independent tasks. + // In this case, the global task covers the rest. + if ('.' in positivePatternsGroup) { + const task = convertPatternGroupToTask('.', positive, negative, dynamic); + return [task]; + } + return convertPatternGroupsToTasks(positivePatternsGroup, negative, dynamic); +} +exports.convertPatternsToTasks = convertPatternsToTasks; +function getPositivePatterns(patterns) { + return utils.pattern.getPositivePatterns(patterns); +} +exports.getPositivePatterns = getPositivePatterns; +function getNegativePatternsAsPositive(patterns, ignore) { + const negative = utils.pattern.getNegativePatterns(patterns).concat(ignore); + const positive = negative.map(utils.pattern.convertToPositivePattern); + return positive; +} +exports.getNegativePatternsAsPositive = getNegativePatternsAsPositive; +function groupPatternsByBaseDirectory(patterns) { + return patterns.reduce((collection, pattern) => { + const base = utils.pattern.getBaseDirectory(pattern); + if (base in collection) { + collection[base].push(pattern); + } + else { + collection[base] = [pattern]; + } + return collection; + }, {}); +} +exports.groupPatternsByBaseDirectory = groupPatternsByBaseDirectory; +function convertPatternGroupsToTasks(positive, negative, dynamic) { + return Object.keys(positive).map((base) => { + return convertPatternGroupToTask(base, positive[base], negative, dynamic); + }); +} +exports.convertPatternGroupsToTasks = convertPatternGroupsToTasks; +function convertPatternGroupToTask(base, positive, negative, dynamic) { + return { + dynamic, + positive, + negative, + base, + patterns: [].concat(positive, negative.map(utils.pattern.convertToNegativePattern)) + }; +} +exports.convertPatternGroupToTask = convertPatternGroupToTask; - return new Promise(function (resolve, reject) { - for (var i = 0, promise; i < promises.length; i++) { - promise = promises[i]; - if (promise && typeof promise.then === 'function') { - promise.then(resolve, reject); - } else { - resolve(promise); - } - } - }); -}; +/***/ }), +/* 180 */ +/***/ (function(module, exports, __webpack_require__) { -Promise.resolve = function (value) { - if (value && typeof value === 'object' && value.constructor === Promise) { - return value; - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const array = __webpack_require__(181); +exports.array = array; +const errno = __webpack_require__(182); +exports.errno = errno; +const fs = __webpack_require__(183); +exports.fs = fs; +const path = __webpack_require__(184); +exports.path = path; +const pattern = __webpack_require__(185); +exports.pattern = pattern; +const stream = __webpack_require__(206); +exports.stream = stream; - return new Promise(function (resolve) { - resolve(value); - }); -}; -Promise.reject = function (reason) { - return new Promise(function (resolve, reject) { - reject(reason); - }); -}; +/***/ }), +/* 181 */ +/***/ (function(module, exports, __webpack_require__) { -module.exports = Promise; +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function flatten(items) { + return items.reduce((collection, item) => [].concat(collection, item), []); +} +exports.flatten = flatten; /***/ }), -/* 178 */ +/* 182 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; - -var arrayUniq = __webpack_require__(179); - -module.exports = function () { - return arrayUniq([].concat.apply([], arguments)); -}; + +Object.defineProperty(exports, "__esModule", { value: true }); +function isEnoentCodeError(error) { + return error.code === 'ENOENT'; +} +exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 179 */ +/* 183 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +class DirentFromStats { + constructor(name, stats) { + this.name = name; + this.isBlockDevice = stats.isBlockDevice.bind(stats); + this.isCharacterDevice = stats.isCharacterDevice.bind(stats); + this.isDirectory = stats.isDirectory.bind(stats); + this.isFIFO = stats.isFIFO.bind(stats); + this.isFile = stats.isFile.bind(stats); + this.isSocket = stats.isSocket.bind(stats); + this.isSymbolicLink = stats.isSymbolicLink.bind(stats); + } +} +function createDirentFromStats(name, stats) { + return new DirentFromStats(name, stats); +} +exports.createDirentFromStats = createDirentFromStats; -// there's 3 implementations written in increasing order of efficiency - -// 1 - no Set type is defined -function uniqNoSet(arr) { - var ret = []; +/***/ }), +/* 184 */ +/***/ (function(module, exports, __webpack_require__) { - for (var i = 0; i < arr.length; i++) { - if (ret.indexOf(arr[i]) === -1) { - ret.push(arr[i]); - } - } +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(16); +/** + * Designed to work only with simple paths: `dir\\file`. + */ +function unixify(filepath) { + return filepath.replace(/\\/g, '/'); +} +exports.unixify = unixify; +function makeAbsolute(cwd, filepath) { + return path.resolve(cwd, filepath); +} +exports.makeAbsolute = makeAbsolute; - return ret; -} -// 2 - a simple Set type is defined -function uniqSet(arr) { - var seen = new Set(); - return arr.filter(function (el) { - if (!seen.has(el)) { - seen.add(el); - return true; - } +/***/ }), +/* 185 */ +/***/ (function(module, exports, __webpack_require__) { - return false; - }); -} +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(16); +const globParent = __webpack_require__(186); +const isGlob = __webpack_require__(187); +const micromatch = __webpack_require__(189); +const GLOBSTAR = '**'; +function isStaticPattern(pattern) { + return !isDynamicPattern(pattern); +} +exports.isStaticPattern = isStaticPattern; +function isDynamicPattern(pattern) { + return isGlob(pattern, { strict: false }); +} +exports.isDynamicPattern = isDynamicPattern; +function convertToPositivePattern(pattern) { + return isNegativePattern(pattern) ? pattern.slice(1) : pattern; +} +exports.convertToPositivePattern = convertToPositivePattern; +function convertToNegativePattern(pattern) { + return '!' + pattern; +} +exports.convertToNegativePattern = convertToNegativePattern; +function isNegativePattern(pattern) { + return pattern.startsWith('!') && pattern[1] !== '('; +} +exports.isNegativePattern = isNegativePattern; +function isPositivePattern(pattern) { + return !isNegativePattern(pattern); +} +exports.isPositivePattern = isPositivePattern; +function getNegativePatterns(patterns) { + return patterns.filter(isNegativePattern); +} +exports.getNegativePatterns = getNegativePatterns; +function getPositivePatterns(patterns) { + return patterns.filter(isPositivePattern); +} +exports.getPositivePatterns = getPositivePatterns; +function getBaseDirectory(pattern) { + return globParent(pattern); +} +exports.getBaseDirectory = getBaseDirectory; +function hasGlobStar(pattern) { + return pattern.indexOf(GLOBSTAR) !== -1; +} +exports.hasGlobStar = hasGlobStar; +function endsWithSlashGlobStar(pattern) { + return pattern.endsWith('/' + GLOBSTAR); +} +exports.endsWithSlashGlobStar = endsWithSlashGlobStar; +function isAffectDepthOfReadingPattern(pattern) { + const basename = path.basename(pattern); + return endsWithSlashGlobStar(pattern) || isStaticPattern(basename); +} +exports.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern; +function getNaiveDepth(pattern) { + const base = getBaseDirectory(pattern); + const patternDepth = pattern.split('/').length; + const patternBaseDepth = base.split('/').length; + /** + * This is a hack for pattern that has no base directory. + * + * This is related to the `*\something\*` pattern. + */ + if (base === '.') { + return patternDepth - patternBaseDepth; + } + return patternDepth - patternBaseDepth - 1; +} +exports.getNaiveDepth = getNaiveDepth; +function getMaxNaivePatternsDepth(patterns) { + return patterns.reduce((max, pattern) => { + const depth = getNaiveDepth(pattern); + return depth > max ? depth : max; + }, 0); +} +exports.getMaxNaivePatternsDepth = getMaxNaivePatternsDepth; +function makeRe(pattern, options) { + return micromatch.makeRe(pattern, options); +} +exports.makeRe = makeRe; +function convertPatternsToRe(patterns, options) { + return patterns.map((pattern) => makeRe(pattern, options)); +} +exports.convertPatternsToRe = convertPatternsToRe; +function matchAny(entry, patternsRe) { + const filepath = entry.replace(/^\.[\\\/]/, ''); + return patternsRe.some((patternRe) => patternRe.test(filepath)); +} +exports.matchAny = matchAny; + + +/***/ }), +/* 186 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var isGlob = __webpack_require__(187); +var pathPosixDirname = __webpack_require__(16).posix.dirname; +var isWin32 = __webpack_require__(11).platform() === 'win32'; + +var slash = '/'; +var backslash = /\\/g; +var enclosure = /[\{\[].*[\/]*.*[\}\]]$/; +var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; +var escaped = /\\([\*\?\|\[\]\(\)\{\}])/g; + +module.exports = function globParent(str) { + // flip windows path separators + if (isWin32 && str.indexOf(slash) < 0) { + str = str.replace(backslash, slash); + } + + // special case for strings ending in enclosure containing path separator + if (enclosure.test(str)) { + str += slash; + } + + // preserves full path in case of trailing path separator + str += 'a'; + + // remove path parts that are globby + do { + str = pathPosixDirname(str); + } while (isGlob(str) || globby.test(str)); + + // remove escape chars and return result + return str.replace(escaped, '$1'); +}; + + +/***/ }), +/* 187 */ +/***/ (function(module, exports, __webpack_require__) { + +/*! + * is-glob + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +var isExtglob = __webpack_require__(188); +var chars = { '{': '}', '(': ')', '[': ']'}; +var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; +var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; + +module.exports = function isGlob(str, options) { + if (typeof str !== 'string' || str === '') { + return false; + } + + if (isExtglob(str)) { + return true; + } + + var regex = strictRegex; + var match; + + // optionally relax regex + if (options && options.strict === false) { + regex = relaxedRegex; + } + + while ((match = regex.exec(str))) { + if (match[2]) return true; + var idx = match.index + match[0].length; + + // if an open bracket/brace/paren is escaped, + // set the index to the next closing character + var open = match[1]; + var close = open ? chars[open] : null; + if (open && close) { + var n = str.indexOf(close, idx); + if (n !== -1) { + idx = n + 1; + } + } + + str = str.slice(idx); + } + return false; +}; + + +/***/ }), +/* 188 */ +/***/ (function(module, exports) { + +/*! + * is-extglob + * + * Copyright (c) 2014-2016, Jon Schlinkert. + * Licensed under the MIT License. + */ + +module.exports = function isExtglob(str) { + if (typeof str !== 'string' || str === '') { + return false; + } + + var match; + while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { + if (match[2]) return true; + str = str.slice(match.index + match[0].length); + } + + return false; +}; + + +/***/ }), +/* 189 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const util = __webpack_require__(29); +const braces = __webpack_require__(190); +const picomatch = __webpack_require__(200); +const utils = __webpack_require__(203); +const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); + +/** + * Returns an array of strings that match one or more glob patterns. + * + * ```js + * const mm = require('micromatch'); + * // mm(list, patterns[, options]); + * + * console.log(mm(['a.js', 'a.txt'], ['*.js'])); + * //=> [ 'a.js' ] + * ``` + * @param {String|Array} list List of strings to match. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} options See available [options](#options) + * @return {Array} Returns an array of matches + * @summary false + * @api public + */ + +const micromatch = (list, patterns, options) => { + patterns = [].concat(patterns); + list = [].concat(list); + + let omit = new Set(); + let keep = new Set(); + let items = new Set(); + let negatives = 0; + + let onResult = state => { + items.add(state.output); + if (options && options.onResult) { + options.onResult(state); + } + }; + + for (let i = 0; i < patterns.length; i++) { + let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true); + let negated = isMatch.state.negated || isMatch.state.negatedExtglob; + if (negated) negatives++; + + for (let item of list) { + let matched = isMatch(item, true); + + let match = negated ? !matched.isMatch : matched.isMatch; + if (!match) continue; + + if (negated) { + omit.add(matched.output); + } else { + omit.delete(matched.output); + keep.add(matched.output); + } + } + } + + let result = negatives === patterns.length ? [...items] : [...keep]; + let matches = result.filter(item => !omit.has(item)); + + if (options && matches.length === 0) { + if (options.failglob === true) { + throw new Error(`No matches found for "${patterns.join(', ')}"`); + } + + if (options.nonull === true || options.nullglob === true) { + return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns; + } + } + + return matches; +}; + +/** + * Backwards compatibility + */ + +micromatch.match = micromatch; + +/** + * Returns a matcher function from the given glob `pattern` and `options`. + * The returned function takes a string to match as its only argument and returns + * true if the string is a match. + * + * ```js + * const mm = require('micromatch'); + * // mm.matcher(pattern[, options]); + * + * const isMatch = mm.matcher('*.!(*a)'); + * console.log(isMatch('a.a')); //=> false + * console.log(isMatch('a.b')); //=> true + * ``` + * @param {String} `pattern` Glob pattern + * @param {Object} `options` + * @return {Function} Returns a matcher function. + * @api public + */ + +micromatch.matcher = (pattern, options) => picomatch(pattern, options); + +/** + * Returns true if **any** of the given glob `patterns` match the specified `string`. + * + * ```js + * const mm = require('micromatch'); + * // mm.isMatch(string, patterns[, options]); + * + * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true + * console.log(mm.isMatch('a.a', 'b.*')); //=> false + * ``` + * @param {String} str The string to test. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} [options] See available [options](#options). + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); + +/** + * Backwards compatibility + */ + +micromatch.any = micromatch.isMatch; + +/** + * Returns a list of strings that _**do not match any**_ of the given `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.not(list, patterns[, options]); + * + * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a')); + * //=> ['b.b', 'c.c'] + * ``` + * @param {Array} `list` Array of strings to match. + * @param {String|Array} `patterns` One or more glob pattern to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Array} Returns an array of strings that **do not match** the given patterns. + * @api public + */ + +micromatch.not = (list, patterns, options = {}) => { + patterns = [].concat(patterns).map(String); + let result = new Set(); + let items = []; + + let onResult = state => { + if (options.onResult) options.onResult(state); + items.push(state.output); + }; + + let matches = micromatch(list, patterns, { ...options, onResult }); + + for (let item of items) { + if (!matches.includes(item)) { + result.add(item); + } + } + return [...result]; +}; + +/** + * Returns true if the given `string` contains the given pattern. Similar + * to [.isMatch](#isMatch) but the pattern can match any part of the string. + * + * ```js + * var mm = require('micromatch'); + * // mm.contains(string, pattern[, options]); + * + * console.log(mm.contains('aa/bb/cc', '*b')); + * //=> true + * console.log(mm.contains('aa/bb/cc', '*d')); + * //=> false + * ``` + * @param {String} `str` The string to match. + * @param {String|Array} `patterns` Glob pattern to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if the patter matches any part of `str`. + * @api public + */ + +micromatch.contains = (str, pattern, options) => { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string: "${util.inspect(str)}"`); + } + + if (Array.isArray(pattern)) { + return pattern.some(p => micromatch.contains(str, p, options)); + } + + if (typeof pattern === 'string') { + if (isEmptyString(str) || isEmptyString(pattern)) { + return false; + } + + if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) { + return true; + } + } + + return micromatch.isMatch(str, pattern, { ...options, contains: true }); +}; + +/** + * Filter the keys of the given object with the given `glob` pattern + * and `options`. Does not attempt to match nested keys. If you need this feature, + * use [glob-object][] instead. + * + * ```js + * const mm = require('micromatch'); + * // mm.matchKeys(object, patterns[, options]); + * + * const obj = { aa: 'a', ab: 'b', ac: 'c' }; + * console.log(mm.matchKeys(obj, '*b')); + * //=> { ab: 'b' } + * ``` + * @param {Object} `object` The object with keys to filter. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Object} Returns an object with only keys that match the given patterns. + * @api public + */ + +micromatch.matchKeys = (obj, patterns, options) => { + if (!utils.isObject(obj)) { + throw new TypeError('Expected the first argument to be an object'); + } + let keys = micromatch(Object.keys(obj), patterns, options); + let res = {}; + for (let key of keys) res[key] = obj[key]; + return res; +}; + +/** + * Returns true if some of the strings in the given `list` match any of the given glob `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.some(list, patterns[, options]); + * + * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); + * // true + * console.log(mm.some(['foo.js'], ['*.js', '!foo.js'])); + * // false + * ``` + * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +micromatch.some = (list, patterns, options) => { + let items = [].concat(list); + + for (let pattern of [].concat(patterns)) { + let isMatch = picomatch(String(pattern), options); + if (items.some(item => isMatch(item))) { + return true; + } + } + return false; +}; + +/** + * Returns true if every string in the given `list` matches + * any of the given glob `patterns`. + * + * ```js + * const mm = require('micromatch'); + * // mm.every(list, patterns[, options]); + * + * console.log(mm.every('foo.js', ['foo.js'])); + * // true + * console.log(mm.every(['foo.js', 'bar.js'], ['*.js'])); + * // true + * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js'])); + * // false + * console.log(mm.every(['foo.js'], ['*.js', '!foo.js'])); + * // false + * ``` + * @param {String|Array} `list` The string or array of strings to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +micromatch.every = (list, patterns, options) => { + let items = [].concat(list); + + for (let pattern of [].concat(patterns)) { + let isMatch = picomatch(String(pattern), options); + if (!items.every(item => isMatch(item))) { + return false; + } + } + return true; +}; + +/** + * Returns true if **all** of the given `patterns` match + * the specified string. + * + * ```js + * const mm = require('micromatch'); + * // mm.all(string, patterns[, options]); + * + * console.log(mm.all('foo.js', ['foo.js'])); + * // true + * + * console.log(mm.all('foo.js', ['*.js', '!foo.js'])); + * // false + * + * console.log(mm.all('foo.js', ['*.js', 'foo.js'])); + * // true + * + * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js'])); + * // true + * ``` + * @param {String|Array} `str` The string to test. + * @param {String|Array} `patterns` One or more glob patterns to use for matching. + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +micromatch.all = (str, patterns, options) => { + if (typeof str !== 'string') { + throw new TypeError(`Expected a string: "${util.inspect(str)}"`); + } + + return [].concat(patterns).every(p => picomatch(p, options)(str)); +}; + +/** + * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match. + * + * ```js + * const mm = require('micromatch'); + * // mm.capture(pattern, string[, options]); + * + * console.log(mm.capture('test/*.js', 'test/foo.js')); + * //=> ['foo'] + * console.log(mm.capture('test/*.js', 'foo/bar.css')); + * //=> null + * ``` + * @param {String} `glob` Glob pattern to use for matching. + * @param {String} `input` String to match + * @param {Object} `options` See available [options](#options) for changing how matches are performed + * @return {Boolean} Returns an array of captures if the input matches the glob pattern, otherwise `null`. + * @api public + */ + +micromatch.capture = (glob, input, options) => { + let posix = utils.isWindows(options); + let regex = picomatch.makeRe(String(glob), { ...options, capture: true }); + let match = regex.exec(posix ? utils.toPosixSlashes(input) : input); + + if (match) { + return match.slice(1).map(v => v === void 0 ? '' : v); + } +}; + +/** + * Create a regular expression from the given glob `pattern`. + * + * ```js + * const mm = require('micromatch'); + * // mm.makeRe(pattern[, options]); + * + * console.log(mm.makeRe('*.js')); + * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/ + * ``` + * @param {String} `pattern` A glob pattern to convert to regex. + * @param {Object} `options` + * @return {RegExp} Returns a regex created from the given pattern. + * @api public + */ + +micromatch.makeRe = (...args) => picomatch.makeRe(...args); + +/** + * Scan a glob pattern to separate the pattern into segments. Used + * by the [split](#split) method. + * + * ```js + * const mm = require('micromatch'); + * const state = mm.scan(pattern[, options]); + * ``` + * @param {String} `pattern` + * @param {Object} `options` + * @return {Object} Returns an object with + * @api public + */ + +micromatch.scan = (...args) => picomatch.scan(...args); + +/** + * Parse a glob pattern to create the source string for a regular + * expression. + * + * ```js + * const mm = require('micromatch'); + * const state = mm(pattern[, options]); + * ``` + * @param {String} `glob` + * @param {Object} `options` + * @return {Object} Returns an object with useful properties and output to be used as regex source string. + * @api public + */ + +micromatch.parse = (patterns, options) => { + let res = []; + for (let pattern of [].concat(patterns || [])) { + for (let str of braces(String(pattern), options)) { + res.push(picomatch.parse(str, options)); + } + } + return res; +}; + +/** + * Process the given brace `pattern`. + * + * ```js + * const { braces } = require('micromatch'); + * console.log(braces('foo/{a,b,c}/bar')); + * //=> [ 'foo/(a|b|c)/bar' ] + * + * console.log(braces('foo/{a,b,c}/bar', { expand: true })); + * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ] + * ``` + * @param {String} `pattern` String with brace pattern to process. + * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options. + * @return {Array} + * @api public + */ + +micromatch.braces = (pattern, options) => { + if (typeof pattern !== 'string') throw new TypeError('Expected a string'); + if ((options && options.nobrace === true) || !/\{.*\}/.test(pattern)) { + return [pattern]; + } + return braces(pattern, options); +}; + +/** + * Expand braces + */ + +micromatch.braceExpand = (pattern, options) => { + if (typeof pattern !== 'string') throw new TypeError('Expected a string'); + return micromatch.braces(pattern, { ...options, expand: true }); +}; + +/** + * Expose micromatch + */ + +module.exports = micromatch; + + +/***/ }), +/* 190 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const stringify = __webpack_require__(191); +const compile = __webpack_require__(193); +const expand = __webpack_require__(197); +const parse = __webpack_require__(198); + +/** + * Expand the given pattern or create a regex-compatible string. + * + * ```js + * const braces = require('braces'); + * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] + * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] + * ``` + * @param {String} `str` + * @param {Object} `options` + * @return {String} + * @api public + */ + +const braces = (input, options = {}) => { + let output = []; + + if (Array.isArray(input)) { + for (let pattern of input) { + let result = braces.create(pattern, options); + if (Array.isArray(result)) { + output.push(...result); + } else { + output.push(result); + } + } + } else { + output = [].concat(braces.create(input, options)); + } + + if (options && options.expand === true && options.nodupes === true) { + output = [...new Set(output)]; + } + return output; +}; + +/** + * Parse the given `str` with the given `options`. + * + * ```js + * // braces.parse(pattern, [, options]); + * const ast = braces.parse('a/{b,c}/d'); + * console.log(ast); + * ``` + * @param {String} pattern Brace pattern to parse + * @param {Object} options + * @return {Object} Returns an AST + * @api public + */ + +braces.parse = (input, options = {}) => parse(input, options); + +/** + * Creates a braces string from an AST, or an AST node. + * + * ```js + * const braces = require('braces'); + * let ast = braces.parse('foo/{a,b}/bar'); + * console.log(stringify(ast.nodes[2])); //=> '{a,b}' + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.stringify = (input, options = {}) => { + if (typeof input === 'string') { + return stringify(braces.parse(input, options), options); + } + return stringify(input, options); +}; + +/** + * Compiles a brace pattern into a regex-compatible, optimized string. + * This method is called by the main [braces](#braces) function by default. + * + * ```js + * const braces = require('braces'); + * console.log(braces.compile('a/{b,c}/d')); + * //=> ['a/(b|c)/d'] + * ``` + * @param {String} `input` Brace pattern or AST. + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.compile = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + return compile(input, options); +}; + +/** + * Expands a brace pattern into an array. This method is called by the + * main [braces](#braces) function when `options.expand` is true. Before + * using this method it's recommended that you read the [performance notes](#performance)) + * and advantages of using [.compile](#compile) instead. + * + * ```js + * const braces = require('braces'); + * console.log(braces.expand('a/{b,c}/d')); + * //=> ['a/b/d', 'a/c/d']; + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.expand = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); + } + + let result = expand(input, options); + + // filter out empty strings if specified + if (options.noempty === true) { + result = result.filter(Boolean); + } + + // filter out duplicates if specified + if (options.nodupes === true) { + result = [...new Set(result)]; + } + + return result; +}; + +/** + * Processes a brace pattern and returns either an expanded array + * (if `options.expand` is true), a highly optimized regex-compatible string. + * This method is called by the main [braces](#braces) function. + * + * ```js + * const braces = require('braces'); + * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) + * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' + * ``` + * @param {String} `pattern` Brace pattern + * @param {Object} `options` + * @return {Array} Returns an array of expanded values. + * @api public + */ + +braces.create = (input, options = {}) => { + if (input === '' || input.length < 3) { + return [input]; + } + + return options.expand !== true + ? braces.compile(input, options) + : braces.expand(input, options); +}; + +/** + * Expose "braces" + */ + +module.exports = braces; + + +/***/ }), +/* 191 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const utils = __webpack_require__(192); + +module.exports = (ast, options = {}) => { + let stringify = (node, parent = {}) => { + let invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); + let invalidNode = node.invalid === true && options.escapeInvalid === true; + let output = ''; + + if (node.value) { + if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { + return '\\' + node.value; + } + return node.value; + } + + if (node.value) { + return node.value; + } + + if (node.nodes) { + for (let child of node.nodes) { + output += stringify(child); + } + } + return output; + }; + + return stringify(ast); +}; + + + +/***/ }), +/* 192 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +exports.isInteger = num => { + if (typeof num === 'number') { + return Number.isInteger(num); + } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isInteger(Number(num)); + } + return false; +}; + +/** + * Find a node of the given type + */ + +exports.find = (node, type) => node.nodes.find(node => node.type === type); + +/** + * Find a node of the given type + */ + +exports.exceedsLimit = (min, max, step = 1, limit) => { + if (limit === false) return false; + if (!exports.isInteger(min) || !exports.isInteger(max)) return false; + return ((Number(max) - Number(min)) / Number(step)) >= limit; +}; + +/** + * Escape the given node with '\\' before node.value + */ + +exports.escapeNode = (block, n = 0, type) => { + let node = block.nodes[n]; + if (!node) return; + + if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { + if (node.escaped !== true) { + node.value = '\\' + node.value; + node.escaped = true; + } + } +}; + +/** + * Returns true if the given brace node should be enclosed in literal braces + */ + +exports.encloseBrace = node => { + if (node.type !== 'brace') return false; + if ((node.commas >> 0 + node.ranges >> 0) === 0) { + node.invalid = true; + return true; + } + return false; +}; + +/** + * Returns true if a brace node is invalid. + */ + +exports.isInvalidBrace = block => { + if (block.type !== 'brace') return false; + if (block.invalid === true || block.dollar) return true; + if ((block.commas >> 0 + block.ranges >> 0) === 0) { + block.invalid = true; + return true; + } + if (block.open !== true || block.close !== true) { + block.invalid = true; + return true; + } + return false; +}; + +/** + * Returns true if a node is an open or close node + */ + +exports.isOpenOrClose = node => { + if (node.type === 'open' || node.type === 'close') { + return true; + } + return node.open === true || node.close === true; +}; + +/** + * Reduce an array of text nodes. + */ + +exports.reduce = nodes => nodes.reduce((acc, node) => { + if (node.type === 'text') acc.push(node.value); + if (node.type === 'range') node.type = 'text'; + return acc; +}, []); + +/** + * Flatten an array + */ + +exports.flatten = (...args) => { + const result = []; + const flat = arr => { + for (let i = 0; i < arr.length; i++) { + let ele = arr[i]; + Array.isArray(ele) ? flat(ele, result) : ele !== void 0 && result.push(ele); + } + return result; + }; + flat(args); + return result; +}; + + +/***/ }), +/* 193 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const fill = __webpack_require__(194); +const utils = __webpack_require__(192); + +const compile = (ast, options = {}) => { + let walk = (node, parent = {}) => { + let invalidBlock = utils.isInvalidBrace(parent); + let invalidNode = node.invalid === true && options.escapeInvalid === true; + let invalid = invalidBlock === true || invalidNode === true; + let prefix = options.escapeInvalid === true ? '\\' : ''; + let output = ''; + + if (node.isOpen === true) { + return prefix + node.value; + } + if (node.isClose === true) { + return prefix + node.value; + } + + if (node.type === 'open') { + return invalid ? (prefix + node.value) : '('; + } + + if (node.type === 'close') { + return invalid ? (prefix + node.value) : ')'; + } + + if (node.type === 'comma') { + return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|'); + } + + if (node.value) { + return node.value; + } + + if (node.nodes && node.ranges > 0) { + let args = utils.reduce(node.nodes); + let range = fill(...args, { ...options, wrap: false, toRegex: true }); + + if (range.length !== 0) { + return args.length > 1 && range.length > 1 ? `(${range})` : range; + } + } + + if (node.nodes) { + for (let child of node.nodes) { + output += walk(child, node); + } + } + return output; + }; + + return walk(ast); +}; + +module.exports = compile; + + +/***/ }), +/* 194 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * fill-range + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. + */ + + + +const util = __webpack_require__(29); +const toRegexRange = __webpack_require__(195); + +const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); + +const transform = toNumber => { + return value => toNumber === true ? Number(value) : String(value); +}; + +const isValidValue = value => { + return typeof value === 'number' || (typeof value === 'string' && value !== ''); +}; + +const isNumber = num => Number.isInteger(+num); + +const zeros = input => { + let value = `${input}`; + let index = -1; + if (value[0] === '-') value = value.slice(1); + if (value === '0') return false; + while (value[++index] === '0'); + return index > 0; +}; + +const stringify = (start, end, options) => { + if (typeof start === 'string' || typeof end === 'string') { + return true; + } + return options.stringify === true; +}; + +const pad = (input, maxLength, toNumber) => { + if (maxLength > 0) { + let dash = input[0] === '-' ? '-' : ''; + if (dash) input = input.slice(1); + input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); + } + if (toNumber === false) { + return String(input); + } + return input; +}; + +const toMaxLen = (input, maxLength) => { + let negative = input[0] === '-' ? '-' : ''; + if (negative) { + input = input.slice(1); + maxLength--; + } + while (input.length < maxLength) input = '0' + input; + return negative ? ('-' + input) : input; +}; + +const toSequence = (parts, options) => { + parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); + parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); + + let prefix = options.capture ? '' : '?:'; + let positives = ''; + let negatives = ''; + let result; + + if (parts.positives.length) { + positives = parts.positives.join('|'); + } + + if (parts.negatives.length) { + negatives = `-(${prefix}${parts.negatives.join('|')})`; + } + + if (positives && negatives) { + result = `${positives}|${negatives}`; + } else { + result = positives || negatives; + } + + if (options.wrap) { + return `(${prefix}${result})`; + } + + return result; +}; + +const toRange = (a, b, isNumbers, options) => { + if (isNumbers) { + return toRegexRange(a, b, { wrap: false, ...options }); + } + + let start = String.fromCharCode(a); + if (a === b) return start; + + let stop = String.fromCharCode(b); + return `[${start}-${stop}]`; +}; + +const toRegex = (start, end, options) => { + if (Array.isArray(start)) { + let wrap = options.wrap === true; + let prefix = options.capture ? '' : '?:'; + return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); + } + return toRegexRange(start, end, options); +}; + +const rangeError = (...args) => { + return new RangeError('Invalid range arguments: ' + util.inspect(...args)); +}; + +const invalidRange = (start, end, options) => { + if (options.strictRanges === true) throw rangeError([start, end]); + return []; +}; + +const invalidStep = (step, options) => { + if (options.strictRanges === true) { + throw new TypeError(`Expected step "${step}" to be a number`); + } + return []; +}; + +const fillNumbers = (start, end, step = 1, options = {}) => { + let a = Number(start); + let b = Number(end); + + if (!Number.isInteger(a) || !Number.isInteger(b)) { + if (options.strictRanges === true) throw rangeError([start, end]); + return []; + } + + // fix negative zero + if (a === 0) a = 0; + if (b === 0) b = 0; + + let descending = a > b; + let startString = String(start); + let endString = String(end); + let stepString = String(step); + step = Math.max(Math.abs(step), 1); + + let padded = zeros(startString) || zeros(endString) || zeros(stepString); + let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; + let toNumber = padded === false && stringify(start, end, options) === false; + let format = options.transform || transform(toNumber); + + if (options.toRegex && step === 1) { + return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); + } + + let parts = { negatives: [], positives: [] }; + let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); + let range = []; + let index = 0; + + while (descending ? a >= b : a <= b) { + if (options.toRegex === true && step > 1) { + push(a); + } else { + range.push(pad(format(a, index), maxLen, toNumber)); + } + a = descending ? a - step : a + step; + index++; + } + + if (options.toRegex === true) { + return step > 1 + ? toSequence(parts, options) + : toRegex(range, null, { wrap: false, ...options }); + } + + return range; +}; + +const fillLetters = (start, end, step = 1, options = {}) => { + if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { + return invalidRange(start, end, options); + } + + + let format = options.transform || (val => String.fromCharCode(val)); + let a = `${start}`.charCodeAt(0); + let b = `${end}`.charCodeAt(0); + + let descending = a > b; + let min = Math.min(a, b); + let max = Math.max(a, b); + + if (options.toRegex && step === 1) { + return toRange(min, max, false, options); + } + + let range = []; + let index = 0; + + while (descending ? a >= b : a <= b) { + range.push(format(a, index)); + a = descending ? a - step : a + step; + index++; + } + + if (options.toRegex === true) { + return toRegex(range, null, { wrap: false, options }); + } + + return range; +}; + +const fill = (start, end, step, options = {}) => { + if (end == null && isValidValue(start)) { + return [start]; + } + + if (!isValidValue(start) || !isValidValue(end)) { + return invalidRange(start, end, options); + } + + if (typeof step === 'function') { + return fill(start, end, 1, { transform: step }); + } + + if (isObject(step)) { + return fill(start, end, 0, step); + } + + let opts = { ...options }; + if (opts.capture === true) opts.wrap = true; + step = step || opts.step || 1; + + if (!isNumber(step)) { + if (step != null && !isObject(step)) return invalidStep(step, opts); + return fill(start, end, 1, step); + } + + if (isNumber(start) && isNumber(end)) { + return fillNumbers(start, end, step, opts); + } + + return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); +}; + +module.exports = fill; + + +/***/ }), +/* 195 */ +/***/ (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__(196); + +const toRegexRange = (min, max, options) => { + if (isNumber(min) === false) { + throw new TypeError('toRegexRange: expected the first argument to be a number'); + } + + if (max === void 0 || min === max) { + return String(min); + } + + if (isNumber(max) === false) { + throw new TypeError('toRegexRange: expected the second argument to be a number.'); + } + + let opts = { relaxZeros: true, ...options }; + if (typeof opts.strictZeros === 'boolean') { + opts.relaxZeros = opts.strictZeros === false; + } + + 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; + } + + 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; + } + 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; + } + + if (b >= 0) { + positives = splitToPatterns(a, b, state, opts); + } + + 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})`; + } + + toRegexRange.cache[cacheKey] = state; + return state.result; +}; + +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 }; + } + + 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; + + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit, options); + + } else { + count++; + } + } + + if (count) { + pattern += options.shorthand === true ? '\\d' : '[0-9]'; + } + + 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 = ''; + + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.count.length > 1) { + prev.count.pop(); + } + + 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); + } + + obj.string = zeros + obj.pattern + toQuantifier(obj.count); + tokens.push(obj); + start = max + 1; + prev = obj; + } + + return tokens; +} + +function filterPatterns(arr, comparison, prefix, intersection, options) { + let result = []; + + for (let ele of arr) { + let { string } = ele; + + // only push if _both_ are negative... + if (!intersection && !contains(comparison, 'string', string)) { + result.push(prefix + string); + } + + // or _both_ are positive + if (intersection && contains(comparison, 'string', string)) { + result.push(prefix + string); + } + } + 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; + + 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}}`; + } + } +} + +/** + * Cache + */ + +toRegexRange.cache = {}; +toRegexRange.clearCache = () => (toRegexRange.cache = {}); + +/** + * Expose `toRegexRange` + */ + +module.exports = toRegexRange; + + +/***/ }), +/* 196 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ + + + +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; +}; + + +/***/ }), +/* 197 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const fill = __webpack_require__(194); +const stringify = __webpack_require__(191); +const utils = __webpack_require__(192); + +const append = (queue = '', stash = '', enclose = false) => { + let result = []; + + queue = [].concat(queue); + stash = [].concat(stash); + + if (!stash.length) return queue; + if (!queue.length) { + return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; + } + + for (let item of queue) { + if (Array.isArray(item)) { + for (let value of item) { + result.push(append(value, stash, enclose)); + } + } else { + for (let ele of stash) { + if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; + result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele)); + } + } + } + return utils.flatten(result); +}; + +const expand = (ast, options = {}) => { + let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; + + let walk = (node, parent = {}) => { + node.queue = []; + + let p = parent; + let q = parent.queue; + + while (p.type !== 'brace' && p.type !== 'root' && p.parent) { + p = p.parent; + q = p.queue; + } + + if (node.invalid || node.dollar) { + q.push(append(q.pop(), stringify(node, options))); + return; + } + + if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { + q.push(append(q.pop(), ['{}'])); + return; + } + + if (node.nodes && node.ranges > 0) { + let args = utils.reduce(node.nodes); + + if (utils.exceedsLimit(...args, options.step, rangeLimit)) { + throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + } + + let range = fill(...args, options); + if (range.length === 0) { + range = stringify(node, options); + } + + q.push(append(q.pop(), range)); + node.nodes = []; + return; + } + + let enclose = utils.encloseBrace(node); + let queue = node.queue; + let block = node; + + while (block.type !== 'brace' && block.type !== 'root' && block.parent) { + block = block.parent; + queue = block.queue; + } + + for (let i = 0; i < node.nodes.length; i++) { + let child = node.nodes[i]; + + if (child.type === 'comma' && node.type === 'brace') { + if (i === 1) queue.push(''); + queue.push(''); + continue; + } + + if (child.type === 'close') { + q.push(append(q.pop(), queue, enclose)); + continue; + } + + if (child.value && child.type !== 'open') { + queue.push(append(queue.pop(), child.value)); + continue; + } + + if (child.nodes) { + walk(child, node); + } + } + + return queue; + }; + + return utils.flatten(walk(ast)); +}; + +module.exports = expand; + + +/***/ }), +/* 198 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const stringify = __webpack_require__(191); + +/** + * Constants + */ + +const { + MAX_LENGTH, + CHAR_BACKSLASH, /* \ */ + CHAR_BACKTICK, /* ` */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_RIGHT_SQUARE_BRACKET, /* ] */ + CHAR_DOUBLE_QUOTE, /* " */ + CHAR_SINGLE_QUOTE, /* ' */ + CHAR_NO_BREAK_SPACE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE +} = __webpack_require__(199); + +/** + * parse + */ + +const parse = (input, options = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); + } + + let opts = options || {}; + let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + if (input.length > max) { + throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); + } + + let ast = { type: 'root', input, nodes: [] }; + let stack = [ast]; + let block = ast; + let prev = ast; + let brackets = 0; + let length = input.length; + let index = 0; + let depth = 0; + let value; + let memo = {}; + + /** + * Helpers + */ + + const advance = () => input[index++]; + const push = node => { + if (node.type === 'text' && prev.type === 'dot') { + prev.type = 'text'; + } + + if (prev && prev.type === 'text' && node.type === 'text') { + prev.value += node.value; + return; + } + + block.nodes.push(node); + node.parent = block; + node.prev = prev; + prev = node; + return node; + }; + + push({ type: 'bos' }); + + while (index < length) { + block = stack[stack.length - 1]; + value = advance(); + + /** + * Invalid chars + */ + + if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { + continue; + } + + /** + * Escaped chars + */ + + if (value === CHAR_BACKSLASH) { + push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); + continue; + } + + /** + * Right square bracket (literal): ']' + */ + + if (value === CHAR_RIGHT_SQUARE_BRACKET) { + push({ type: 'text', value: '\\' + value }); + continue; + } + + /** + * Left square bracket: '[' + */ + + if (value === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + + let closed = true; + let next; + + while (index < length && (next = advance())) { + value += next; + + if (next === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + continue; + } + + if (next === CHAR_BACKSLASH) { + value += advance(); + continue; + } + + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + brackets--; + + if (brackets === 0) { + break; + } + } + } + + push({ type: 'text', value }); + continue; + } + + /** + * Parentheses + */ + + if (value === CHAR_LEFT_PARENTHESES) { + block = push({ type: 'paren', nodes: [] }); + stack.push(block); + push({ type: 'text', value }); + continue; + } + + if (value === CHAR_RIGHT_PARENTHESES) { + if (block.type !== 'paren') { + push({ type: 'text', value }); + continue; + } + block = stack.pop(); + push({ type: 'text', value }); + block = stack[stack.length - 1]; + continue; + } + + /** + * Quotes: '|"|` + */ + + if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { + let open = value; + let next; + + if (options.keepQuotes !== true) { + value = ''; + } + + while (index < length && (next = advance())) { + if (next === CHAR_BACKSLASH) { + value += next + advance(); + continue; + } + + if (next === open) { + if (options.keepQuotes === true) value += next; + break; + } + + value += next; + } + + push({ type: 'text', value }); + continue; + } + + /** + * Left curly brace: '{' + */ + + if (value === CHAR_LEFT_CURLY_BRACE) { + depth++; + + let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; + let brace = { + type: 'brace', + open: true, + close: false, + dollar, + depth, + commas: 0, + ranges: 0, + nodes: [] + }; + + block = push(brace); + stack.push(block); + push({ type: 'open', value }); + continue; + } + + /** + * Right curly brace: '}' + */ + + if (value === CHAR_RIGHT_CURLY_BRACE) { + if (block.type !== 'brace') { + push({ type: 'text', value }); + continue; + } + + let type = 'close'; + block = stack.pop(); + block.close = true; + + push({ type, value }); + depth--; + + block = stack[stack.length - 1]; + continue; + } + + /** + * Comma: ',' + */ + + if (value === CHAR_COMMA && depth > 0) { + if (block.ranges > 0) { + block.ranges = 0; + let open = block.nodes.shift(); + block.nodes = [open, { type: 'text', value: stringify(block) }]; + } + + push({ type: 'comma', value }); + block.commas++; + continue; + } + + /** + * Dot: '.' + */ + + if (value === CHAR_DOT && depth > 0 && block.commas === 0) { + let siblings = block.nodes; + + if (depth === 0 || siblings.length === 0) { + push({ type: 'text', value }); + continue; + } + + if (prev.type === 'dot') { + block.range = []; + prev.value += value; + prev.type = 'range'; + + if (block.nodes.length !== 3 && block.nodes.length !== 5) { + block.invalid = true; + block.ranges = 0; + prev.type = 'text'; + continue; + } + + block.ranges++; + block.args = []; + continue; + } + + if (prev.type === 'range') { + siblings.pop(); + + let before = siblings[siblings.length - 1]; + before.value += prev.value + value; + prev = before; + block.ranges--; + continue; + } + + push({ type: 'dot', value }); + continue; + } + + /** + * Text + */ + + push({ type: 'text', value }); + } + + // Mark imbalanced braces and brackets as invalid + do { + block = stack.pop(); + + if (block.type !== 'root') { + block.nodes.forEach(node => { + if (!node.nodes) { + if (node.type === 'open') node.isOpen = true; + if (node.type === 'close') node.isClose = true; + if (!node.nodes) node.type = 'text'; + node.invalid = true; + } + }); + + // get the location of the block on parent.nodes (block's siblings) + let parent = stack[stack.length - 1]; + let index = parent.nodes.indexOf(block); + // replace the (invalid) block with it's nodes + parent.nodes.splice(index, 1, ...block.nodes); + } + } while (stack.length > 0); + + push({ type: 'eos' }); + return ast; +}; + +module.exports = parse; + + +/***/ }), +/* 199 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = { + MAX_LENGTH: 1024 * 64, + + // Digits + CHAR_0: '0', /* 0 */ + CHAR_9: '9', /* 9 */ + + // Alphabet chars. + CHAR_UPPERCASE_A: 'A', /* A */ + CHAR_LOWERCASE_A: 'a', /* a */ + CHAR_UPPERCASE_Z: 'Z', /* Z */ + CHAR_LOWERCASE_Z: 'z', /* z */ + + CHAR_LEFT_PARENTHESES: '(', /* ( */ + CHAR_RIGHT_PARENTHESES: ')', /* ) */ + + CHAR_ASTERISK: '*', /* * */ + + // Non-alphabetic chars. + CHAR_AMPERSAND: '&', /* & */ + CHAR_AT: '@', /* @ */ + CHAR_BACKSLASH: '\\', /* \ */ + CHAR_BACKTICK: '`', /* ` */ + CHAR_CARRIAGE_RETURN: '\r', /* \r */ + CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ + CHAR_COLON: ':', /* : */ + CHAR_COMMA: ',', /* , */ + CHAR_DOLLAR: '$', /* . */ + CHAR_DOT: '.', /* . */ + CHAR_DOUBLE_QUOTE: '"', /* " */ + CHAR_EQUAL: '=', /* = */ + CHAR_EXCLAMATION_MARK: '!', /* ! */ + CHAR_FORM_FEED: '\f', /* \f */ + CHAR_FORWARD_SLASH: '/', /* / */ + CHAR_HASH: '#', /* # */ + CHAR_HYPHEN_MINUS: '-', /* - */ + CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ + CHAR_LEFT_CURLY_BRACE: '{', /* { */ + CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ + CHAR_LINE_FEED: '\n', /* \n */ + CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ + CHAR_PERCENT: '%', /* % */ + CHAR_PLUS: '+', /* + */ + CHAR_QUESTION_MARK: '?', /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ + CHAR_RIGHT_CURLY_BRACE: '}', /* } */ + CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ + CHAR_SEMICOLON: ';', /* ; */ + CHAR_SINGLE_QUOTE: '\'', /* ' */ + CHAR_SPACE: ' ', /* */ + CHAR_TAB: '\t', /* \t */ + CHAR_UNDERSCORE: '_', /* _ */ + CHAR_VERTICAL_LINE: '|', /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ +}; + + +/***/ }), +/* 200 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = __webpack_require__(201); + + +/***/ }), +/* 201 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const path = __webpack_require__(16); +const scan = __webpack_require__(202); +const parse = __webpack_require__(205); +const utils = __webpack_require__(203); + +/** + * Creates a matcher function from one or more glob patterns. The + * returned function takes a string to match as its first argument, + * and returns true if the string is a match. The returned matcher + * function also takes a boolean as the second argument that, when true, + * returns an object with additional information. + * + * ```js + * const picomatch = require('picomatch'); + * // picomatch(glob[, options]); + * + * const isMatch = picomatch('*.!(*a)'); + * console.log(isMatch('a.a')); //=> false + * console.log(isMatch('a.b')); //=> true + * ``` + * @name picomatch + * @param {String|Array} `globs` One or more glob patterns. + * @param {Object=} `options` + * @return {Function=} Returns a matcher function. + * @api public + */ + +const picomatch = (glob, options, returnState = false) => { + if (Array.isArray(glob)) { + let fns = glob.map(input => picomatch(input, options, returnState)); + return str => { + for (let isMatch of fns) { + let state = isMatch(str); + if (state) return state; + } + return false; + }; + } + + if (typeof glob !== 'string' || glob === '') { + throw new TypeError('Expected pattern to be a non-empty string'); + } + + let opts = options || {}; + let posix = utils.isWindows(options); + let regex = picomatch.makeRe(glob, options, false, true); + let state = regex.state; + delete regex.state; + + let isIgnored = () => false; + if (opts.ignore) { + let ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; + isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); + } + + const matcher = (input, returnObject = false) => { + let { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); + let result = { glob, state, regex, posix, input, output, match, isMatch }; + + if (typeof opts.onResult === 'function') { + opts.onResult(result); + } + + if (isMatch === false) { + result.isMatch = false; + return returnObject ? result : false; + } + + if (isIgnored(input)) { + if (typeof opts.onIgnore === 'function') { + opts.onIgnore(result); + } + result.isMatch = false; + return returnObject ? result : false; + } + + if (typeof opts.onMatch === 'function') { + opts.onMatch(result); + } + return returnObject ? result : true; + }; + + if (returnState) { + matcher.state = state; + } + + return matcher; +}; + +/** + * Test `input` with the given `regex`. This is used by the main + * `picomatch()` function to test the input string. + * + * ```js + * const picomatch = require('picomatch'); + * // picomatch.test(input, regex[, options]); + * + * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); + * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } + * ``` + * @param {String} `input` String to test. + * @param {RegExp} `regex` + * @return {Object} Returns an object with matching info. + * @api public + */ + +picomatch.test = (input, regex, options, { glob, posix } = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected input to be a string'); + } + + if (input === '') { + return { isMatch: false, output: '' }; + } + + let opts = options || {}; + let format = opts.format || (posix ? utils.toPosixSlashes : null); + let match = input === glob; + let output = (match && format) ? format(input) : input; + + if (match === false) { + output = format ? format(input) : input; + match = output === glob; + } + + if (match === false || opts.capture === true) { + if (opts.matchBase === true || opts.basename === true) { + match = picomatch.matchBase(input, regex, options, posix); + } else { + match = regex.exec(output); + } + } + + return { isMatch: !!match, match, output }; +}; + +/** + * Match the basename of a filepath. + * + * ```js + * const picomatch = require('picomatch'); + * // picomatch.matchBase(input, glob[, options]); + * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true + * ``` + * @param {String} `input` String to test. + * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe). + * @return {Boolean} + * @api public + */ + +picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { + let regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); + return regex.test(path.basename(input)); +}; + +/** + * Returns true if **any** of the given glob `patterns` match the specified `string`. + * + * ```js + * const picomatch = require('picomatch'); + * // picomatch.isMatch(string, patterns[, options]); + * + * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true + * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false + * ``` + * @param {String|Array} str The string to test. + * @param {String|Array} patterns One or more glob patterns to use for matching. + * @param {Object} [options] See available [options](#options). + * @return {Boolean} Returns true if any patterns match `str` + * @api public + */ + +picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); + +/** + * Parse a glob pattern to create the source string for a regular + * expression. + * + * ```js + * const picomatch = require('picomatch'); + * const result = picomatch.parse(glob[, options]); + * ``` + * @param {String} `glob` + * @param {Object} `options` + * @return {Object} Returns an object with useful properties and output to be used as a regex source string. + * @api public + */ + +picomatch.parse = (glob, options) => parse(glob, options); + +/** + * Scan a glob pattern to separate the pattern into segments. + * + * ```js + * const picomatch = require('picomatch'); + * // picomatch.scan(input[, options]); + * + * const result = picomatch.scan('!./foo/*.js'); + * console.log(result); + * // { prefix: '!./', + * // input: '!./foo/*.js', + * // base: 'foo', + * // glob: '*.js', + * // negated: true, + * // isGlob: true } + * ``` + * @param {String} `input` Glob pattern to scan. + * @param {Object} `options` + * @return {Object} Returns an object with + * @api public + */ + +picomatch.scan = (input, options) => scan(input, options); + +/** + * Create a regular expression from a glob pattern. + * + * ```js + * const picomatch = require('picomatch'); + * // picomatch.makeRe(input[, options]); + * + * console.log(picomatch.makeRe('*.js')); + * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ + * ``` + * @param {String} `input` A glob pattern to convert to regex. + * @param {Object} `options` + * @return {RegExp} Returns a regex created from the given pattern. + * @api public + */ + +picomatch.makeRe = (input, options, returnOutput = false, returnState = false) => { + if (!input || typeof input !== 'string') { + throw new TypeError('Expected a non-empty string'); + } + + let opts = options || {}; + let prepend = opts.contains ? '' : '^'; + let append = opts.contains ? '' : '$'; + let state = { negated: false, fastpaths: true }; + let prefix = ''; + let output; + + if (input.startsWith('./')) { + input = input.slice(2); + prefix = state.prefix = './'; + } + + if (opts.fastpaths !== false && (input[0] === '.' || input[0] === '*')) { + output = parse.fastpaths(input, options); + } + + if (output === void 0) { + state = picomatch.parse(input, options); + state.prefix = prefix + (state.prefix || ''); + output = state.output; + } + + if (returnOutput === true) { + return output; + } + + let source = `${prepend}(?:${output})${append}`; + if (state && state.negated === true) { + source = `^(?!${source}).*$`; + } + + let regex = picomatch.toRegex(source, options); + if (returnState === true) { + regex.state = state; + } + + return regex; +}; + +/** + * Create a regular expression from the given regex source string. + * + * ```js + * const picomatch = require('picomatch'); + * // picomatch.toRegex(source[, options]); + * + * const { output } = picomatch.parse('*.js'); + * console.log(picomatch.toRegex(output)); + * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ + * ``` + * @param {String} `source` Regular expression source string. + * @param {Object} `options` + * @return {RegExp} + * @api public + */ + +picomatch.toRegex = (source, options) => { + try { + let opts = options || {}; + return new RegExp(source, opts.flags || (opts.nocase ? 'i' : '')); + } catch (err) { + if (options && options.debug === true) throw err; + return /$^/; + } +}; + +/** + * Picomatch constants. + * @return {Object} + */ + +picomatch.constants = __webpack_require__(204); + +/** + * Expose "picomatch" + */ + +module.exports = picomatch; + + +/***/ }), +/* 202 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const utils = __webpack_require__(203); + +const { + CHAR_ASTERISK, /* * */ + CHAR_AT, /* @ */ + CHAR_BACKWARD_SLASH, /* \ */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_EXCLAMATION_MARK, /* ! */ + CHAR_FORWARD_SLASH, /* / */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_PLUS, /* + */ + CHAR_QUESTION_MARK, /* ? */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_RIGHT_SQUARE_BRACKET /* ] */ +} = __webpack_require__(204); + +const isPathSeparator = code => { + return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; +}; + +/** + * Quickly scans a glob pattern and returns an object with a handful of + * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists), + * `glob` (the actual pattern), and `negated` (true if the path starts with `!`). + * + * ```js + * const pm = require('picomatch'); + * console.log(pm.scan('foo/bar/*.js')); + * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' } + * ``` + * @param {String} `str` + * @param {Object} `options` + * @return {Object} Returns an object with tokens and regex source string. + * @api public + */ + +module.exports = (input, options) => { + let opts = options || {}; + let length = input.length - 1; + let index = -1; + let start = 0; + let lastIndex = 0; + let isGlob = false; + let backslashes = false; + let negated = false; + let braces = 0; + let prev; + let code; + + let braceEscaped = false; + + let eos = () => index >= length; + let advance = () => { + prev = code; + return input.charCodeAt(++index); + }; + + while (index < length) { + code = advance(); + let next; + + if (code === CHAR_BACKWARD_SLASH) { + backslashes = true; + next = advance(); + + if (next === CHAR_LEFT_CURLY_BRACE) { + braceEscaped = true; + } + continue; + } + + if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { + braces++; + + while (!eos() && (next = advance())) { + if (next === CHAR_BACKWARD_SLASH) { + backslashes = true; + next = advance(); + continue; + } + + if (next === CHAR_LEFT_CURLY_BRACE) { + braces++; + continue; + } + + if (!braceEscaped && next === CHAR_DOT && (next = advance()) === CHAR_DOT) { + isGlob = true; + break; + } + + if (!braceEscaped && next === CHAR_COMMA) { + isGlob = true; + break; + } + + if (next === CHAR_RIGHT_CURLY_BRACE) { + braces--; + if (braces === 0) { + braceEscaped = false; + break; + } + } + } + } + + if (code === CHAR_FORWARD_SLASH) { + if (prev === CHAR_DOT && index === (start + 1)) { + start += 2; + continue; + } + + lastIndex = index + 1; + continue; + } + + if (code === CHAR_ASTERISK) { + isGlob = true; + break; + } + + if (code === CHAR_ASTERISK || code === CHAR_QUESTION_MARK) { + isGlob = true; + break; + } + + if (code === CHAR_LEFT_SQUARE_BRACKET) { + while (!eos() && (next = advance())) { + if (next === CHAR_BACKWARD_SLASH) { + backslashes = true; + next = advance(); + continue; + } + + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + isGlob = true; + break; + } + } + } + + let isExtglobChar = code === CHAR_PLUS + || code === CHAR_AT + || code === CHAR_EXCLAMATION_MARK; + + if (isExtglobChar && input.charCodeAt(index + 1) === CHAR_LEFT_PARENTHESES) { + isGlob = true; + break; + } + + if (code === CHAR_EXCLAMATION_MARK && index === start) { + negated = true; + start++; + continue; + } + + if (code === CHAR_LEFT_PARENTHESES) { + while (!eos() && (next = advance())) { + if (next === CHAR_BACKWARD_SLASH) { + backslashes = true; + next = advance(); + continue; + } + + if (next === CHAR_RIGHT_PARENTHESES) { + isGlob = true; + break; + } + } + } + + if (isGlob) { + break; + } + } + + let prefix = ''; + let orig = input; + let base = input; + let glob = ''; + + if (start > 0) { + prefix = input.slice(0, start); + input = input.slice(start); + lastIndex -= start; + } + + if (base && isGlob === true && lastIndex > 0) { + base = input.slice(0, lastIndex); + glob = input.slice(lastIndex); + } else if (isGlob === true) { + base = ''; + glob = input; + } else { + base = input; + } + + if (base && base !== '' && base !== '/' && base !== input) { + if (isPathSeparator(base.charCodeAt(base.length - 1))) { + base = base.slice(0, -1); + } + } + + if (opts.unescape === true) { + if (glob) glob = utils.removeBackslashes(glob); + + if (base && backslashes === true) { + base = utils.removeBackslashes(base); + } + } + + return { prefix, input: orig, base, glob, negated, isGlob }; +}; + + +/***/ }), +/* 203 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const path = __webpack_require__(16); +const win32 = process.platform === 'win32'; +const { + REGEX_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_GLOBAL, + REGEX_REMOVE_BACKSLASH +} = __webpack_require__(204); + +exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); +exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); +exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str); +exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); +exports.toPosixSlashes = str => str.replace(/\\/g, '/'); + +exports.removeBackslashes = str => { + return str.replace(REGEX_REMOVE_BACKSLASH, match => { + return match === '\\' ? '' : match; + }); +} + +exports.supportsLookbehinds = () => { + let segs = process.version.slice(1).split('.'); + if (segs.length === 3 && +segs[0] >= 9 || (+segs[0] === 8 && +segs[1] >= 10)) { + return true; + } + return false; +}; + +exports.isWindows = options => { + if (options && typeof options.windows === 'boolean') { + return options.windows; + } + return win32 === true || path.sep === '\\'; +}; + +exports.escapeLast = (input, char, lastIdx) => { + let idx = input.lastIndexOf(char, lastIdx); + if (idx === -1) return input; + if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1); + return input.slice(0, idx) + '\\' + input.slice(idx); +}; + + +/***/ }), +/* 204 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const path = __webpack_require__(16); +const WIN_SLASH = '\\\\/'; +const WIN_NO_SLASH = `[^${WIN_SLASH}]`; + +/** + * Posix glob regex + */ + +const DOT_LITERAL = '\\.'; +const PLUS_LITERAL = '\\+'; +const QMARK_LITERAL = '\\?'; +const SLASH_LITERAL = '\\/'; +const ONE_CHAR = '(?=.)'; +const QMARK = '[^/]'; +const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; +const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; +const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; +const NO_DOT = `(?!${DOT_LITERAL})`; +const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; +const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; +const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; +const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; +const STAR = `${QMARK}*?`; + +const POSIX_CHARS = { + DOT_LITERAL, + PLUS_LITERAL, + QMARK_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + QMARK, + END_ANCHOR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK_NO_DOT, + STAR, + START_ANCHOR +}; + +/** + * Windows glob regex + */ + +const WINDOWS_CHARS = { + ...POSIX_CHARS, + + SLASH_LITERAL: `[${WIN_SLASH}]`, + QMARK: WIN_NO_SLASH, + STAR: `${WIN_NO_SLASH}*?`, + DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, + NO_DOT: `(?!${DOT_LITERAL})`, + NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, + NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + QMARK_NO_DOT: `[^.${WIN_SLASH}]`, + START_ANCHOR: `(?:^|[${WIN_SLASH}])`, + END_ANCHOR: `(?:[${WIN_SLASH}]|$)` +}; + +/** + * POSIX Bracket Regex + */ + +const POSIX_REGEX_SOURCE = { + alnum: 'a-zA-Z0-9', + alpha: 'a-zA-Z', + ascii: '\\x00-\\x7F', + blank: ' \\t', + cntrl: '\\x00-\\x1F\\x7F', + digit: '0-9', + graph: '\\x21-\\x7E', + lower: 'a-z', + print: '\\x20-\\x7E ', + punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~', + space: ' \\t\\r\\n\\v\\f', + upper: 'A-Z', + word: 'A-Za-z0-9_', + xdigit: 'A-Fa-f0-9' +}; + +module.exports = { + MAX_LENGTH: 1024 * 64, + POSIX_REGEX_SOURCE, + + // regular expressions + REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, + REGEX_NON_SPECIAL_CHAR: /^[^@![\].,$*+?^{}()|\\/]+/, + REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, + REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, + REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, + REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, + + // Replace globs with equivalent patterns to reduce parsing time. + REPLACEMENTS: { + '***': '*', + '**/**': '**', + '**/**/**': '**' + }, + + // Digits + CHAR_0: 48, /* 0 */ + CHAR_9: 57, /* 9 */ + + // Alphabet chars. + CHAR_UPPERCASE_A: 65, /* A */ + CHAR_LOWERCASE_A: 97, /* a */ + CHAR_UPPERCASE_Z: 90, /* Z */ + CHAR_LOWERCASE_Z: 122, /* z */ + + CHAR_LEFT_PARENTHESES: 40, /* ( */ + CHAR_RIGHT_PARENTHESES: 41, /* ) */ + + CHAR_ASTERISK: 42, /* * */ + + // Non-alphabetic chars. + CHAR_AMPERSAND: 38, /* & */ + CHAR_AT: 64, /* @ */ + CHAR_BACKWARD_SLASH: 92, /* \ */ + CHAR_CARRIAGE_RETURN: 13, /* \r */ + CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ + CHAR_COLON: 58, /* : */ + CHAR_COMMA: 44, /* , */ + CHAR_DOT: 46, /* . */ + CHAR_DOUBLE_QUOTE: 34, /* " */ + CHAR_EQUAL: 61, /* = */ + CHAR_EXCLAMATION_MARK: 33, /* ! */ + CHAR_FORM_FEED: 12, /* \f */ + CHAR_FORWARD_SLASH: 47, /* / */ + CHAR_GRAVE_ACCENT: 96, /* ` */ + CHAR_HASH: 35, /* # */ + CHAR_HYPHEN_MINUS: 45, /* - */ + CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ + CHAR_LEFT_CURLY_BRACE: 123, /* { */ + CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ + CHAR_LINE_FEED: 10, /* \n */ + CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ + CHAR_PERCENT: 37, /* % */ + CHAR_PLUS: 43, /* + */ + CHAR_QUESTION_MARK: 63, /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ + CHAR_RIGHT_CURLY_BRACE: 125, /* } */ + CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ + CHAR_SEMICOLON: 59, /* ; */ + CHAR_SINGLE_QUOTE: 39, /* ' */ + CHAR_SPACE: 32, /* */ + CHAR_TAB: 9, /* \t */ + CHAR_UNDERSCORE: 95, /* _ */ + CHAR_VERTICAL_LINE: 124, /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ + + SEP: path.sep, + + /** + * Create EXTGLOB_CHARS + */ + + extglobChars(chars) { + return { + '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, + '?': { type: 'qmark', open: '(?:', close: ')?' }, + '+': { type: 'plus', open: '(?:', close: ')+' }, + '*': { type: 'star', open: '(?:', close: ')*' }, + '@': { type: 'at', open: '(?:', close: ')' } + }; + }, + + /** + * Create GLOB_CHARS + */ + + globChars(win32) { + return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; + } +}; + + +/***/ }), +/* 205 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const utils = __webpack_require__(203); +const constants = __webpack_require__(204); + +/** + * Constants + */ + +const { + MAX_LENGTH, + POSIX_REGEX_SOURCE, + REGEX_NON_SPECIAL_CHAR, + REGEX_SPECIAL_CHARS_BACKREF, + REPLACEMENTS +} = constants; + +/** + * Helpers + */ + +const expandRange = (args, options) => { + if (typeof options.expandRange === 'function') { + return options.expandRange(...args, options); + } + + args.sort(); + let value = `[${args.join('-')}]`; + + try { + /* eslint-disable no-new */ + new RegExp(value); + } catch (ex) { + return args.map(v => utils.escapeRegex(v)).join('..'); + } + + return value; +}; + +const negate = state => { + let count = 1; + + while (state.peek() === '!' && (state.peek(2) !== '(' || state.peek(3) === '?')) { + state.advance(); + state.start++; + count++; + } + + if (count % 2 === 0) { + return false; + } + + state.negated = true; + state.start++; + return true; +}; + +/** + * Create the message for a syntax error + */ + +const syntaxError = (type, char) => { + return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; +}; + +/** + * Parse the given input string. + * @param {String} input + * @param {Object} options + * @return {Object} + */ + +const parse = (input, options) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); + } + + input = REPLACEMENTS[input] || input; + + let opts = { ...options }; + let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + let len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } + + let bos = { type: 'bos', value: '', output: opts.prepend || '' }; + let tokens = [bos]; + + let capture = opts.capture ? '' : '?:'; + let win32 = utils.isWindows(options); + + // create constants based on platform, for windows or posix + const PLATFORM_CHARS = constants.globChars(win32); + const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS); + + const { + DOT_LITERAL, + PLUS_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + DOTS_SLASH, + NO_DOT, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK, + QMARK_NO_DOT, + STAR, + START_ANCHOR + } = PLATFORM_CHARS; + + const globstar = (opts) => { + return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; + }; + + let nodot = opts.dot ? '' : NO_DOT; + let star = opts.bash === true ? globstar(opts) : STAR; + let qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT; + + if (opts.capture) { + star = `(${star})`; + } + + // minimatch options support + if (typeof opts.noext === 'boolean') { + opts.noextglob = opts.noext; + } + + let state = { + index: -1, + start: 0, + consumed: '', + output: '', + backtrack: false, + brackets: 0, + braces: 0, + parens: 0, + quotes: 0, + tokens + }; + + let extglobs = []; + let stack = []; + let prev = bos; + let value; + + /** + * Tokenizing helpers + */ + + const eos = () => state.index === len - 1; + const peek = state.peek = (n = 1) => input[state.index + n]; + const advance = state.advance = () => input[++state.index]; + const append = token => { + state.output += token.output != null ? token.output : token.value; + state.consumed += token.value || ''; + }; + + const increment = type => { + state[type]++; + stack.push(type); + }; + + const decrement = type => { + state[type]--; + stack.pop(); + }; + + /** + * Push tokens onto the tokens array. This helper speeds up + * tokenizing by 1) helping us avoid backtracking as much as possible, + * and 2) helping us avoid creating extra tokens when consecutive + * characters are plain text. This improves performance and simplifies + * lookbehinds. + */ + + const push = tok => { + if (prev.type === 'globstar') { + let isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace'); + let isExtglob = extglobs.length && (tok.type === 'pipe' || tok.type === 'paren'); + if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) { + state.output = state.output.slice(0, -prev.output.length); + prev.type = 'star'; + prev.value = '*'; + prev.output = star; + state.output += prev.output; + } + } + + if (extglobs.length && tok.type !== 'paren' && !EXTGLOB_CHARS[tok.value]) { + extglobs[extglobs.length - 1].inner += tok.value; + } + + if (tok.value || tok.output) append(tok); + if (prev && prev.type === 'text' && tok.type === 'text') { + prev.value += tok.value; + return; + } + + tok.prev = prev; + tokens.push(tok); + prev = tok; + }; + + const extglobOpen = (type, value) => { + let token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' }; + + token.prev = prev; + token.parens = state.parens; + token.output = state.output; + let output = (opts.capture ? '(' : '') + token.open; + + push({ type, value, output: state.output ? '' : ONE_CHAR }); + push({ type: 'paren', extglob: true, value: advance(), output }); + increment('parens'); + extglobs.push(token); + }; + + const extglobClose = token => { + let output = token.close + (opts.capture ? ')' : ''); + + if (token.type === 'negate') { + let extglobStar = star; + + if (token.inner && token.inner.length > 1 && token.inner.includes('/')) { + extglobStar = globstar(opts); + } + + if (extglobStar !== star || eos() || /^\)+$/.test(input.slice(state.index + 1))) { + output = token.close = ')$))' + extglobStar; + } + + if (token.prev.type === 'bos' && eos()) { + state.negatedExtglob = true; + } + } + + push({ type: 'paren', extglob: true, value, output }); + decrement('parens'); + }; + + if (opts.fastpaths !== false && !/(^[*!]|[/{[()\]}"])/.test(input)) { + let backslashes = false; + + let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { + if (first === '\\') { + backslashes = true; + return m; + } + + if (first === '?') { + if (esc) { + return esc + first + (rest ? QMARK.repeat(rest.length) : ''); + } + if (index === 0) { + return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ''); + } + return QMARK.repeat(chars.length); + } + + if (first === '.') { + return DOT_LITERAL.repeat(chars.length); + } + + if (first === '*') { + if (esc) { + return esc + first + (rest ? star : ''); + } + return star; + } + return esc ? m : '\\' + m; + }); + + if (backslashes === true) { + if (opts.unescape === true) { + output = output.replace(/\\/g, ''); + } else { + output = output.replace(/\\+/g, m => { + return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : ''); + }); + } + } + + state.output = output; + return state; + } + + /** + * Tokenize input until we reach end-of-string + */ + + while (!eos()) { + value = advance(); + + if (value === '\u0000') { + continue; + } + + /** + * Escaped characters + */ + + if (value === '\\') { + let next = peek(); + + if (next === '/' && opts.bash !== true) { + continue; + } + + if (next === '.' || next === ';') { + continue; + } + + if (!next) { + value += '\\'; + push({ type: 'text', value }); + continue; + } + + // collapse slashes to reduce potential for exploits + let match = /^\\+/.exec(input.slice(state.index + 1)); + let slashes = 0; + + if (match && match[0].length > 2) { + slashes = match[0].length; + state.index += slashes; + if (slashes % 2 !== 0) { + value += '\\'; + } + } + + if (opts.unescape === true) { + value = advance() || ''; + } else { + value += advance() || ''; + } + + if (state.brackets === 0) { + push({ type: 'text', value }); + continue; + } + } + + /** + * If we're inside a regex character class, continue + * until we reach the closing bracket. + */ + + if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) { + if (opts.posix !== false && value === ':') { + let inner = prev.value.slice(1); + if (inner.includes('[')) { + prev.posix = true; + + if (inner.includes(':')) { + let idx = prev.value.lastIndexOf('['); + let pre = prev.value.slice(0, idx); + let rest = prev.value.slice(idx + 2); + let posix = POSIX_REGEX_SOURCE[rest]; + if (posix) { + prev.value = pre + posix; + state.backtrack = true; + advance(); + + if (!bos.output && tokens.indexOf(prev) === 1) { + bos.output = ONE_CHAR; + } + continue; + } + } + } + } + + if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) { + value = '\\' + value; + } + + if (value === ']' && (prev.value === '[' || prev.value === '[^')) { + value = '\\' + value; + } + + if (opts.posix === true && value === '!' && prev.value === '[') { + value = '^'; + } + + prev.value += value; + append({ value }); + continue; + } + + /** + * If we're inside a quoted string, continue + * until we reach the closing double quote. + */ + + if (state.quotes === 1 && value !== '"') { + value = utils.escapeRegex(value); + prev.value += value; + append({ value }); + continue; + } + + /** + * Double quotes + */ + + if (value === '"') { + state.quotes = state.quotes === 1 ? 0 : 1; + if (opts.keepQuotes === true) { + push({ type: 'text', value }); + } + continue; + } + + /** + * Parentheses + */ + + if (value === '(') { + push({ type: 'paren', value }); + increment('parens'); + continue; + } + + if (value === ')') { + if (state.parens === 0 && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('opening', '(')); + } + + let extglob = extglobs[extglobs.length - 1]; + if (extglob && state.parens === extglob.parens + 1) { + extglobClose(extglobs.pop()); + continue; + } + + push({ type: 'paren', value, output: state.parens ? ')' : '\\)' }); + decrement('parens'); + continue; + } + + /** + * Brackets + */ + + if (value === '[') { + if (opts.nobracket === true || !input.slice(state.index + 1).includes(']')) { + if (opts.nobracket !== true && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('closing', ']')); + } + + value = '\\' + value; + } else { + increment('brackets'); + } + + push({ type: 'bracket', value }); + continue; + } + + if (value === ']') { + if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) { + push({ type: 'text', value, output: '\\' + value }); + continue; + } + + if (state.brackets === 0) { + if (opts.strictBrackets === true) { + throw new SyntaxError(syntaxError('opening', '[')); + } + + push({ type: 'text', value, output: '\\' + value }); + continue; + } + + decrement('brackets'); + + let prevValue = prev.value.slice(1); + if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) { + value = '/' + value; + } + + prev.value += value; + append({ value }); + + // when literal brackets are explicitly disabled + // assume we should match with a regex character class + if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { + continue; + } + + let escaped = utils.escapeRegex(prev.value); + state.output = state.output.slice(0, -prev.value.length); + + // when literal brackets are explicitly enabled + // assume we should escape the brackets to match literal characters + if (opts.literalBrackets === true) { + state.output += escaped; + prev.value = escaped; + continue; + } + + // when the user specifies nothing, try to match both + prev.value = `(${capture}${escaped}|${prev.value})`; + state.output += prev.value; + continue; + } + + /** + * Braces + */ + + if (value === '{' && opts.nobrace !== true) { + push({ type: 'brace', value, output: '(' }); + increment('braces'); + continue; + } + + if (value === '}') { + if (opts.nobrace === true || state.braces === 0) { + push({ type: 'text', value, output: '\\' + value }); + continue; + } + + let output = ')'; + + if (state.dots === true) { + let arr = tokens.slice(); + let range = []; + + for (let i = arr.length - 1; i >= 0; i--) { + tokens.pop(); + if (arr[i].type === 'brace') { + break; + } + if (arr[i].type !== 'dots') { + range.unshift(arr[i].value); + } + } + + output = expandRange(range, opts); + state.backtrack = true; + } + + push({ type: 'brace', value, output }); + decrement('braces'); + continue; + } + + /** + * Pipes + */ + + if (value === '|') { + if (extglobs.length > 0) { + extglobs[extglobs.length - 1].conditions++; + } + push({ type: 'text', value }); + continue; + } + + /** + * Commas + */ + + if (value === ',') { + let output = value; + + if (state.braces > 0 && stack[stack.length - 1] === 'braces') { + output = '|'; + } + + push({ type: 'comma', value, output }); + continue; + } + + /** + * Slashes + */ + + if (value === '/') { + // if the beginning of the glob is "./", advance the start + // to the current index, and don't add the "./" characters + // to the state. This greatly simplifies lookbehinds when + // checking for BOS characters like "!" and "." (not "./") + if (prev.type === 'dot' && state.index === 1) { + state.start = state.index + 1; + state.consumed = ''; + state.output = ''; + tokens.pop(); + prev = bos; // reset "prev" to the first token + continue; + } + + push({ type: 'slash', value, output: SLASH_LITERAL }); + continue; + } + + /** + * Dots + */ + + if (value === '.') { + if (state.braces > 0 && prev.type === 'dot') { + if (prev.value === '.') prev.output = DOT_LITERAL; + prev.type = 'dots'; + prev.output += value; + prev.value += value; + state.dots = true; + continue; + } + + push({ type: 'dot', value, output: DOT_LITERAL }); + continue; + } + + /** + * Question marks + */ + + if (value === '?') { + if (prev && prev.type === 'paren') { + let next = peek(); + let output = value; + + if (next === '<' && !utils.supportsLookbehinds()) { + throw new Error('Node.js v10 or higher is required for regex lookbehinds'); + } + + if (prev.value === '(' && !/[!=<:]/.test(next) || (next === '<' && !/[!=]/.test(peek(2)))) { + output = '\\' + value; + } + + push({ type: 'text', value, output }); + continue; + } + + if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + extglobOpen('qmark', value); + continue; + } + + if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) { + push({ type: 'qmark', value, output: QMARK_NO_DOT }); + continue; + } + + push({ type: 'qmark', value, output: QMARK }); + continue; + } + + /** + * Exclamation + */ + + if (value === '!') { + if (opts.noextglob !== true && peek() === '(') { + if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) { + extglobOpen('negate', value); + continue; + } + } + + if (opts.nonegate !== true && state.index === 0) { + negate(state); + continue; + } + } + + /** + * Plus + */ + + if (value === '+') { + if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + extglobOpen('plus', value); + continue; + } + + if (prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) { + let output = prev.extglob === true ? '\\' + value : value; + push({ type: 'plus', value, output }); + continue; + } + + // use regex behavior inside parens + if (state.parens > 0 && opts.regex !== false) { + push({ type: 'plus', value }); + continue; + } + + push({ type: 'plus', value: PLUS_LITERAL }); + continue; + } + + /** + * Plain text + */ + + if (value === '@') { + if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + push({ type: 'at', value, output: '' }); + continue; + } + + push({ type: 'text', value }); + continue; + } + + /** + * Plain text + */ + + if (value !== '*') { + if (value === '$' || value === '^') { + value = '\\' + value; + } + + let match = REGEX_NON_SPECIAL_CHAR.exec(input.slice(state.index + 1)); + if (match) { + value += match[0]; + state.index += match[0].length; + } + + push({ type: 'text', value }); + continue; + } + + /** + * Stars + */ + + if (prev && (prev.type === 'globstar' || prev.star === true)) { + prev.type = 'star'; + prev.star = true; + prev.value += value; + prev.output = star; + state.backtrack = true; + state.consumed += value; + continue; + } + + if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { + extglobOpen('star', value); + continue; + } + + if (prev.type === 'star') { + if (opts.noglobstar === true) { + state.consumed += value; + continue; + } + + let prior = prev.prev; + let before = prior.prev; + let isStart = prior.type === 'slash' || prior.type === 'bos'; + let afterStar = before && (before.type === 'star' || before.type === 'globstar'); + + if (opts.bash === true && (!isStart || (!eos() && peek() !== '/'))) { + push({ type: 'star', value, output: '' }); + continue; + } + + let isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace'); + let isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren'); + if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) { + push({ type: 'star', value, output: '' }); + continue; + } + + // strip consecutive `/**/` + while (input.slice(state.index + 1, state.index + 4) === '/**') { + let after = input[state.index + 4]; + if (after && after !== '/') { + break; + } + state.consumed += '/**'; + state.index += 3; + } + + if (prior.type === 'bos' && eos()) { + prev.type = 'globstar'; + prev.value += value; + prev.output = globstar(opts); + state.output = prev.output; + state.consumed += value; + continue; + } + + if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) { + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = '(?:' + prior.output; + + prev.type = 'globstar'; + prev.output = globstar(opts) + '|$)'; + prev.value += value; + + state.output += prior.output + prev.output; + state.consumed += value; + continue; + } + + let next = peek(); + if (prior.type === 'slash' && prior.prev.type !== 'bos' && next === '/') { + let end = peek(2) !== void 0 ? '|$' : ''; + + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = '(?:' + prior.output; + + prev.type = 'globstar'; + prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; + prev.value += value; + + state.output += prior.output + prev.output; + state.consumed += value + advance(); + + push({ type: 'slash', value, output: '' }); + continue; + } + + if (prior.type === 'bos' && next === '/') { + prev.type = 'globstar'; + prev.value += value; + prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`; + state.output = prev.output; + state.consumed += value + advance(); + push({ type: 'slash', value, output: '' }); + continue; + } + + // remove single star from output + state.output = state.output.slice(0, -prev.output.length); + + // reset previous token to globstar + prev.type = 'globstar'; + prev.output = globstar(opts); + prev.value += value; + + // reset output with globstar + state.output += prev.output; + state.consumed += value; + continue; + } + + let token = { type: 'star', value, output: star }; + + if (opts.bash === true) { + token.output = '.*?'; + if (prev.type === 'bos' || prev.type === 'slash') { + token.output = nodot + token.output; + } + push(token); + continue; + } + + if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) { + token.output = value; + push(token); + continue; + } + + if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') { + if (prev.type === 'dot') { + state.output += NO_DOT_SLASH; + prev.output += NO_DOT_SLASH; + + } else if (opts.dot === true) { + state.output += NO_DOTS_SLASH; + prev.output += NO_DOTS_SLASH; + + } else { + state.output += nodot; + prev.output += nodot; + } + + if (peek() !== '*') { + state.output += ONE_CHAR; + prev.output += ONE_CHAR; + } + } + + push(token); + } + + while (state.brackets > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']')); + state.output = utils.escapeLast(state.output, '['); + decrement('brackets'); + } + + while (state.parens > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')')); + state.output = utils.escapeLast(state.output, '('); + decrement('parens'); + } + + while (state.braces > 0) { + if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}')); + state.output = utils.escapeLast(state.output, '{'); + decrement('braces'); + } + + if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) { + push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` }); + } + + // rebuild the output if we had to backtrack at any point + if (state.backtrack === true) { + state.output = ''; + + for (let token of state.tokens) { + state.output += token.output != null ? token.output : token.value; + + if (token.suffix) { + state.output += token.suffix; + } + } + } + + return state; +}; + +/** + * Fast paths for creating regular expressions for common glob patterns. + * This can significantly speed up processing and has very little downside + * impact when none of the fast paths match. + */ + +parse.fastpaths = (input, options) => { + let opts = { ...options }; + let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + let len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } + + input = REPLACEMENTS[input] || input; + let win32 = utils.isWindows(options); + + // create constants based on platform, for windows or posix + const { + DOT_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOTS_SLASH, + STAR, + START_ANCHOR + } = constants.globChars(win32); + + let capture = opts.capture ? '' : '?:'; + let star = opts.bash === true ? '.*?' : STAR; + let nodot = opts.dot ? NO_DOTS : NO_DOT; + let slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; + + if (opts.capture) { + star = `(${star})`; + } + + const globstar = (opts) => { + return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; + }; + + const create = str => { + switch (str) { + case '*': + return `${nodot}${ONE_CHAR}${star}`; + + case '.*': + return `${DOT_LITERAL}${ONE_CHAR}${star}`; + + case '*.*': + return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + + case '*/*': + return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; + + case '**': + return nodot + globstar(opts); + + case '**/*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; + + case '**/*.*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; + + case '**/.*': + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; + + default: { + let match = /^(.*?)\.(\w+)$/.exec(str); + if (!match) return; + + let source = create(match[1], options); + if (!source) return; + + return source + DOT_LITERAL + match[2]; + } + } + }; + + let output = create(input); + if (output && opts.strictSlashes !== true) { + output += `${SLASH_LITERAL}?`; + } + + return output; +}; + +module.exports = parse; + + +/***/ }), +/* 206 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const merge2 = __webpack_require__(177); +function merge(streams) { + const mergedStream = merge2(streams); + streams.forEach((stream) => { + stream.once('error', (err) => mergedStream.emit('error', err)); + }); + return mergedStream; +} +exports.merge = merge; + + +/***/ }), +/* 207 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = __webpack_require__(208); +const provider_1 = __webpack_require__(235); +class ProviderAsync extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new stream_1.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const entries = []; + return new Promise((resolve, reject) => { + const stream = this.api(root, task, options); + stream.once('error', reject); + stream.on('data', (entry) => entries.push(options.transform(entry))); + stream.once('end', () => resolve(entries)); + }); + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderAsync; + + +/***/ }), +/* 208 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = __webpack_require__(28); +const fsStat = __webpack_require__(209); +const fsWalk = __webpack_require__(214); +const reader_1 = __webpack_require__(234); +class ReaderStream extends reader_1.default { + constructor() { + super(...arguments); + this._walkStream = fsWalk.walkStream; + this._stat = fsStat.stat; + } + dynamic(root, options) { + return this._walkStream(root, options); + } + static(patterns, options) { + const filepaths = patterns.map(this._getFullEntryPath, this); + const stream = new stream_1.PassThrough({ objectMode: true }); + stream._write = (index, _enc, done) => { + return this._getEntry(filepaths[index], patterns[index], options) + .then((entry) => { + if (entry !== null && options.entryFilter(entry)) { + stream.push(entry); + } + if (index === filepaths.length - 1) { + stream.end(); + } + done(); + }) + .catch(done); + }; + for (let i = 0; i < filepaths.length; i++) { + stream.write(i); + } + return stream; + } + _getEntry(filepath, pattern, options) { + return this._getStat(filepath) + .then((stats) => this._makeEntry(stats, pattern)) + .catch((error) => { + if (options.errorFilter(error)) { + return null; + } + throw error; + }); + } + _getStat(filepath) { + return new Promise((resolve, reject) => { + this._stat(filepath, this._fsStatSettings, (error, stats) => { + error ? reject(error) : resolve(stats); + }); + }); + } +} +exports.default = ReaderStream; + + +/***/ }), +/* 209 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const async = __webpack_require__(210); +const sync = __webpack_require__(211); +const settings_1 = __webpack_require__(212); +exports.Settings = settings_1.default; +function stat(path, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + return async.read(path, getSettings(), optionsOrSettingsOrCallback); + } + async.read(path, getSettings(optionsOrSettingsOrCallback), callback); +} +exports.stat = stat; +function statSync(path, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + return sync.read(path, settings); +} +exports.statSync = statSync; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} + + +/***/ }), +/* 210 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function read(path, settings, callback) { + settings.fs.lstat(path, (lstatError, lstat) => { + if (lstatError) { + return callFailureCallback(callback, lstatError); + } + if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { + return callSuccessCallback(callback, lstat); + } + settings.fs.stat(path, (statError, stat) => { + if (statError) { + if (settings.throwErrorOnBrokenSymbolicLink) { + return callFailureCallback(callback, statError); + } + return callSuccessCallback(callback, lstat); + } + if (settings.markSymbolicLink) { + stat.isSymbolicLink = () => true; + } + callSuccessCallback(callback, stat); + }); + }); +} +exports.read = read; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, result) { + callback(null, result); +} + + +/***/ }), +/* 211 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function read(path, settings) { + const lstat = settings.fs.lstatSync(path); + if (!lstat.isSymbolicLink() || !settings.followSymbolicLink) { + return lstat; + } + try { + const stat = settings.fs.statSync(path); + if (settings.markSymbolicLink) { + stat.isSymbolicLink = () => true; + } + return stat; + } + catch (error) { + if (!settings.throwErrorOnBrokenSymbolicLink) { + return lstat; + } + throw error; + } +} +exports.read = read; + + +/***/ }), +/* 212 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(213); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.followSymbolicLink = this._getValue(this._options.followSymbolicLink, true); + this.fs = fs.createFileSystemAdapter(this._options.fs); + this.markSymbolicLink = this._getValue(this._options.markSymbolicLink, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); + } + _getValue(option, value) { + return option === undefined ? value : option; + } +} +exports.default = Settings; + + +/***/ }), +/* 213 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(23); +exports.FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + stat: fs.stat, + lstatSync: fs.lstatSync, + statSync: fs.statSync +}; +function createFileSystemAdapter(fsMethods) { + if (!fsMethods) { + return exports.FILE_SYSTEM_ADAPTER; + } + return Object.assign({}, exports.FILE_SYSTEM_ADAPTER, fsMethods); +} +exports.createFileSystemAdapter = createFileSystemAdapter; + + +/***/ }), +/* 214 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const async_1 = __webpack_require__(215); +const stream_1 = __webpack_require__(230); +const sync_1 = __webpack_require__(231); +const settings_1 = __webpack_require__(233); +exports.Settings = settings_1.default; +function walk(dir, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + return new async_1.default(dir, getSettings()).read(optionsOrSettingsOrCallback); + } + new async_1.default(dir, getSettings(optionsOrSettingsOrCallback)).read(callback); +} +exports.walk = walk; +function walkSync(dir, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + const provider = new sync_1.default(dir, settings); + return provider.read(); +} +exports.walkSync = walkSync; +function walkStream(dir, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + const provider = new stream_1.default(dir, settings); + return provider.read(); +} +exports.walkStream = walkStream; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} + + +/***/ }), +/* 215 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const async_1 = __webpack_require__(216); +class AsyncProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new async_1.default(this._root, this._settings); + this._storage = new Set(); + } + read(callback) { + this._reader.onError((error) => { + callFailureCallback(callback, error); + }); + this._reader.onEntry((entry) => { + this._storage.add(entry); + }); + this._reader.onEnd(() => { + callSuccessCallback(callback, Array.from(this._storage)); + }); + this._reader.read(); + } +} +exports.default = AsyncProvider; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, entries) { + callback(null, entries); +} + + +/***/ }), +/* 216 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const events_1 = __webpack_require__(46); +const fsScandir = __webpack_require__(217); +const fastq = __webpack_require__(226); +const common = __webpack_require__(228); +const reader_1 = __webpack_require__(229); +class AsyncReader extends reader_1.default { + constructor(_root, _settings) { + super(_root, _settings); + this._settings = _settings; + this._scandir = fsScandir.scandir; + this._emitter = new events_1.EventEmitter(); + this._queue = fastq(this._worker.bind(this), this._settings.concurrency); + this._isFatalError = false; + this._isDestroyed = false; + this._queue.drain = () => { + if (!this._isFatalError) { + this._emitter.emit('end'); + } + }; + } + read() { + this._isFatalError = false; + this._isDestroyed = false; + setImmediate(() => { + this._pushToQueue(this._root, this._settings.basePath); + }); + return this._emitter; + } + destroy() { + if (this._isDestroyed) { + throw new Error('The reader is already destroyed'); + } + this._isDestroyed = true; + this._queue.killAndDrain(); + } + onEntry(callback) { + this._emitter.on('entry', callback); + } + onError(callback) { + this._emitter.once('error', callback); + } + onEnd(callback) { + this._emitter.once('end', callback); + } + _pushToQueue(dir, base) { + const queueItem = { dir, base }; + this._queue.push(queueItem, (error) => { + if (error) { + this._handleError(error); + } + }); + } + _worker(item, done) { + this._scandir(item.dir, this._settings.fsScandirSettings, (error, entries) => { + if (error) { + return done(error, undefined); + } + for (const entry of entries) { + this._handleEntry(entry, item.base); + } + done(null, undefined); + }); + } + _handleError(error) { + if (!common.isFatalError(this._settings, error)) { + return; + } + this._isFatalError = true; + this._isDestroyed = true; + this._emitter.emit('error', error); + } + _handleEntry(entry, base) { + if (this._isDestroyed || this._isFatalError) { + return; + } + const fullpath = entry.path; + if (base !== undefined) { + entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); + } + if (common.isAppliedFilter(this._settings.entryFilter, entry)) { + this._emitEntry(entry); + } + if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { + this._pushToQueue(fullpath, entry.path); + } + } + _emitEntry(entry) { + this._emitter.emit('entry', entry); + } +} +exports.default = AsyncReader; + + +/***/ }), +/* 217 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const async = __webpack_require__(218); +const sync = __webpack_require__(223); +const settings_1 = __webpack_require__(224); +exports.Settings = settings_1.default; +function scandir(path, optionsOrSettingsOrCallback, callback) { + if (typeof optionsOrSettingsOrCallback === 'function') { + return async.read(path, getSettings(), optionsOrSettingsOrCallback); + } + async.read(path, getSettings(optionsOrSettingsOrCallback), callback); +} +exports.scandir = scandir; +function scandirSync(path, optionsOrSettings) { + const settings = getSettings(optionsOrSettings); + return sync.read(path, settings); +} +exports.scandirSync = scandirSync; +function getSettings(settingsOrOptions = {}) { + if (settingsOrOptions instanceof settings_1.default) { + return settingsOrOptions; + } + return new settings_1.default(settingsOrOptions); +} + + +/***/ }), +/* 218 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fsStat = __webpack_require__(209); +const rpl = __webpack_require__(219); +const constants_1 = __webpack_require__(220); +const utils = __webpack_require__(221); +function read(dir, settings, callback) { + if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { + return readdirWithFileTypes(dir, settings, callback); + } + return readdir(dir, settings, callback); +} +exports.read = read; +function readdirWithFileTypes(dir, settings, callback) { + settings.fs.readdir(dir, { withFileTypes: true }, (readdirError, dirents) => { + if (readdirError) { + return callFailureCallback(callback, readdirError); + } + const entries = dirents.map((dirent) => ({ + dirent, + name: dirent.name, + path: `${dir}${settings.pathSegmentSeparator}${dirent.name}` + })); + if (!settings.followSymbolicLinks) { + return callSuccessCallback(callback, entries); + } + const tasks = entries.map((entry) => makeRplTaskEntry(entry, settings)); + rpl(tasks, (rplError, rplEntries) => { + if (rplError) { + return callFailureCallback(callback, rplError); + } + callSuccessCallback(callback, rplEntries); + }); + }); +} +exports.readdirWithFileTypes = readdirWithFileTypes; +function makeRplTaskEntry(entry, settings) { + return (done) => { + if (!entry.dirent.isSymbolicLink()) { + return done(null, entry); + } + settings.fs.stat(entry.path, (statError, stats) => { + if (statError) { + if (settings.throwErrorOnBrokenSymbolicLink) { + return done(statError); + } + return done(null, entry); + } + entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); + return done(null, entry); + }); + }; +} +function readdir(dir, settings, callback) { + settings.fs.readdir(dir, (readdirError, names) => { + if (readdirError) { + return callFailureCallback(callback, readdirError); + } + const filepaths = names.map((name) => `${dir}${settings.pathSegmentSeparator}${name}`); + const tasks = filepaths.map((filepath) => { + return (done) => fsStat.stat(filepath, settings.fsStatSettings, done); + }); + rpl(tasks, (rplError, results) => { + if (rplError) { + return callFailureCallback(callback, rplError); + } + const entries = []; + for (let index = 0; index < names.length; index++) { + const name = names[index]; + const stats = results[index]; + const entry = { + name, + path: filepaths[index], + dirent: utils.fs.createDirentFromStats(name, stats) + }; + if (settings.stats) { + entry.stats = stats; + } + entries.push(entry); + } + callSuccessCallback(callback, entries); + }); + }); +} +exports.readdir = readdir; +function callFailureCallback(callback, error) { + callback(error); +} +function callSuccessCallback(callback, result) { + callback(null, result); +} + + +/***/ }), +/* 219 */ +/***/ (function(module, exports) { + +module.exports = runParallel + +function runParallel (tasks, cb) { + var results, pending, keys + var isSync = true + + if (Array.isArray(tasks)) { + results = [] + pending = tasks.length + } else { + keys = Object.keys(tasks) + results = {} + pending = keys.length + } + + function done (err) { + function end () { + if (cb) cb(err, results) + cb = null + } + if (isSync) process.nextTick(end) + else end() + } + + function each (i, err, result) { + results[i] = result + if (--pending === 0 || err) { + done(err) + } + } + + if (!pending) { + // empty + done(null) + } else if (keys) { + // object + keys.forEach(function (key) { + tasks[key](function (err, result) { each(key, err, result) }) + }) + } else { + // array + tasks.forEach(function (task, i) { + task(function (err, result) { each(i, err, result) }) + }) + } + + isSync = false +} + + +/***/ }), +/* 220 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const NODE_PROCESS_VERSION_PARTS = process.versions.node.split('.'); +const MAJOR_VERSION = parseInt(NODE_PROCESS_VERSION_PARTS[0], 10); +const MINOR_VERSION = parseInt(NODE_PROCESS_VERSION_PARTS[1], 10); +/** + * IS `true` for Node.js 10.10 and greater. + */ +exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = MAJOR_VERSION > 10 || (MAJOR_VERSION === 10 && MINOR_VERSION >= 10); + + +/***/ }), +/* 221 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(222); +exports.fs = fs; + + +/***/ }), +/* 222 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +class DirentFromStats { + constructor(name, stats) { + this.name = name; + this.isBlockDevice = stats.isBlockDevice.bind(stats); + this.isCharacterDevice = stats.isCharacterDevice.bind(stats); + this.isDirectory = stats.isDirectory.bind(stats); + this.isFIFO = stats.isFIFO.bind(stats); + this.isFile = stats.isFile.bind(stats); + this.isSocket = stats.isSocket.bind(stats); + this.isSymbolicLink = stats.isSymbolicLink.bind(stats); + } +} +function createDirentFromStats(name, stats) { + return new DirentFromStats(name, stats); +} +exports.createDirentFromStats = createDirentFromStats; + + +/***/ }), +/* 223 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fsStat = __webpack_require__(209); +const constants_1 = __webpack_require__(220); +const utils = __webpack_require__(221); +function read(dir, settings) { + if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { + return readdirWithFileTypes(dir, settings); + } + return readdir(dir, settings); +} +exports.read = read; +function readdirWithFileTypes(dir, settings) { + const dirents = settings.fs.readdirSync(dir, { withFileTypes: true }); + return dirents.map((dirent) => { + const entry = { + dirent, + name: dirent.name, + path: `${dir}${settings.pathSegmentSeparator}${dirent.name}` + }; + if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) { + try { + const stats = settings.fs.statSync(entry.path); + entry.dirent = utils.fs.createDirentFromStats(entry.name, stats); + } + catch (error) { + if (settings.throwErrorOnBrokenSymbolicLink) { + throw error; + } + } + } + return entry; + }); +} +exports.readdirWithFileTypes = readdirWithFileTypes; +function readdir(dir, settings) { + const names = settings.fs.readdirSync(dir); + return names.map((name) => { + const entryPath = `${dir}${settings.pathSegmentSeparator}${name}`; + const stats = fsStat.statSync(entryPath, settings.fsStatSettings); + const entry = { + name, + path: entryPath, + dirent: utils.fs.createDirentFromStats(name, stats) + }; + if (settings.stats) { + entry.stats = stats; + } + return entry; + }); +} +exports.readdir = readdir; + + +/***/ }), +/* 224 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(16); +const fsStat = __webpack_require__(209); +const fs = __webpack_require__(225); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, false); + this.fs = fs.createFileSystemAdapter(this._options.fs); + this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); + this.stats = this._getValue(this._options.stats, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, true); + this.fsStatSettings = new fsStat.Settings({ + followSymbolicLink: this.followSymbolicLinks, + fs: this.fs, + throwErrorOnBrokenSymbolicLink: this.throwErrorOnBrokenSymbolicLink + }); + } + _getValue(option, value) { + return option === undefined ? value : option; + } +} +exports.default = Settings; + + +/***/ }), +/* 225 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(23); +exports.FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + stat: fs.stat, + lstatSync: fs.lstatSync, + statSync: fs.statSync, + readdir: fs.readdir, + readdirSync: fs.readdirSync +}; +function createFileSystemAdapter(fsMethods) { + if (!fsMethods) { + return exports.FILE_SYSTEM_ADAPTER; + } + return Object.assign({}, exports.FILE_SYSTEM_ADAPTER, fsMethods); +} +exports.createFileSystemAdapter = createFileSystemAdapter; + + +/***/ }), +/* 226 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var reusify = __webpack_require__(227) + +function fastqueue (context, worker, concurrency) { + if (typeof context === 'function') { + concurrency = worker + worker = context + context = null + } + + var cache = reusify(Task) + var queueHead = null + var queueTail = null + var _running = 0 + + var self = { + push: push, + drain: noop, + saturated: noop, + pause: pause, + paused: false, + concurrency: concurrency, + running: running, + resume: resume, + idle: idle, + length: length, + unshift: unshift, + empty: noop, + kill: kill, + killAndDrain: killAndDrain + } + + return self + + function running () { + return _running + } + + function pause () { + self.paused = true + } + + function length () { + var current = queueHead + var counter = 0 + + while (current) { + current = current.next + counter++ + } + + return counter + } + + function resume () { + if (!self.paused) return + self.paused = false + for (var i = 0; i < self.concurrency; i++) { + _running++ + release() + } + } + + function idle () { + return _running === 0 && self.length() === 0 + } + + function push (value, done) { + var current = cache.get() + + current.context = context + current.release = release + current.value = value + current.callback = done || noop + + if (_running === self.concurrency || self.paused) { + if (queueTail) { + queueTail.next = current + queueTail = current + } else { + queueHead = current + queueTail = current + self.saturated() + } + } else { + _running++ + worker.call(context, current.value, current.worked) + } + } + + function unshift (value, done) { + var current = cache.get() + + current.context = context + current.release = release + current.value = value + current.callback = done || noop + + if (_running === self.concurrency || self.paused) { + if (queueHead) { + current.next = queueHead + queueHead = current + } else { + queueHead = current + queueTail = current + self.saturated() + } + } else { + _running++ + worker.call(context, current.value, current.worked) + } + } + + function release (holder) { + if (holder) { + cache.release(holder) + } + var next = queueHead + if (next) { + if (!self.paused) { + if (queueTail === queueHead) { + queueTail = null + } + queueHead = next.next + next.next = null + worker.call(context, next.value, next.worked) + if (queueTail === null) { + self.empty() + } + } else { + _running-- + } + } else if (--_running === 0) { + self.drain() + } + } + + function kill () { + queueHead = null + queueTail = null + self.drain = noop + } + + function killAndDrain () { + queueHead = null + queueTail = null + self.drain() + self.drain = noop + } +} + +function noop () {} + +function Task () { + this.value = null + this.callback = noop + this.next = null + this.release = noop + this.context = null + + var self = this + + this.worked = function worked (err, result) { + var callback = self.callback + self.value = null + self.callback = noop + callback.call(self.context, err, result) + self.release(self) + } +} + +module.exports = fastqueue + + +/***/ }), +/* 227 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +function reusify (Constructor) { + var head = new Constructor() + var tail = head + + function get () { + var current = head + + if (current.next) { + head = current.next + } else { + head = new Constructor() + tail = head + } + + current.next = null + + return current + } + + function release (obj) { + tail.next = obj + tail = obj + } + + return { + get: get, + release: release + } +} + +module.exports = reusify + + +/***/ }), +/* 228 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function isFatalError(settings, error) { + if (settings.errorFilter === null) { + return true; + } + return !settings.errorFilter(error); +} +exports.isFatalError = isFatalError; +function isAppliedFilter(filter, value) { + return filter === null || filter(value); +} +exports.isAppliedFilter = isAppliedFilter; +function replacePathSegmentSeparator(filepath, separator) { + return filepath.split(/[\\\/]/).join(separator); +} +exports.replacePathSegmentSeparator = replacePathSegmentSeparator; +function joinPathSegments(a, b, separator) { + if (a === '') { + return b; + } + return a + separator + b; +} +exports.joinPathSegments = joinPathSegments; + + +/***/ }), +/* 229 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const common = __webpack_require__(228); +class Reader { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._root = common.replacePathSegmentSeparator(_root, _settings.pathSegmentSeparator); + } +} +exports.default = Reader; + + +/***/ }), +/* 230 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = __webpack_require__(28); +const async_1 = __webpack_require__(216); +class StreamProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new async_1.default(this._root, this._settings); + this._stream = new stream_1.Readable({ + objectMode: true, + read: () => { }, + destroy: this._reader.destroy.bind(this._reader) + }); + } + read() { + this._reader.onError((error) => { + this._stream.emit('error', error); + }); + this._reader.onEntry((entry) => { + this._stream.push(entry); + }); + this._reader.onEnd(() => { + this._stream.push(null); + }); + this._reader.read(); + return this._stream; + } +} +exports.default = StreamProvider; + + +/***/ }), +/* 231 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const sync_1 = __webpack_require__(232); +class SyncProvider { + constructor(_root, _settings) { + this._root = _root; + this._settings = _settings; + this._reader = new sync_1.default(this._root, this._settings); + } + read() { + return this._reader.read(); + } +} +exports.default = SyncProvider; + + +/***/ }), +/* 232 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fsScandir = __webpack_require__(217); +const common = __webpack_require__(228); +const reader_1 = __webpack_require__(229); +class SyncReader extends reader_1.default { + constructor() { + super(...arguments); + this._scandir = fsScandir.scandirSync; + this._storage = new Set(); + this._queue = new Set(); + } + read() { + this._pushToQueue(this._root, this._settings.basePath); + this._handleQueue(); + return Array.from(this._storage); + } + _pushToQueue(dir, base) { + this._queue.add({ dir, base }); + } + _handleQueue() { + for (const item of this._queue.values()) { + this._handleDirectory(item.dir, item.base); + } + } + _handleDirectory(dir, base) { + try { + const entries = this._scandir(dir, this._settings.fsScandirSettings); + for (const entry of entries) { + this._handleEntry(entry, base); + } + } + catch (error) { + this._handleError(error); + } + } + _handleError(error) { + if (!common.isFatalError(this._settings, error)) { + return; + } + throw error; + } + _handleEntry(entry, base) { + const fullpath = entry.path; + if (base !== undefined) { + entry.path = common.joinPathSegments(base, entry.name, this._settings.pathSegmentSeparator); + } + if (common.isAppliedFilter(this._settings.entryFilter, entry)) { + this._pushToStorage(entry); + } + if (entry.dirent.isDirectory() && common.isAppliedFilter(this._settings.deepFilter, entry)) { + this._pushToQueue(fullpath, entry.path); + } + } + _pushToStorage(entry) { + this._storage.add(entry); + } +} +exports.default = SyncReader; + + +/***/ }), +/* 233 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(16); +const fsScandir = __webpack_require__(217); +class Settings { + constructor(_options = {}) { + this._options = _options; + this.basePath = this._getValue(this._options.basePath, undefined); + this.concurrency = this._getValue(this._options.concurrency, Infinity); + this.deepFilter = this._getValue(this._options.deepFilter, null); + this.entryFilter = this._getValue(this._options.entryFilter, null); + this.errorFilter = this._getValue(this._options.errorFilter, null); + this.pathSegmentSeparator = this._getValue(this._options.pathSegmentSeparator, path.sep); + this.fsScandirSettings = new fsScandir.Settings({ + followSymbolicLinks: this._options.followSymbolicLinks, + fs: this._options.fs, + pathSegmentSeparator: this._options.pathSegmentSeparator, + stats: this._options.stats, + throwErrorOnBrokenSymbolicLink: this._options.throwErrorOnBrokenSymbolicLink + }); + } + _getValue(option, value) { + return option === undefined ? value : option; + } +} +exports.default = Settings; + + +/***/ }), +/* 234 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(16); +const fsStat = __webpack_require__(209); +const utils = __webpack_require__(180); +class Reader { + constructor(_settings) { + this._settings = _settings; + this._fsStatSettings = new fsStat.Settings({ + followSymbolicLink: this._settings.followSymbolicLinks, + fs: this._settings.fs, + throwErrorOnBrokenSymbolicLink: this._settings.followSymbolicLinks + }); + } + _getFullEntryPath(filepath) { + return path.resolve(this._settings.cwd, filepath); + } + _makeEntry(stats, pattern) { + const entry = { + name: pattern, + path: pattern, + dirent: utils.fs.createDirentFromStats(pattern, stats) + }; + if (this._settings.stats) { + entry.stats = stats; + } + return entry; + } + _isFatalError(error) { + return !utils.errno.isEnoentCodeError(error) && !this._settings.suppressErrors; + } +} +exports.default = Reader; + + +/***/ }), +/* 235 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const path = __webpack_require__(16); +const deep_1 = __webpack_require__(236); +const entry_1 = __webpack_require__(237); +const error_1 = __webpack_require__(238); +const entry_2 = __webpack_require__(239); +class Provider { + constructor(_settings) { + this._settings = _settings; + this.errorFilter = new error_1.default(this._settings); + this.entryFilter = new entry_1.default(this._settings, this._getMicromatchOptions()); + this.deepFilter = new deep_1.default(this._settings, this._getMicromatchOptions()); + this.entryTransformer = new entry_2.default(this._settings); + } + _getRootDirectory(task) { + return path.resolve(this._settings.cwd, task.base); + } + _getReaderOptions(task) { + const basePath = task.base === '.' ? '' : task.base; + return { + basePath, + pathSegmentSeparator: '/', + concurrency: this._settings.concurrency, + deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative), + entryFilter: this.entryFilter.getFilter(task.positive, task.negative), + errorFilter: this.errorFilter.getFilter(), + followSymbolicLinks: this._settings.followSymbolicLinks, + fs: this._settings.fs, + stats: this._settings.stats, + throwErrorOnBrokenSymbolicLink: this._settings.throwErrorOnBrokenSymbolicLink, + transform: this.entryTransformer.getTransformer() + }; + } + _getMicromatchOptions() { + return { + dot: this._settings.dot, + matchBase: this._settings.baseNameMatch, + nobrace: !this._settings.braceExpansion, + nocase: !this._settings.caseSensitiveMatch, + noext: !this._settings.extglob, + noglobstar: !this._settings.globstar, + posix: true, + strictSlashes: false + }; + } +} +exports.default = Provider; + + +/***/ }), +/* 236 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(180); +class DeepFilter { + constructor(_settings, _micromatchOptions) { + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + } + getFilter(basePath, positive, negative) { + const maxPatternDepth = this._getMaxPatternDepth(positive); + const negativeRe = this._getNegativePatternsRe(negative); + return (entry) => this._filter(basePath, entry, negativeRe, maxPatternDepth); + } + _getMaxPatternDepth(patterns) { + const globstar = patterns.some(utils.pattern.hasGlobStar); + return globstar ? Infinity : utils.pattern.getMaxNaivePatternsDepth(patterns); + } + _getNegativePatternsRe(patterns) { + const affectDepthOfReadingPatterns = patterns.filter(utils.pattern.isAffectDepthOfReadingPattern); + return utils.pattern.convertPatternsToRe(affectDepthOfReadingPatterns, this._micromatchOptions); + } + _filter(basePath, entry, negativeRe, maxPatternDepth) { + const depth = this._getEntryDepth(basePath, entry.path); + if (this._isSkippedByDeep(depth)) { + return false; + } + if (this._isSkippedByMaxPatternDepth(depth, maxPatternDepth)) { + return false; + } + if (this._isSkippedSymbolicLink(entry)) { + return false; + } + if (this._isSkippedDotDirectory(entry)) { + return false; + } + return this._isSkippedByNegativePatterns(entry, negativeRe); + } + _getEntryDepth(basePath, entryPath) { + const basePathDepth = basePath.split('/').length; + const entryPathDepth = entryPath.split('/').length; + return entryPathDepth - (basePath === '' ? 0 : basePathDepth); + } + _isSkippedByDeep(entryDepth) { + return entryDepth >= this._settings.deep; + } + _isSkippedByMaxPatternDepth(entryDepth, maxPatternDepth) { + return !this._settings.baseNameMatch && maxPatternDepth !== Infinity && entryDepth > maxPatternDepth; + } + _isSkippedSymbolicLink(entry) { + return !this._settings.followSymbolicLinks && entry.dirent.isSymbolicLink(); + } + _isSkippedDotDirectory(entry) { + return !this._settings.dot && entry.name.startsWith('.'); + } + _isSkippedByNegativePatterns(entry, negativeRe) { + return !utils.pattern.matchAny(entry.path, negativeRe); + } +} +exports.default = DeepFilter; + + +/***/ }), +/* 237 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(180); +class EntryFilter { + constructor(_settings, _micromatchOptions) { + this._settings = _settings; + this._micromatchOptions = _micromatchOptions; + this.index = new Map(); + } + getFilter(positive, negative) { + const positiveRe = utils.pattern.convertPatternsToRe(positive, this._micromatchOptions); + const negativeRe = utils.pattern.convertPatternsToRe(negative, this._micromatchOptions); + return (entry) => this._filter(entry, positiveRe, negativeRe); + } + _filter(entry, positiveRe, negativeRe) { + if (this._settings.unique) { + if (this._isDuplicateEntry(entry)) { + return false; + } + this._createIndexRecord(entry); + } + if (this._onlyFileFilter(entry) || this._onlyDirectoryFilter(entry)) { + return false; + } + if (this._isSkippedByAbsoluteNegativePatterns(entry, negativeRe)) { + return false; + } + const filepath = this._settings.baseNameMatch ? entry.name : entry.path; + return this._isMatchToPatterns(filepath, positiveRe) && !this._isMatchToPatterns(entry.path, negativeRe); + } + _isDuplicateEntry(entry) { + return this.index.has(entry.path); + } + _createIndexRecord(entry) { + this.index.set(entry.path, undefined); + } + _onlyFileFilter(entry) { + return this._settings.onlyFiles && !entry.dirent.isFile(); + } + _onlyDirectoryFilter(entry) { + return this._settings.onlyDirectories && !entry.dirent.isDirectory(); + } + _isSkippedByAbsoluteNegativePatterns(entry, negativeRe) { + if (!this._settings.absolute) { + return false; + } + const fullpath = utils.path.makeAbsolute(this._settings.cwd, entry.path); + return this._isMatchToPatterns(fullpath, negativeRe); + } + _isMatchToPatterns(filepath, patternsRe) { + return utils.pattern.matchAny(filepath, patternsRe); + } +} +exports.default = EntryFilter; + + +/***/ }), +/* 238 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(180); +class ErrorFilter { + constructor(_settings) { + this._settings = _settings; + } + getFilter() { + return (error) => this._isNonFatalError(error); + } + _isNonFatalError(error) { + return utils.errno.isEnoentCodeError(error) || this._settings.suppressErrors; + } +} +exports.default = ErrorFilter; + + +/***/ }), +/* 239 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const utils = __webpack_require__(180); +class EntryTransformer { + constructor(_settings) { + this._settings = _settings; + } + getTransformer() { + return (entry) => this._transform(entry); + } + _transform(entry) { + let filepath = entry.path; + if (this._settings.absolute) { + filepath = utils.path.makeAbsolute(this._settings.cwd, filepath); + filepath = utils.path.unixify(filepath); + } + if (this._settings.markDirectories && entry.dirent.isDirectory()) { + filepath += '/'; + } + if (!this._settings.objectMode) { + return filepath; + } + return Object.assign({}, entry, { path: filepath }); + } +} +exports.default = EntryTransformer; + + +/***/ }), +/* 240 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = __webpack_require__(28); +const stream_2 = __webpack_require__(208); +const provider_1 = __webpack_require__(235); +class ProviderStream extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new stream_2.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const source = this.api(root, task, options); + const dest = new stream_1.Readable({ objectMode: true, read: () => { } }); + source + .once('error', (error) => dest.emit('error', error)) + .on('data', (entry) => dest.emit('data', options.transform(entry))) + .once('end', () => dest.emit('end')); + return dest; + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderStream; + + +/***/ }), +/* 241 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const sync_1 = __webpack_require__(242); +const provider_1 = __webpack_require__(235); +class ProviderSync extends provider_1.default { + constructor() { + super(...arguments); + this._reader = new sync_1.default(this._settings); + } + read(task) { + const root = this._getRootDirectory(task); + const options = this._getReaderOptions(task); + const entries = this.api(root, task, options); + return entries.map(options.transform); + } + api(root, task, options) { + if (task.dynamic) { + return this._reader.dynamic(root, options); + } + return this._reader.static(task.patterns, options); + } +} +exports.default = ProviderSync; + + +/***/ }), +/* 242 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fsStat = __webpack_require__(209); +const fsWalk = __webpack_require__(214); +const reader_1 = __webpack_require__(234); +class ReaderSync extends reader_1.default { + constructor() { + super(...arguments); + this._walkSync = fsWalk.walkSync; + this._statSync = fsStat.statSync; + } + dynamic(root, options) { + return this._walkSync(root, options); + } + static(patterns, options) { + const entries = []; + for (const pattern of patterns) { + const filepath = this._getFullEntryPath(pattern); + const entry = this._getEntry(filepath, pattern, options); + if (entry === null || !options.entryFilter(entry)) { + continue; + } + entries.push(entry); + } + return entries; + } + _getEntry(filepath, pattern, options) { + try { + const stats = this._getStat(filepath); + return this._makeEntry(stats, pattern); + } + catch (error) { + if (options.errorFilter(error)) { + return null; + } + throw error; + } + } + _getStat(filepath) { + return this._statSync(filepath, this._fsStatSettings); + } +} +exports.default = ReaderSync; + + +/***/ }), +/* 243 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __webpack_require__(23); +const os = __webpack_require__(11); +const CPU_COUNT = os.cpus().length; +exports.DEFAULT_FILE_SYSTEM_ADAPTER = { + lstat: fs.lstat, + lstatSync: fs.lstatSync, + stat: fs.stat, + statSync: fs.statSync, + readdir: fs.readdir, + readdirSync: fs.readdirSync +}; +// tslint:enable no-redundant-jsdoc +class Settings { + constructor(_options = {}) { + this._options = _options; + this.absolute = this._getValue(this._options.absolute, false); + this.baseNameMatch = this._getValue(this._options.baseNameMatch, false); + this.braceExpansion = this._getValue(this._options.braceExpansion, true); + this.caseSensitiveMatch = this._getValue(this._options.caseSensitiveMatch, true); + this.concurrency = this._getValue(this._options.concurrency, CPU_COUNT); + this.cwd = this._getValue(this._options.cwd, process.cwd()); + this.deep = this._getValue(this._options.deep, Infinity); + this.dot = this._getValue(this._options.dot, false); + this.extglob = this._getValue(this._options.extglob, true); + this.followSymbolicLinks = this._getValue(this._options.followSymbolicLinks, true); + this.fs = this._getFileSystemMethods(this._options.fs); + this.globstar = this._getValue(this._options.globstar, true); + this.ignore = this._getValue(this._options.ignore, []); + this.markDirectories = this._getValue(this._options.markDirectories, false); + this.objectMode = this._getValue(this._options.objectMode, false); + this.onlyDirectories = this._getValue(this._options.onlyDirectories, false); + this.onlyFiles = this._getValue(this._options.onlyFiles, true); + this.stats = this._getValue(this._options.stats, false); + this.suppressErrors = this._getValue(this._options.suppressErrors, false); + this.throwErrorOnBrokenSymbolicLink = this._getValue(this._options.throwErrorOnBrokenSymbolicLink, false); + this.unique = this._getValue(this._options.unique, true); + if (this.onlyDirectories) { + this.onlyFiles = false; + } + if (this.stats) { + this.objectMode = true; + } + } + _getValue(option, value) { + return option === undefined ? value : option; + } + _getFileSystemMethods(methods = {}) { + return Object.assign({}, exports.DEFAULT_FILE_SYSTEM_ADAPTER, methods); + } +} +exports.default = Settings; + + +/***/ }), +/* 244 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const path = __webpack_require__(16); +const pathType = __webpack_require__(245); + +const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; + +const getPath = (filepath, cwd) => { + const pth = filepath[0] === '!' ? filepath.slice(1) : filepath; + return path.isAbsolute(pth) ? pth : path.join(cwd, pth); +}; + +const addExtensions = (file, extensions) => { + if (path.extname(file)) { + return `**/${file}`; + } + + return `**/${file}.${getExtensions(extensions)}`; +}; + +const getGlob = (directory, options) => { + if (options.files && !Array.isArray(options.files)) { + throw new TypeError(`Expected \`files\` to be of type \`Array\` but received type \`${typeof options.files}\``); + } + + if (options.extensions && !Array.isArray(options.extensions)) { + throw new TypeError(`Expected \`extensions\` to be of type \`Array\` but received type \`${typeof options.extensions}\``); + } + + if (options.files && options.extensions) { + return options.files.map(x => path.posix.join(directory, addExtensions(x, options.extensions))); + } + + if (options.files) { + return options.files.map(x => path.posix.join(directory, `**/${x}`)); + } + + if (options.extensions) { + return [path.posix.join(directory, `**/*.${getExtensions(options.extensions)}`)]; + } + + return [path.posix.join(directory, '**')]; +}; + +module.exports = async (input, options) => { + options = { + cwd: process.cwd(), + ...options + }; + + if (typeof options.cwd !== 'string') { + throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``); + } + + const globs = await Promise.all([].concat(input).map(async x => { + const isDirectory = await pathType.isDirectory(getPath(x, options.cwd)); + return isDirectory ? getGlob(x, options) : x; + })); + + return [].concat.apply([], globs); // eslint-disable-line prefer-spread +}; + +module.exports.sync = (input, options) => { + options = { + cwd: process.cwd(), + ...options + }; + + if (typeof options.cwd !== 'string') { + throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``); + } + + const globs = [].concat(input).map(x => pathType.isDirectorySync(getPath(x, options.cwd)) ? getGlob(x, options) : x); + + return [].concat.apply([], globs); // eslint-disable-line prefer-spread +}; + + +/***/ }), +/* 245 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const {promisify} = __webpack_require__(29); +const fs = __webpack_require__(23); + +async function isType(fsStatType, statsMethodName, filePath) { + if (typeof filePath !== 'string') { + throw new TypeError(`Expected a string, got ${typeof filePath}`); + } + + try { + const stats = await promisify(fs[fsStatType])(filePath); + return stats[statsMethodName](); + } catch (error) { + if (error.code === 'ENOENT') { + return false; + } + + throw error; + } +} + +function isTypeSync(fsStatType, statsMethodName, filePath) { + if (typeof filePath !== 'string') { + throw new TypeError(`Expected a string, got ${typeof filePath}`); + } + + try { + return fs[fsStatType](filePath)[statsMethodName](); + } catch (error) { + if (error.code === 'ENOENT') { + return false; + } + + throw error; + } +} + +exports.isFile = isType.bind(null, 'stat', 'isFile'); +exports.isDirectory = isType.bind(null, 'stat', 'isDirectory'); +exports.isSymlink = isType.bind(null, 'lstat', 'isSymbolicLink'); +exports.isFileSync = isTypeSync.bind(null, 'statSync', 'isFile'); +exports.isDirectorySync = isTypeSync.bind(null, 'statSync', 'isDirectory'); +exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); + + +/***/ }), +/* 246 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const {promisify} = __webpack_require__(29); +const fs = __webpack_require__(23); +const path = __webpack_require__(16); +const fastGlob = __webpack_require__(178); +const gitIgnore = __webpack_require__(247); +const slash = __webpack_require__(248); + +const DEFAULT_IGNORE = [ + '**/node_modules/**', + '**/flow-typed/**', + '**/coverage/**', + '**/.git' +]; + +const readFileP = promisify(fs.readFile); + +const mapGitIgnorePatternTo = base => ignore => { + if (ignore.startsWith('!')) { + return '!' + path.posix.join(base, ignore.slice(1)); + } + + return path.posix.join(base, ignore); +}; + +const parseGitIgnore = (content, options) => { + const base = slash(path.relative(options.cwd, path.dirname(options.fileName))); + + return content + .split(/\r?\n/) + .filter(Boolean) + .filter(line => !line.startsWith('#')) + .map(mapGitIgnorePatternTo(base)); +}; + +const reduceIgnore = files => { + return files.reduce((ignores, file) => { + ignores.add(parseGitIgnore(file.content, { + cwd: file.cwd, + fileName: file.filePath + })); + return ignores; + }, gitIgnore()); +}; + +const ensureAbsolutePathForCwd = (cwd, p) => { + if (path.isAbsolute(p)) { + if (p.startsWith(cwd)) { + return p; + } + + throw new Error(`Path ${p} is not in cwd ${cwd}`); + } + + return path.join(cwd, p); +}; + +const getIsIgnoredPredecate = (ignores, cwd) => { + return p => ignores.ignores(slash(path.relative(cwd, ensureAbsolutePathForCwd(cwd, p)))); +}; + +const getFile = async (file, cwd) => { + const filePath = path.join(cwd, file); + const content = await readFileP(filePath, 'utf8'); + + return { + cwd, + filePath, + content + }; +}; + +const getFileSync = (file, cwd) => { + const filePath = path.join(cwd, file); + const content = fs.readFileSync(filePath, 'utf8'); + + return { + cwd, + filePath, + content + }; +}; + +const normalizeOptions = ({ + ignore = [], + cwd = process.cwd() +} = {}) => { + return {ignore, cwd}; +}; + +module.exports = async options => { + options = normalizeOptions(options); + + const paths = await fastGlob('**/.gitignore', { + ignore: DEFAULT_IGNORE.concat(options.ignore), + cwd: options.cwd + }); + + const files = await Promise.all(paths.map(file => getFile(file, options.cwd))); + const ignores = reduceIgnore(files); + + return getIsIgnoredPredecate(ignores, options.cwd); +}; + +module.exports.sync = options => { + options = normalizeOptions(options); + + const paths = fastGlob.sync('**/.gitignore', { + ignore: DEFAULT_IGNORE.concat(options.ignore), + cwd: options.cwd + }); + + const files = paths.map(file => getFileSync(file, options.cwd)); + const ignores = reduceIgnore(files); + + return getIsIgnoredPredecate(ignores, options.cwd); +}; + + +/***/ }), +/* 247 */ +/***/ (function(module, exports) { + +// A simple implementation of make-array +function makeArray (subject) { + return Array.isArray(subject) + ? subject + : [subject] +} + +const REGEX_TEST_BLANK_LINE = /^\s+$/ +const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/ +const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/ +const REGEX_SPLITALL_CRLF = /\r?\n/g +// /foo, +// ./foo, +// ../foo, +// . +// .. +const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/ + +const SLASH = '/' +const KEY_IGNORE = typeof Symbol !== 'undefined' + ? Symbol.for('node-ignore') + /* istanbul ignore next */ + : 'node-ignore' + +const define = (object, key, value) => + Object.defineProperty(object, key, {value}) + +const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g + +// Sanitize the range of a regular expression +// The cases are complicated, see test cases for details +const sanitizeRange = range => range.replace( + REGEX_REGEXP_RANGE, + (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) + ? match + // Invalid range (out of order) which is ok for gitignore rules but + // fatal for JavaScript regular expression, so eliminate it. + : '' +) + +// > If the pattern ends with a slash, +// > it is removed for the purpose of the following description, +// > but it would only find a match with a directory. +// > In other words, foo/ will match a directory foo and paths underneath it, +// > but will not match a regular file or a symbolic link foo +// > (this is consistent with the way how pathspec works in general in Git). +// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`' +// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call +// you could use option `mark: true` with `glob` + +// '`foo/`' should not continue with the '`..`' +const DEFAULT_REPLACER_PREFIX = [ + + // > Trailing spaces are ignored unless they are quoted with backslash ("\") + [ + // (a\ ) -> (a ) + // (a ) -> (a) + // (a \ ) -> (a ) + /\\?\s+$/, + match => match.indexOf('\\') === 0 + ? ' ' + : '' + ], + + // replace (\ ) with ' ' + [ + /\\\s/g, + () => ' ' + ], + + // Escape metacharacters + // which is written down by users but means special for regular expressions. + + // > There are 12 characters with special meanings: + // > - the backslash \, + // > - the caret ^, + // > - the dollar sign $, + // > - the period or dot ., + // > - the vertical bar or pipe symbol |, + // > - the question mark ?, + // > - the asterisk or star *, + // > - the plus sign +, + // > - the opening parenthesis (, + // > - the closing parenthesis ), + // > - and the opening square bracket [, + // > - the opening curly brace {, + // > These special characters are often called "metacharacters". + [ + /[\\^$.|*+(){]/g, + match => `\\${match}` + ], + + [ + // > [abc] matches any character inside the brackets + // > (in this case a, b, or c); + /\[([^\]/]*)($|\])/g, + (match, p1, p2) => p2 === ']' + ? `[${sanitizeRange(p1)}]` + : `\\${match}` + ], + + [ + // > a question mark (?) matches a single character + /(?!\\)\?/g, + () => '[^/]' + ], + + // leading slash + [ + + // > A leading slash matches the beginning of the pathname. + // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". + // A leading slash matches the beginning of the pathname + /^\//, + () => '^' + ], + + // replace special metacharacter slash after the leading slash + [ + /\//g, + () => '\\/' + ], + + [ + // > A leading "**" followed by a slash means match in all directories. + // > For example, "**/foo" matches file or directory "foo" anywhere, + // > the same as pattern "foo". + // > "**/foo/bar" matches file or directory "bar" anywhere that is directly + // > under directory "foo". + // Notice that the '*'s have been replaced as '\\*' + /^\^*\\\*\\\*\\\//, + + // '**/foo' <-> 'foo' + () => '^(?:.*\\/)?' + ] +] + +const DEFAULT_REPLACER_SUFFIX = [ + // starting + [ + // there will be no leading '/' + // (which has been replaced by section "leading slash") + // If starts with '**', adding a '^' to the regular expression also works + /^(?=[^^])/, + function startingReplacer () { + return !/\/(?!$)/.test(this) + // > If the pattern does not contain a slash /, + // > Git treats it as a shell glob pattern + // Actually, if there is only a trailing slash, + // git also treats it as a shell glob pattern + ? '(?:^|\\/)' + + // > Otherwise, Git treats the pattern as a shell glob suitable for + // > consumption by fnmatch(3) + : '^' + } + ], + + // two globstars + [ + // Use lookahead assertions so that we could match more than one `'/**'` + /\\\/\\\*\\\*(?=\\\/|$)/g, + + // Zero, one or several directories + // should not use '*', or it will be replaced by the next replacer + + // Check if it is not the last `'/**'` + (_, index, str) => index + 6 < str.length + + // case: /**/ + // > A slash followed by two consecutive asterisks then a slash matches + // > zero or more directories. + // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on. + // '/**/' + ? '(?:\\/[^\\/]+)*' + + // case: /** + // > A trailing `"/**"` matches everything inside. + + // #21: everything inside but it should not include the current folder + : '\\/.+' + ], + + // intermediate wildcards + [ + // Never replace escaped '*' + // ignore rule '\*' will match the path '*' + + // 'abc.*/' -> go + // 'abc.*' -> skip this rule + /(^|[^\\]+)\\\*(?=.+)/g, + + // '*.js' matches '.js' + // '*.js' doesn't match 'abc' + (_, p1) => `${p1}[^\\/]*` + ], + + // trailing wildcard + [ + /(\^|\\\/)?\\\*$/, + (_, p1) => { + const prefix = p1 + // '\^': + // '/*' does not match '' + // '/*' does not match everything + + // '\\\/': + // 'abc/*' does not match 'abc/' + ? `${p1}[^/]+` + + // 'a*' matches 'a' + // 'a*' matches 'aa' + : '[^/]*' + + return `${prefix}(?=$|\\/$)` + } + ], + + [ + // unescape + /\\\\\\/g, + () => '\\' + ] +] + +const POSITIVE_REPLACERS = [ + ...DEFAULT_REPLACER_PREFIX, + + // 'f' + // matches + // - /f(end) + // - /f/ + // - (start)f(end) + // - (start)f/ + // doesn't match + // - oof + // - foo + // pseudo: + // -> (^|/)f(/|$) + + // ending + [ + // 'js' will not match 'js.' + // 'ab' will not match 'abc' + /(?:[^*/])$/, + + // 'js*' will not match 'a.js' + // 'js/' will not match 'a.js' + // 'js' will match 'a.js' and 'a.js/' + match => `${match}(?=$|\\/)` + ], + + ...DEFAULT_REPLACER_SUFFIX +] + +const NEGATIVE_REPLACERS = [ + ...DEFAULT_REPLACER_PREFIX, + + // #24, #38 + // The MISSING rule of [gitignore docs](https://git-scm.com/docs/gitignore) + // A negative pattern without a trailing wildcard should not + // re-include the things inside that directory. + + // eg: + // ['node_modules/*', '!node_modules'] + // should ignore `node_modules/a.js` + [ + /(?:[^*])$/, + match => `${match}(?=$|\\/$)` + ], + + ...DEFAULT_REPLACER_SUFFIX +] + +// A simple cache, because an ignore rule only has only one certain meaning +const regexCache = Object.create(null) + +// @param {pattern} +const makeRegex = (pattern, negative, ignorecase) => { + const r = regexCache[pattern] + if (r) { + return r + } + + const replacers = negative + ? NEGATIVE_REPLACERS + : POSITIVE_REPLACERS + + const source = replacers.reduce( + (prev, current) => prev.replace(current[0], current[1].bind(pattern)), + pattern + ) + + return regexCache[pattern] = ignorecase + ? new RegExp(source, 'i') + : new RegExp(source) +} + +const isString = subject => typeof subject === 'string' + +// > A blank line matches no files, so it can serve as a separator for readability. +const checkPattern = pattern => pattern + && isString(pattern) + && !REGEX_TEST_BLANK_LINE.test(pattern) + + // > A line starting with # serves as a comment. + && pattern.indexOf('#') !== 0 + +const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF) + +class IgnoreRule { + constructor ( + origin, + pattern, + negative, + regex + ) { + this.origin = origin + this.pattern = pattern + this.negative = negative + this.regex = regex + } +} + +const createRule = (pattern, ignorecase) => { + const origin = pattern + let negative = false + + // > An optional prefix "!" which negates the pattern; + if (pattern.indexOf('!') === 0) { + negative = true + pattern = pattern.substr(1) + } + + pattern = pattern + // > Put a backslash ("\") in front of the first "!" for patterns that + // > begin with a literal "!", for example, `"\!important!.txt"`. + .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!') + // > Put a backslash ("\") in front of the first hash for patterns that + // > begin with a hash. + .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#') + + const regex = makeRegex(pattern, negative, ignorecase) + + return new IgnoreRule( + origin, + pattern, + negative, + regex + ) +} + +const throwError = (message, Ctor) => { + throw new Ctor(message) +} + +const checkPath = (path, originalPath, doThrow) => { + if (!isString(path)) { + return doThrow( + `path must be a string, but got \`${originalPath}\``, + TypeError + ) + } + + // We don't know if we should ignore '', so throw + if (!path) { + return doThrow(`path must not be empty`, TypeError) + } + + // Check if it is a relative path + if (checkPath.isNotRelative(path)) { + const r = '`path.relative()`d' + return doThrow( + `path should be a ${r} string, but got "${originalPath}"`, + RangeError + ) + } + + return true +} + +const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path) + +checkPath.isNotRelative = isNotRelative +checkPath.convert = p => p + +class Ignore { + constructor ({ + ignorecase = true + } = {}) { + this._rules = [] + this._ignorecase = ignorecase + define(this, KEY_IGNORE, true) + this._initCache() + } + + _initCache () { + this._ignoreCache = Object.create(null) + this._testCache = Object.create(null) + } + + _addPattern (pattern) { + // #32 + if (pattern && pattern[KEY_IGNORE]) { + this._rules = this._rules.concat(pattern._rules) + this._added = true + return + } + + if (checkPattern(pattern)) { + const rule = createRule(pattern, this._ignorecase) + this._added = true + this._rules.push(rule) + } + } + + // @param {Array | string | Ignore} pattern + add (pattern) { + this._added = false + + makeArray( + isString(pattern) + ? splitPattern(pattern) + : pattern + ).forEach(this._addPattern, this) + + // Some rules have just added to the ignore, + // making the behavior changed. + if (this._added) { + this._initCache() + } + + return this + } + + // legacy + addPattern (pattern) { + return this.add(pattern) + } + + // | ignored : unignored + // negative | 0:0 | 0:1 | 1:0 | 1:1 + // -------- | ------- | ------- | ------- | -------- + // 0 | TEST | TEST | SKIP | X + // 1 | TESTIF | SKIP | TEST | X + + // - SKIP: always skip + // - TEST: always test + // - TESTIF: only test if checkUnignored + // - X: that never happen + + // @param {boolean} whether should check if the path is unignored, + // setting `checkUnignored` to `false` could reduce additional + // path matching. + + // @returns {TestResult} true if a file is ignored + _testOne (path, checkUnignored) { + let ignored = false + let unignored = false + + this._rules.forEach(rule => { + const {negative} = rule + if ( + unignored === negative && ignored !== unignored + || negative && !ignored && !unignored && !checkUnignored + ) { + return + } + + const matched = rule.regex.test(path) + + if (matched) { + ignored = !negative + unignored = negative + } + }) + + return { + ignored, + unignored + } + } + + // @returns {TestResult} + _test (originalPath, cache, checkUnignored, slices) { + const path = originalPath + // Supports nullable path + && checkPath.convert(originalPath) + + checkPath(path, originalPath, throwError) + + return this._t(path, cache, checkUnignored, slices) + } + + _t (path, cache, checkUnignored, slices) { + if (path in cache) { + return cache[path] + } + + if (!slices) { + // path/to/a.js + // ['path', 'to', 'a.js'] + slices = path.split(SLASH) + } + + slices.pop() + + // If the path has no parent directory, just test it + if (!slices.length) { + return cache[path] = this._testOne(path, checkUnignored) + } + + const parent = this._t( + slices.join(SLASH) + SLASH, + cache, + checkUnignored, + slices + ) + + // If the path contains a parent directory, check the parent first + return cache[path] = parent.ignored + // > It is not possible to re-include a file if a parent directory of + // > that file is excluded. + ? parent + : this._testOne(path, checkUnignored) + } + + ignores (path) { + return this._test(path, this._ignoreCache, false).ignored + } + + createFilter () { + return path => !this.ignores(path) + } + + filter (paths) { + return makeArray(paths).filter(this.createFilter()) + } + + // @returns {TestResult} + test (path) { + return this._test(path, this._testCache, true) + } +} + +const factory = options => new Ignore(options) + +const returnFalse = () => false + +const isPathValid = path => + checkPath(path && checkPath.convert(path), path, returnFalse) + +factory.isPathValid = isPathValid + +// Fixes typescript +factory.default = factory + +module.exports = factory + +// Windows +// -------------------------------------------------------------- +/* istanbul ignore if */ +if ( + // Detect `process` so that it can run in browsers. + typeof process !== 'undefined' + && ( + process.env && process.env.IGNORE_TEST_WIN32 + || process.platform === 'win32' + ) +) { + /* eslint no-control-regex: "off" */ + const makePosix = str => /^\\\\\?\\/.test(str) + || /["<>|\u0000-\u001F]+/u.test(str) + ? str + : str.replace(/\\/g, '/') + + checkPath.convert = makePosix + + // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/' + // 'd:\\foo' + const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i + checkPath.isNotRelative = path => + REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path) + || isNotRelative(path) +} + + +/***/ }), +/* 248 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = path => { + const isExtendedLengthPath = /^\\\\\?\\/.test(path); + const hasNonAscii = /[^\u0000-\u0080]+/.test(path); // eslint-disable-line no-control-regex + + if (isExtendedLengthPath || hasNonAscii) { + return path; + } + + return path.replace(/\\/g, '/'); +}; + + +/***/ }), +/* 249 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const {Transform} = __webpack_require__(28); + +class ObjectTransform extends Transform { + constructor() { + super({ + objectMode: true + }); + } +} + +class FilterStream extends ObjectTransform { + constructor(filter) { + super(); + this._filter = filter; + } + + _transform(data, encoding, callback) { + if (this._filter(data)) { + this.push(data); + } + + callback(); + } +} + +class UniqueStream extends ObjectTransform { + constructor() { + super(); + this._pushed = new Set(); + } + + _transform(data, encoding, callback) { + if (!this._pushed.has(data)) { + this.push(data); + this._pushed.add(data); + } + + callback(); + } +} + +module.exports = { + FilterStream, + UniqueStream +}; + + +/***/ }), +/* 250 */ +/***/ (function(module, exports, __webpack_require__) { + +var fs = __webpack_require__(23) +var polyfills = __webpack_require__(251) +var legacy = __webpack_require__(252) +var clone = __webpack_require__(253) + +var util = __webpack_require__(29) + +/* istanbul ignore next - node 0.x polyfill */ +var gracefulQueue +var previousSymbol + +/* istanbul ignore else - node 0.x polyfill */ +if (typeof Symbol === 'function' && typeof Symbol.for === 'function') { + gracefulQueue = Symbol.for('graceful-fs.queue') + // This is used in testing by future versions + previousSymbol = Symbol.for('graceful-fs.previous') +} else { + gracefulQueue = '___graceful-fs.queue' + previousSymbol = '___graceful-fs.previous' +} + +function noop () {} + +var debug = noop +if (util.debuglog) + debug = util.debuglog('gfs4') +else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) + debug = function() { + var m = util.format.apply(util, arguments) + m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ') + console.error(m) + } + +// Once time initialization +if (!global[gracefulQueue]) { + // This queue can be shared by multiple loaded instances + var queue = [] + Object.defineProperty(global, gracefulQueue, { + get: function() { + return queue + } + }) + + // Patch fs.close/closeSync to shared queue version, because we need + // to retry() whenever a close happens *anywhere* in the program. + // This is essential when multiple graceful-fs instances are + // in play at the same time. + fs.close = (function (fs$close) { + function close (fd, cb) { + return fs$close.call(fs, fd, function (err) { + // This function uses the graceful-fs shared queue + if (!err) { + retry() + } + + if (typeof cb === 'function') + cb.apply(this, arguments) + }) + } + + Object.defineProperty(close, previousSymbol, { + value: fs$close + }) + return close + })(fs.close) + + fs.closeSync = (function (fs$closeSync) { + function closeSync (fd) { + // This function uses the graceful-fs shared queue + fs$closeSync.apply(fs, arguments) + retry() + } + + Object.defineProperty(closeSync, previousSymbol, { + value: fs$closeSync + }) + return closeSync + })(fs.closeSync) + + if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) { + process.on('exit', function() { + debug(global[gracefulQueue]) + __webpack_require__(30).equal(global[gracefulQueue].length, 0) + }) + } +} + +module.exports = patch(clone(fs)) +if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) { + module.exports = patch(fs) + fs.__patched = true; +} + +function patch (fs) { + // Everything that references the open() function needs to be in here + polyfills(fs) + fs.gracefulify = patch + + fs.createReadStream = createReadStream + fs.createWriteStream = createWriteStream + var fs$readFile = fs.readFile + fs.readFile = readFile + function readFile (path, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$readFile(path, options, cb) + + function go$readFile (path, options, cb) { + return fs$readFile(path, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readFile, [path, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$writeFile = fs.writeFile + fs.writeFile = writeFile + function writeFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$writeFile(path, data, options, cb) + + function go$writeFile (path, data, options, cb) { + return fs$writeFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$writeFile, [path, data, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$appendFile = fs.appendFile + if (fs$appendFile) + fs.appendFile = appendFile + function appendFile (path, data, options, cb) { + if (typeof options === 'function') + cb = options, options = null + + return go$appendFile(path, data, options, cb) + + function go$appendFile (path, data, options, cb) { + return fs$appendFile(path, data, options, function (err) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$appendFile, [path, data, options, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + var fs$readdir = fs.readdir + fs.readdir = readdir + function readdir (path, options, cb) { + var args = [path] + if (typeof options !== 'function') { + args.push(options) + } else { + cb = options + } + args.push(go$readdir$cb) + + return go$readdir(args) + + function go$readdir$cb (err, files) { + if (files && files.sort) + files.sort() + + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$readdir, [args]]) + + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + } + } + + function go$readdir (args) { + return fs$readdir.apply(fs, args) + } + + if (process.version.substr(0, 4) === 'v0.8') { + var legStreams = legacy(fs) + ReadStream = legStreams.ReadStream + WriteStream = legStreams.WriteStream + } + + var fs$ReadStream = fs.ReadStream + if (fs$ReadStream) { + ReadStream.prototype = Object.create(fs$ReadStream.prototype) + ReadStream.prototype.open = ReadStream$open + } + + var fs$WriteStream = fs.WriteStream + if (fs$WriteStream) { + WriteStream.prototype = Object.create(fs$WriteStream.prototype) + WriteStream.prototype.open = WriteStream$open + } + + Object.defineProperty(fs, 'ReadStream', { + get: function () { + return ReadStream + }, + set: function (val) { + ReadStream = val + }, + enumerable: true, + configurable: true + }) + Object.defineProperty(fs, 'WriteStream', { + get: function () { + return WriteStream + }, + set: function (val) { + WriteStream = val + }, + enumerable: true, + configurable: true + }) + + // legacy names + Object.defineProperty(fs, 'FileReadStream', { + get: function () { + return ReadStream + }, + set: function (val) { + ReadStream = val + }, + enumerable: true, + configurable: true + }) + Object.defineProperty(fs, 'FileWriteStream', { + get: function () { + return WriteStream + }, + set: function (val) { + WriteStream = val + }, + enumerable: true, + configurable: true + }) + + function ReadStream (path, options) { + if (this instanceof ReadStream) + return fs$ReadStream.apply(this, arguments), this + else + return ReadStream.apply(Object.create(ReadStream.prototype), arguments) + } + + function ReadStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + if (that.autoClose) + that.destroy() + + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + that.read() + } + }) + } + + function WriteStream (path, options) { + if (this instanceof WriteStream) + return fs$WriteStream.apply(this, arguments), this + else + return WriteStream.apply(Object.create(WriteStream.prototype), arguments) + } + + function WriteStream$open () { + var that = this + open(that.path, that.flags, that.mode, function (err, fd) { + if (err) { + that.destroy() + that.emit('error', err) + } else { + that.fd = fd + that.emit('open', fd) + } + }) + } + + function createReadStream (path, options) { + return new fs.ReadStream(path, options) + } + + function createWriteStream (path, options) { + return new fs.WriteStream(path, options) + } + + var fs$open = fs.open + fs.open = open + function open (path, flags, mode, cb) { + if (typeof mode === 'function') + cb = mode, mode = null + + return go$open(path, flags, mode, cb) + + function go$open (path, flags, mode, cb) { + return fs$open(path, flags, mode, function (err, fd) { + if (err && (err.code === 'EMFILE' || err.code === 'ENFILE')) + enqueue([go$open, [path, flags, mode, cb]]) + else { + if (typeof cb === 'function') + cb.apply(this, arguments) + retry() + } + }) + } + } + + return fs +} + +function enqueue (elem) { + debug('ENQUEUE', elem[0].name, elem[1]) + global[gracefulQueue].push(elem) +} + +function retry () { + var elem = global[gracefulQueue].shift() + if (elem) { + debug('RETRY', elem[0].name, elem[1]) + elem[0].apply(null, elem[1]) + } +} + + +/***/ }), +/* 251 */ +/***/ (function(module, exports, __webpack_require__) { + +var constants = __webpack_require__(26) + +var origCwd = process.cwd +var cwd = null + +var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform + +process.cwd = function() { + if (!cwd) + cwd = origCwd.call(process) + return cwd +} +try { + process.cwd() +} catch (er) {} + +var chdir = process.chdir +process.chdir = function(d) { + cwd = null + chdir.call(process, d) +} + +module.exports = patch + +function patch (fs) { + // (re-)implement some things that are known busted or missing. + + // lchmod, broken prior to 0.6.2 + // back-port the fix here. + if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + patchLchmod(fs) + } + + // lutimes implementation, or no-op + if (!fs.lutimes) { + patchLutimes(fs) + } + + // https://github.com/isaacs/node-graceful-fs/issues/4 + // Chown should not fail on einval or eperm if non-root. + // It should not fail on enosys ever, as this just indicates + // that a fs doesn't support the intended operation. + + fs.chown = chownFix(fs.chown) + fs.fchown = chownFix(fs.fchown) + fs.lchown = chownFix(fs.lchown) + + fs.chmod = chmodFix(fs.chmod) + fs.fchmod = chmodFix(fs.fchmod) + fs.lchmod = chmodFix(fs.lchmod) + + fs.chownSync = chownFixSync(fs.chownSync) + fs.fchownSync = chownFixSync(fs.fchownSync) + fs.lchownSync = chownFixSync(fs.lchownSync) + + fs.chmodSync = chmodFixSync(fs.chmodSync) + fs.fchmodSync = chmodFixSync(fs.fchmodSync) + fs.lchmodSync = chmodFixSync(fs.lchmodSync) + + fs.stat = statFix(fs.stat) + fs.fstat = statFix(fs.fstat) + fs.lstat = statFix(fs.lstat) + + fs.statSync = statFixSync(fs.statSync) + fs.fstatSync = statFixSync(fs.fstatSync) + fs.lstatSync = statFixSync(fs.lstatSync) + + // if lchmod/lchown do not exist, then make them no-ops + if (!fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + if (cb) process.nextTick(cb) + } + fs.lchmodSync = function () {} + } + if (!fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + if (cb) process.nextTick(cb) + } + fs.lchownSync = function () {} + } + + // on Windows, A/V software can lock the directory, causing this + // to fail with an EACCES or EPERM if the directory contains newly + // created files. Try again on failure, for up to 60 seconds. + + // Set the timeout this long because some Windows Anti-Virus, such as Parity + // bit9, may lock files for up to a minute, causing npm package install + // failures. Also, take care to yield the scheduler. Windows scheduling gives + // CPU to a busy looping process, which can cause the program causing the lock + // contention to be starved of CPU by node, so the contention doesn't resolve. + if (platform === "win32") { + fs.rename = (function (fs$rename) { return function (from, to, cb) { + var start = Date.now() + var backoff = 0; + fs$rename(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM") + && Date.now() - start < 60000) { + setTimeout(function() { + fs.stat(to, function (stater, st) { + if (stater && stater.code === "ENOENT") + fs$rename(from, to, CB); + else + cb(er) + }) + }, backoff) + if (backoff < 100) + backoff += 10; + return; + } + if (cb) cb(er) + }) + }})(fs.rename) + } -// 3 - a standard Set type is defined and it has a forEach method -function uniqSetWithForEach(arr) { - var ret = []; + // if read() returns EAGAIN, then just try it again. + fs.read = (function (fs$read) { + function read (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return fs$read.call(fs, fd, buffer, offset, length, position, callback) + } - (new Set(arr)).forEach(function (el) { - ret.push(el); - }); + // This ensures `util.promisify` works as it does for native `fs.read`. + read.__proto__ = fs$read + return read + })(fs.read) - return ret; -} + fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return fs$readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } + }})(fs.readSync) -// V8 currently has a broken implementation -// https://github.com/joyent/node/issues/8449 -function doesForEachActuallyWork() { - var ret = false; + function patchLchmod (fs) { + fs.lchmod = function (path, mode, callback) { + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + if (callback) callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + if (callback) callback(err || err2) + }) + }) + }) + } - (new Set([true])).forEach(function (el) { - ret = el; - }); + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) - return ret === true; -} + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var threw = true + var ret + try { + ret = fs.fchmodSync(fd, mode) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } + } -if ('Set' in global) { - if (typeof Set.prototype.forEach === 'function' && doesForEachActuallyWork()) { - module.exports = uniqSetWithForEach; - } else { - module.exports = uniqSet; - } -} else { - module.exports = uniqNoSet; -} + function patchLutimes (fs) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + if (er) { + if (cb) cb(er) + return + } + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + if (cb) cb(er || er2) + }) + }) + }) + } + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + var ret + var threw = true + try { + ret = fs.futimesSync(fd, at, mt) + threw = false + } finally { + if (threw) { + try { + fs.closeSync(fd) + } catch (er) {} + } else { + fs.closeSync(fd) + } + } + return ret + } -/***/ }), -/* 180 */ -/***/ (function(module, exports, __webpack_require__) { + } else { + fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) } + fs.lutimesSync = function () {} + } + } -"use strict"; -/* -object-assign -(c) Sindre Sorhus -@license MIT -*/ + function chmodFix (orig) { + if (!orig) return orig + return function (target, mode, cb) { + return orig.call(fs, target, mode, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } + function chmodFixSync (orig) { + if (!orig) return orig + return function (target, mode) { + try { + return orig.call(fs, target, mode) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } -/* eslint-disable no-unused-vars */ -var getOwnPropertySymbols = Object.getOwnPropertySymbols; -var hasOwnProperty = Object.prototype.hasOwnProperty; -var propIsEnumerable = Object.prototype.propertyIsEnumerable; -function toObject(val) { - if (val === null || val === undefined) { - throw new TypeError('Object.assign cannot be called with null or undefined'); - } + function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er) { + if (chownErOk(er)) er = null + if (cb) cb.apply(this, arguments) + }) + } + } - return Object(val); -} + function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } + } -function shouldUseNative() { - try { - if (!Object.assign) { - return false; - } + function statFix (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + function callback (er, stats) { + if (stats) { + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + } + if (cb) cb.apply(this, arguments) + } + return options ? orig.call(fs, target, options, callback) + : orig.call(fs, target, callback) + } + } - // Detect buggy property enumeration order in older V8 versions. + function statFixSync (orig) { + if (!orig) return orig + // Older versions of Node erroneously returned signed integers for + // uid + gid. + return function (target, options) { + var stats = options ? orig.call(fs, target, options) + : orig.call(fs, target) + if (stats.uid < 0) stats.uid += 0x100000000 + if (stats.gid < 0) stats.gid += 0x100000000 + return stats; + } + } - // https://bugs.chromium.org/p/v8/issues/detail?id=4118 - var test1 = new String('abc'); // eslint-disable-line no-new-wrappers - test1[5] = 'de'; - if (Object.getOwnPropertyNames(test1)[0] === '5') { - return false; - } + // ENOSYS means that the fs doesn't support the op. Just ignore + // that, because it doesn't matter. + // + // if there's no getuid, or if getuid() is something other + // than 0, and the error is EINVAL or EPERM, then just ignore + // it. + // + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // + // When running as root, or if other types of errors are + // encountered, then it's strict. + function chownErOk (er) { + if (!er) + return true - // https://bugs.chromium.org/p/v8/issues/detail?id=3056 - var test2 = {}; - for (var i = 0; i < 10; i++) { - test2['_' + String.fromCharCode(i)] = i; - } - var order2 = Object.getOwnPropertyNames(test2).map(function (n) { - return test2[n]; - }); - if (order2.join('') !== '0123456789') { - return false; - } + if (er.code === "ENOSYS") + return true - // https://bugs.chromium.org/p/v8/issues/detail?id=3056 - var test3 = {}; - 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { - test3[letter] = letter; - }); - if (Object.keys(Object.assign({}, test3)).join('') !== - 'abcdefghijklmnopqrst') { - return false; - } + var nonroot = !process.getuid || process.getuid() !== 0 + if (nonroot) { + if (er.code === "EINVAL" || er.code === "EPERM") + return true + } - return true; - } catch (err) { - // We don't expect any of the above to throw, but better to be safe. - return false; - } + return false + } } -module.exports = shouldUseNative() ? Object.assign : function (target, source) { - var from; - var to = toObject(target); - var symbols; - - for (var s = 1; s < arguments.length; s++) { - from = Object(arguments[s]); - - for (var key in from) { - if (hasOwnProperty.call(from, key)) { - to[key] = from[key]; - } - } - - if (getOwnPropertySymbols) { - symbols = getOwnPropertySymbols(from); - for (var i = 0; i < symbols.length; i++) { - if (propIsEnumerable.call(from, symbols[i])) { - to[symbols[i]] = from[symbols[i]]; - } - } - } - } - - return to; -}; - /***/ }), -/* 181 */ +/* 252 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - +var Stream = __webpack_require__(28).Stream -var processFn = function (fn, P, opts) { - return function () { - var that = this; - var args = new Array(arguments.length); +module.exports = legacy - for (var i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } +function legacy (fs) { + return { + ReadStream: ReadStream, + WriteStream: WriteStream + } - return new P(function (resolve, reject) { - args.push(function (err, result) { - if (err) { - reject(err); - } else if (opts.multiArgs) { - var results = new Array(arguments.length - 1); + function ReadStream (path, options) { + if (!(this instanceof ReadStream)) return new ReadStream(path, options); - for (var i = 1; i < arguments.length; i++) { - results[i - 1] = arguments[i]; - } + Stream.call(this); - resolve(results); - } else { - resolve(result); - } - }); + var self = this; - fn.apply(that, args); - }); - }; -}; + this.path = path; + this.fd = null; + this.readable = true; + this.paused = false; -var pify = module.exports = function (obj, P, opts) { - if (typeof P !== 'function') { - opts = P; - P = Promise; - } + this.flags = 'r'; + this.mode = 438; /*=0666*/ + this.bufferSize = 64 * 1024; - opts = opts || {}; - opts.exclude = opts.exclude || [/.+Sync$/]; + options = options || {}; - var filter = function (key) { - var match = function (pattern) { - return typeof pattern === 'string' ? key === pattern : pattern.test(key); - }; + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } - return opts.include ? opts.include.some(match) : !opts.exclude.some(match); - }; + if (this.encoding) this.setEncoding(this.encoding); - var ret = typeof obj === 'function' ? function () { - if (opts.excludeMain) { - return obj.apply(this, arguments); - } + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.end === undefined) { + this.end = Infinity; + } else if ('number' !== typeof this.end) { + throw TypeError('end must be a Number'); + } - return processFn(obj, P, opts).apply(this, arguments); - } : {}; + if (this.start > this.end) { + throw new Error('start must be <= end'); + } - return Object.keys(obj).reduce(function (ret, key) { - var x = obj[key]; + this.pos = this.start; + } - ret[key] = typeof x === 'function' && filter(key) ? processFn(x, P, opts) : x; + if (this.fd !== null) { + process.nextTick(function() { + self._read(); + }); + return; + } - return ret; - }, ret); -}; + fs.open(this.path, this.flags, this.mode, function (err, fd) { + if (err) { + self.emit('error', err); + self.readable = false; + return; + } -pify.all = pify; + self.fd = fd; + self.emit('open', fd); + self._read(); + }) + } + function WriteStream (path, options) { + if (!(this instanceof WriteStream)) return new WriteStream(path, options); -/***/ }), -/* 182 */ -/***/ (function(module, exports, __webpack_require__) { + Stream.call(this); -"use strict"; + this.path = path; + this.fd = null; + this.writable = true; -const path = __webpack_require__(16); + this.flags = 'w'; + this.encoding = 'binary'; + this.mode = 438; /*=0666*/ + this.bytesWritten = 0; -module.exports = path_ => path.resolve(path_) === process.cwd(); + options = options || {}; + // Mixin options into this + var keys = Object.keys(options); + for (var index = 0, length = keys.length; index < length; index++) { + var key = keys[index]; + this[key] = options[key]; + } -/***/ }), -/* 183 */ -/***/ (function(module, exports, __webpack_require__) { + if (this.start !== undefined) { + if ('number' !== typeof this.start) { + throw TypeError('start must be a Number'); + } + if (this.start < 0) { + throw new Error('start must be >= zero'); + } -"use strict"; + this.pos = this.start; + } -const isPathInside = __webpack_require__(184); + this.busy = false; + this._queue = []; -module.exports = path => isPathInside(path, process.cwd()); + if (this.fd === null) { + this._open = fs.open; + this._queue.push([this._open, this.path, this.flags, this.mode, undefined]); + this.flush(); + } + } +} /***/ }), -/* 184 */ +/* 253 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const path = __webpack_require__(16); -const pathIsInside = __webpack_require__(185); -module.exports = (childPath, parentPath) => { - childPath = path.resolve(childPath); - parentPath = path.resolve(parentPath); +module.exports = clone - if (childPath === parentPath) { - return false; - } +function clone (obj) { + if (obj === null || typeof obj !== 'object') + return obj - return pathIsInside(childPath, parentPath); -}; + if (obj instanceof Object) + var copy = { __proto__: obj.__proto__ } + else + var copy = Object.create(null) + + Object.getOwnPropertyNames(obj).forEach(function (key) { + Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key)) + }) + + return copy +} /***/ }), -/* 185 */ +/* 254 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const path = __webpack_require__(16); -var path = __webpack_require__(16); +module.exports = path_ => { + let cwd = process.cwd(); -module.exports = function (thePath, potentialParent) { - // For inside-directory checking, we want to allow trailing slashes, so normalize. - thePath = stripTrailingSep(thePath); - potentialParent = stripTrailingSep(potentialParent); + path_ = path.resolve(path_); - // Node treats only Windows as case-insensitive in its path module; we follow those conventions. - if (process.platform === "win32") { - thePath = thePath.toLowerCase(); - potentialParent = potentialParent.toLowerCase(); - } + if (process.platform === 'win32') { + cwd = cwd.toLowerCase(); + path_ = path_.toLowerCase(); + } - return thePath.lastIndexOf(potentialParent, 0) === 0 && - ( - thePath[potentialParent.length] === path.sep || - thePath[potentialParent.length] === undefined - ); + return path_ === cwd; }; -function stripTrailingSep(thePath) { - if (thePath[thePath.length - 1] === path.sep) { - return thePath.slice(0, -1); - } - return thePath; -} - /***/ }), -/* 186 */ +/* 255 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const path = __webpack_require__(16); -const processFn = (fn, options) => function (...args) { - const P = options.promiseModule; - - return new P((resolve, reject) => { - if (options.multiArgs) { - args.push((...result) => { - if (options.errorFirst) { - if (result[0]) { - reject(result); - } else { - result.shift(); - resolve(result); - } - } else { - resolve(result); - } - }); - } else if (options.errorFirst) { - args.push((error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); - } else { - args.push(resolve); - } - - fn.apply(this, args); - }); -}; - -module.exports = (input, options) => { - options = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, options); +module.exports = (childPath, parentPath) => { + childPath = path.resolve(childPath); + parentPath = path.resolve(parentPath); - const objType = typeof input; - if (!(input !== null && (objType === 'object' || objType === 'function'))) { - throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); + if (process.platform === 'win32') { + childPath = childPath.toLowerCase(); + parentPath = parentPath.toLowerCase(); } - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return options.include ? options.include.some(match) : !options.exclude.some(match); - }; - - let ret; - if (objType === 'function') { - ret = function (...args) { - return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); - }; - } else { - ret = Object.create(Object.getPrototypeOf(input)); + if (childPath === parentPath) { + return false; } - for (const key in input) { // eslint-disable-line guard-for-in - const property = input[key]; - ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; - } + childPath += path.sep; + parentPath += path.sep; - return ret; + return childPath.startsWith(parentPath); }; /***/ }), -/* 187 */ +/* 256 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = rimraf -rimraf.sync = rimrafSync - -var assert = __webpack_require__(30) -var path = __webpack_require__(16) -var fs = __webpack_require__(23) -var glob = __webpack_require__(37) -var _0666 = parseInt('666', 8) +const assert = __webpack_require__(30) +const path = __webpack_require__(16) +const fs = __webpack_require__(23) +let glob = undefined +try { + glob = __webpack_require__(37) +} catch (_err) { + // treat glob as optional. +} -var defaultGlobOpts = { +const defaultGlobOpts = { nosort: true, silent: true } // for EMFILE handling -var timeout = 0 +let timeout = 0 -var isWindows = (process.platform === "win32") +const isWindows = (process.platform === "win32") -function defaults (options) { - var methods = [ +const defaults = options => { + const methods = [ 'unlink', 'chmod', 'stat', @@ -24233,7 +31504,7 @@ function defaults (options) { 'rmdir', 'readdir' ] - methods.forEach(function(m) { + methods.forEach(m => { options[m] = options[m] || fs[m] m = m + 'Sync' options[m] = options[m] || fs[m] @@ -24244,11 +31515,14 @@ function defaults (options) { if (options.glob === false) { options.disableGlob = true } + if (options.disableGlob !== true && glob === undefined) { + throw Error('glob dependency not found, set `options.disableGlob = true` if intentional') + } options.disableGlob = options.disableGlob || false options.glob = options.glob || defaultGlobOpts } -function rimraf (p, options, cb) { +const rimraf = (p, options, cb) => { if (typeof options === 'function') { cb = options options = {} @@ -24262,27 +31536,17 @@ function rimraf (p, options, cb) { defaults(options) - var busyTries = 0 - var errState = null - var n = 0 - - if (options.disableGlob || !glob.hasMagic(p)) - return afterGlob(null, [p]) - - options.lstat(p, function (er, stat) { - if (!er) - return afterGlob(null, [p]) - - glob(p, options.glob, afterGlob) - }) + let busyTries = 0 + let errState = null + let n = 0 - function next (er) { + const next = (er) => { errState = errState || er if (--n === 0) cb(errState) } - function afterGlob (er, results) { + const afterGlob = (er, results) => { if (er) return cb(er) @@ -24290,24 +31554,19 @@ function rimraf (p, options, cb) { if (n === 0) return cb() - results.forEach(function (p) { - rimraf_(p, options, function CB (er) { + results.forEach(p => { + const CB = (er) => { if (er) { if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") && busyTries < options.maxBusyTries) { busyTries ++ - var time = busyTries * 100 // try again, with the same exact callback as this one. - return setTimeout(function () { - rimraf_(p, options, CB) - }, time) + return setTimeout(() => rimraf_(p, options, CB), busyTries * 100) } // this one won't happen if graceful-fs is used. if (er.code === "EMFILE" && timeout < options.emfileWait) { - return setTimeout(function () { - rimraf_(p, options, CB) - }, timeout ++) + return setTimeout(() => rimraf_(p, options, CB), timeout ++) } // already gone @@ -24316,9 +31575,21 @@ function rimraf (p, options, cb) { timeout = 0 next(er) - }) + } + rimraf_(p, options, CB) }) } + + if (options.disableGlob || !glob.hasMagic(p)) + return afterGlob(null, [p]) + + options.lstat(p, (er, stat) => { + if (!er) + return afterGlob(null, [p]) + + glob(p, options.glob, afterGlob) + }) + } // Two possible strategies. @@ -24332,14 +31603,14 @@ function rimraf (p, options, cb) { // // If anyone ever complains about this, then I guess the strategy could // be made configurable somehow. But until then, YAGNI. -function rimraf_ (p, options, cb) { +const rimraf_ = (p, options, cb) => { assert(p) assert(options) assert(typeof cb === 'function') // sunos lets the root user unlink directories, which is... weird. // so we have to lstat here and make sure it's not a dir. - options.lstat(p, function (er, st) { + options.lstat(p, (er, st) => { if (er && er.code === "ENOENT") return cb(null) @@ -24350,7 +31621,7 @@ function rimraf_ (p, options, cb) { if (st && st.isDirectory()) return rmdir(p, options, er, cb) - options.unlink(p, function (er) { + options.unlink(p, er => { if (er) { if (er.code === "ENOENT") return cb(null) @@ -24366,18 +31637,18 @@ function rimraf_ (p, options, cb) { }) } -function fixWinEPERM (p, options, er, cb) { +const fixWinEPERM = (p, options, er, cb) => { assert(p) assert(options) assert(typeof cb === 'function') if (er) assert(er instanceof Error) - options.chmod(p, _0666, function (er2) { + options.chmod(p, 0o666, er2 => { if (er2) cb(er2.code === "ENOENT" ? null : er) else - options.stat(p, function(er3, stats) { + options.stat(p, (er3, stats) => { if (er3) cb(er3.code === "ENOENT" ? null : er) else if (stats.isDirectory()) @@ -24388,14 +31659,14 @@ function fixWinEPERM (p, options, er, cb) { }) } -function fixWinEPERMSync (p, options, er) { +const fixWinEPERMSync = (p, options, er) => { assert(p) assert(options) if (er) assert(er instanceof Error) try { - options.chmodSync(p, _0666) + options.chmodSync(p, 0o666) } catch (er2) { if (er2.code === "ENOENT") return @@ -24403,8 +31674,9 @@ function fixWinEPERMSync (p, options, er) { throw er } + let stats try { - var stats = options.statSync(p) + stats = options.statSync(p) } catch (er3) { if (er3.code === "ENOENT") return @@ -24418,7 +31690,7 @@ function fixWinEPERMSync (p, options, er) { options.unlinkSync(p) } -function rmdir (p, options, originalEr, cb) { +const rmdir = (p, options, originalEr, cb) => { assert(p) assert(options) if (originalEr) @@ -24428,7 +31700,7 @@ function rmdir (p, options, originalEr, cb) { // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS) // if we guessed wrong, and it's not a directory, then // raise the original error. - options.rmdir(p, function (er) { + options.rmdir(p, er => { if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")) rmkids(p, options, cb) else if (er && er.code === "ENOTDIR") @@ -24438,20 +31710,20 @@ function rmdir (p, options, originalEr, cb) { }) } -function rmkids(p, options, cb) { +const rmkids = (p, options, cb) => { assert(p) assert(options) assert(typeof cb === 'function') - options.readdir(p, function (er, files) { + options.readdir(p, (er, files) => { if (er) return cb(er) - var n = files.length + let n = files.length if (n === 0) return options.rmdir(p, cb) - var errState - files.forEach(function (f) { - rimraf(path.join(p, f), options, function (er) { + let errState + files.forEach(f => { + rimraf(path.join(p, f), options, er => { if (errState) return if (er) @@ -24466,7 +31738,7 @@ function rmkids(p, options, cb) { // this looks simpler, and is strictly *faster*, but will // tie up the JavaScript thread and fail on excessively // deep directory trees. -function rimrafSync (p, options) { +const rimrafSync = (p, options) => { options = options || {} defaults(options) @@ -24475,7 +31747,7 @@ function rimrafSync (p, options) { assert(options, 'rimraf: missing options') assert.equal(typeof options, 'object', 'rimraf: options should be object') - var results + let results if (options.disableGlob || !glob.hasMagic(p)) { results = [p] @@ -24491,11 +31763,12 @@ function rimrafSync (p, options) { if (!results.length) return - for (var i = 0; i < results.length; i++) { - var p = results[i] + for (let i = 0; i < results.length; i++) { + const p = results[i] + let st try { - var st = options.lstatSync(p) + st = options.lstatSync(p) } catch (er) { if (er.code === "ENOENT") return @@ -24524,7 +31797,7 @@ function rimrafSync (p, options) { } } -function rmdirSync (p, options, originalEr) { +const rmdirSync = (p, options, originalEr) => { assert(p) assert(options) if (originalEr) @@ -24542,12 +31815,10 @@ function rmdirSync (p, options, originalEr) { } } -function rmkidsSync (p, options) { +const rmkidsSync = (p, options) => { assert(p) assert(options) - options.readdirSync(p).forEach(function (f) { - rimrafSync(path.join(p, f), options) - }) + options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options)) // We only end up here once we got ENOTEMPTY at least once, and // at this point, we are guaranteed to have removed all the kids. @@ -24555,12 +31826,12 @@ function rmkidsSync (p, options) { // try really hard to delete stuff on windows, because it has a // PROFOUNDLY annoying habit of not closing handles promptly when // files are deleted, resulting in spurious ENOTEMPTY errors. - var retries = isWindows ? 100 : 1 - var i = 0 + const retries = isWindows ? 100 : 1 + let i = 0 do { - var threw = true + let threw = true try { - var ret = options.rmdirSync(p, options) + const ret = options.rmdirSync(p, options) threw = false return ret } finally { @@ -24570,95 +31841,242 @@ function rmkidsSync (p, options) { } while (true) } +module.exports = rimraf +rimraf.sync = rimrafSync + /***/ }), -/* 188 */ +/* 257 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +const AggregateError = __webpack_require__(258); -const pMap = (iterable, mapper, options) => new Promise((resolve, reject) => { - options = Object.assign({ - concurrency: Infinity - }, options); - - if (typeof mapper !== 'function') { - throw new TypeError('Mapper function is required'); - } +module.exports = async ( + iterable, + mapper, + { + concurrency = Infinity, + stopOnError = true + } = {} +) => { + return new Promise((resolve, reject) => { + if (typeof mapper !== 'function') { + throw new TypeError('Mapper function is required'); + } - const {concurrency} = options; + if (!(typeof concurrency === 'number' && concurrency >= 1)) { + throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); + } - if (!(typeof concurrency === 'number' && concurrency >= 1)) { - throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${concurrency}\` (${typeof concurrency})`); - } + const ret = []; + const errors = []; + const iterator = iterable[Symbol.iterator](); + let isRejected = false; + let isIterableDone = false; + let resolvingCount = 0; + let currentIndex = 0; - const ret = []; - const iterator = iterable[Symbol.iterator](); - let isRejected = false; - let isIterableDone = false; - let resolvingCount = 0; - let currentIndex = 0; + const next = () => { + if (isRejected) { + return; + } - const next = () => { - if (isRejected) { - return; - } + const nextItem = iterator.next(); + const i = currentIndex; + currentIndex++; - const nextItem = iterator.next(); - const i = currentIndex; - currentIndex++; + if (nextItem.done) { + isIterableDone = true; - if (nextItem.done) { - isIterableDone = true; + if (resolvingCount === 0) { + if (!stopOnError && errors.length !== 0) { + reject(new AggregateError(errors)); + } else { + resolve(ret); + } + } - if (resolvingCount === 0) { - resolve(ret); + return; } - return; - } - - resolvingCount++; + resolvingCount++; - Promise.resolve(nextItem.value) - .then(element => mapper(element, i)) - .then( - value => { - ret[i] = value; + (async () => { + try { + const element = await nextItem.value; + ret[i] = await mapper(element, i); resolvingCount--; next(); - }, - error => { - isRejected = true; - reject(error); + } catch (error) { + if (stopOnError) { + isRejected = true; + reject(error); + } else { + errors.push(error); + resolvingCount--; + next(); + } } - ); - }; + })(); + }; - for (let i = 0; i < concurrency; i++) { - next(); + for (let i = 0; i < concurrency; i++) { + next(); - if (isIterableDone) { - break; + if (isIterableDone) { + break; + } } + }); +}; + + +/***/ }), +/* 258 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const indentString = __webpack_require__(259); +const cleanStack = __webpack_require__(260); + +const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); + +class AggregateError extends Error { + constructor(errors) { + if (!Array.isArray(errors)) { + throw new TypeError(`Expected input to be an Array, got ${typeof errors}`); + } + + errors = [...errors].map(error => { + if (error instanceof Error) { + return error; + } + + if (error !== null && typeof error === 'object') { + // Handle plain error objects with message property and/or possibly other metadata + return Object.assign(new Error(error.message), error); + } + + return new Error(error); + }); + + let message = errors + .map(error => { + // The `stack` property is not standardized, so we can't assume it exists + return typeof error.stack === 'string' ? cleanInternalStack(cleanStack(error.stack)) : String(error); + }) + .join('\n'); + message = '\n' + indentString(message, 4); + super(message); + + this.name = 'AggregateError'; + + Object.defineProperty(this, '_errors', {value: errors}); } -}); -module.exports = pMap; -// TODO: Remove this for the next major release -module.exports.default = pMap; + * [Symbol.iterator]() { + for (const error of this._errors) { + yield error; + } + } +} + +module.exports = AggregateError; /***/ }), -/* 189 */ +/* 259 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = (str, count, opts) => { + // Support older versions: use the third parameter as options.indent + // TODO: Remove the workaround in the next major version + const options = typeof opts === 'object' ? Object.assign({indent: ' '}, opts) : {indent: opts || ' '}; + count = count === undefined ? 1 : count; + + if (typeof str !== 'string') { + throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof str}\``); + } + + if (typeof count !== 'number') { + throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof count}\``); + } + + if (typeof options.indent !== 'string') { + throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof options.indent}\``); + } + + if (count === 0) { + return str; + } + + const regex = options.includeEmptyLines ? /^/mg : /^(?!\s*$)/mg; + return str.replace(regex, options.indent.repeat(count)); +} +; + + +/***/ }), +/* 260 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(190); -const cliCursor = __webpack_require__(194); -const cliSpinners = __webpack_require__(198); +const os = __webpack_require__(11); + +const extractPathRegex = /\s+at.*(?:\(|\s)(.*)\)?/; +const pathRegex = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:babel-polyfill|pirates)\/.*)?\w+)\.js:\d+:\d+)|native)/; +const homeDir = os.homedir(); + +module.exports = (stack, options) => { + options = Object.assign({pretty: false}, options); + + return stack.replace(/\\/g, '/') + .split('\n') + .filter(line => { + const pathMatches = line.match(extractPathRegex); + if (pathMatches === null || !pathMatches[1]) { + return true; + } + + const match = pathMatches[1]; + + // Electron + if ( + match.includes('.app/Contents/Resources/electron.asar') || + match.includes('.app/Contents/Resources/default_app.asar') + ) { + return false; + } + + return !pathRegex.test(match); + }) + .filter(line => line.trim() !== '') + .map(line => { + if (options.pretty) { + return line.replace(extractPathRegex, (m, p1) => m.replace(p1, p1.replace(homeDir, '~'))); + } + + return line; + }) + .join('\n'); +}; + + +/***/ }), +/* 261 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +const chalk = __webpack_require__(262); +const cliCursor = __webpack_require__(266); +const cliSpinners = __webpack_require__(270); const logSymbols = __webpack_require__(158); class Ora { @@ -24806,16 +32224,16 @@ module.exports.promise = (action, options) => { /***/ }), -/* 190 */ +/* 262 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(191); -const stdoutColor = __webpack_require__(192).stdout; +const ansiStyles = __webpack_require__(263); +const stdoutColor = __webpack_require__(264).stdout; -const template = __webpack_require__(193); +const template = __webpack_require__(265); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -25041,7 +32459,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 191 */ +/* 263 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -25214,7 +32632,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 192 */ +/* 264 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -25356,7 +32774,7 @@ module.exports = { /***/ }), -/* 193 */ +/* 265 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -25491,12 +32909,12 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 194 */ +/* 266 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(195); +const restoreCursor = __webpack_require__(267); let hidden = false; @@ -25537,12 +32955,12 @@ exports.toggle = (force, stream) => { /***/ }), -/* 195 */ +/* 267 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(196); +const onetime = __webpack_require__(268); const signalExit = __webpack_require__(110); module.exports = onetime(() => { @@ -25553,12 +32971,12 @@ module.exports = onetime(() => { /***/ }), -/* 196 */ +/* 268 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(197); +const mimicFn = __webpack_require__(269); module.exports = (fn, opts) => { // TODO: Remove this in v3 @@ -25599,7 +33017,7 @@ module.exports = (fn, opts) => { /***/ }), -/* 197 */ +/* 269 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -25615,22 +33033,22 @@ module.exports = (to, from) => { /***/ }), -/* 198 */ +/* 270 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(199); +module.exports = __webpack_require__(271); /***/ }), -/* 199 */ +/* 271 */ /***/ (function(module) { module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]}}"); /***/ }), -/* 200 */ +/* 272 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -25690,7 +33108,7 @@ const RunCommand = { }; /***/ }), -/* 201 */ +/* 273 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -25701,7 +33119,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(35); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(36); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(202); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(274); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -25785,14 +33203,14 @@ const WatchCommand = { }; /***/ }), -/* 202 */ +/* 274 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "waitUntilWatchIsReady", function() { return waitUntilWatchIsReady; }); -/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(203); -/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(302); +/* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(275); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(374); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -25859,168 +33277,168 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 203 */ +/* 275 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _internal_Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return _internal_Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]; }); -/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(222); +/* harmony import */ var _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(294); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return _internal_observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_1__["ConnectableObservable"]; }); -/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(227); +/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(299); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_2__["GroupedObservable"]; }); -/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(219); +/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(291); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observable", function() { return _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_3__["observable"]; }); -/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(223); +/* harmony import */ var _internal_Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(295); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return _internal_Subject__WEBPACK_IMPORTED_MODULE_4__["Subject"]; }); -/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(228); +/* harmony import */ var _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(300); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return _internal_BehaviorSubject__WEBPACK_IMPORTED_MODULE_5__["BehaviorSubject"]; }); -/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(229); +/* harmony import */ var _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(301); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return _internal_ReplaySubject__WEBPACK_IMPORTED_MODULE_6__["ReplaySubject"]; }); -/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(246); +/* harmony import */ var _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(318); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return _internal_AsyncSubject__WEBPACK_IMPORTED_MODULE_7__["AsyncSubject"]; }); -/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(247); +/* harmony import */ var _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(319); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asapScheduler", function() { return _internal_scheduler_asap__WEBPACK_IMPORTED_MODULE_8__["asap"]; }); -/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(251); +/* harmony import */ var _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(323); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "asyncScheduler", function() { return _internal_scheduler_async__WEBPACK_IMPORTED_MODULE_9__["async"]; }); -/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(230); +/* harmony import */ var _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(302); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "queueScheduler", function() { return _internal_scheduler_queue__WEBPACK_IMPORTED_MODULE_10__["queue"]; }); -/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(252); +/* harmony import */ var _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(324); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "animationFrameScheduler", function() { return _internal_scheduler_animationFrame__WEBPACK_IMPORTED_MODULE_11__["animationFrame"]; }); -/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(255); +/* harmony import */ var _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(327); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualTimeScheduler"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return _internal_scheduler_VirtualTimeScheduler__WEBPACK_IMPORTED_MODULE_12__["VirtualAction"]; }); -/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(236); +/* harmony import */ var _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(308); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Scheduler", function() { return _internal_Scheduler__WEBPACK_IMPORTED_MODULE_13__["Scheduler"]; }); -/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(212); +/* harmony import */ var _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(284); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return _internal_Subscription__WEBPACK_IMPORTED_MODULE_14__["Subscription"]; }); -/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(206); +/* harmony import */ var _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(278); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return _internal_Subscriber__WEBPACK_IMPORTED_MODULE_15__["Subscriber"]; }); -/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(238); +/* harmony import */ var _internal_Notification__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(310); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return _internal_Notification__WEBPACK_IMPORTED_MODULE_16__["Notification"]; }); -/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(220); +/* harmony import */ var _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(292); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return _internal_util_pipe__WEBPACK_IMPORTED_MODULE_17__["pipe"]; }); -/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(221); +/* harmony import */ var _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(293); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "noop", function() { return _internal_util_noop__WEBPACK_IMPORTED_MODULE_18__["noop"]; }); -/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(256); +/* harmony import */ var _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(328); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "identity", function() { return _internal_util_identity__WEBPACK_IMPORTED_MODULE_19__["identity"]; }); -/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(257); +/* harmony import */ var _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(329); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return _internal_util_isObservable__WEBPACK_IMPORTED_MODULE_20__["isObservable"]; }); -/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(258); +/* harmony import */ var _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(330); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return _internal_util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_21__["ArgumentOutOfRangeError"]; }); -/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(259); +/* harmony import */ var _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(331); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return _internal_util_EmptyError__WEBPACK_IMPORTED_MODULE_22__["EmptyError"]; }); -/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(224); +/* harmony import */ var _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(296); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return _internal_util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_23__["ObjectUnsubscribedError"]; }); -/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(217); +/* harmony import */ var _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(289); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return _internal_util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_24__["UnsubscriptionError"]; }); -/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(260); +/* harmony import */ var _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(332); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return _internal_util_TimeoutError__WEBPACK_IMPORTED_MODULE_25__["TimeoutError"]; }); -/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(261); +/* harmony import */ var _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(333); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return _internal_observable_bindCallback__WEBPACK_IMPORTED_MODULE_26__["bindCallback"]; }); -/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(263); +/* harmony import */ var _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(335); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return _internal_observable_bindNodeCallback__WEBPACK_IMPORTED_MODULE_27__["bindNodeCallback"]; }); -/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(264); +/* harmony import */ var _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(336); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_observable_combineLatest__WEBPACK_IMPORTED_MODULE_28__["combineLatest"]; }); -/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(275); +/* harmony import */ var _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(347); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_observable_concat__WEBPACK_IMPORTED_MODULE_29__["concat"]; }); -/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(285); +/* harmony import */ var _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(357); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return _internal_observable_defer__WEBPACK_IMPORTED_MODULE_30__["defer"]; }); -/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(239); +/* harmony import */ var _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(311); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["empty"]; }); -/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(286); +/* harmony import */ var _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(358); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return _internal_observable_forkJoin__WEBPACK_IMPORTED_MODULE_32__["forkJoin"]; }); -/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(276); +/* harmony import */ var _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(348); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "from", function() { return _internal_observable_from__WEBPACK_IMPORTED_MODULE_33__["from"]; }); -/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(287); +/* harmony import */ var _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(359); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return _internal_observable_fromEvent__WEBPACK_IMPORTED_MODULE_34__["fromEvent"]; }); -/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(288); +/* harmony import */ var _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(360); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return _internal_observable_fromEventPattern__WEBPACK_IMPORTED_MODULE_35__["fromEventPattern"]; }); -/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(289); +/* harmony import */ var _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(361); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return _internal_observable_generate__WEBPACK_IMPORTED_MODULE_36__["generate"]; }); -/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(290); +/* harmony import */ var _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(362); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return _internal_observable_iif__WEBPACK_IMPORTED_MODULE_37__["iif"]; }); -/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(291); +/* harmony import */ var _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(363); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return _internal_observable_interval__WEBPACK_IMPORTED_MODULE_38__["interval"]; }); -/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(293); +/* harmony import */ var _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(365); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_observable_merge__WEBPACK_IMPORTED_MODULE_39__["merge"]; }); -/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(294); +/* harmony import */ var _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(366); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "never", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["never"]; }); -/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(240); +/* harmony import */ var _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(312); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "of", function() { return _internal_observable_of__WEBPACK_IMPORTED_MODULE_41__["of"]; }); -/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(295); +/* harmony import */ var _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(367); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_observable_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_42__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(296); +/* harmony import */ var _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(368); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return _internal_observable_pairs__WEBPACK_IMPORTED_MODULE_43__["pairs"]; }); -/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(297); +/* harmony import */ var _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(369); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_observable_race__WEBPACK_IMPORTED_MODULE_44__["race"]; }); -/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(298); +/* harmony import */ var _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(370); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "range", function() { return _internal_observable_range__WEBPACK_IMPORTED_MODULE_45__["range"]; }); -/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(245); +/* harmony import */ var _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(317); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return _internal_observable_throwError__WEBPACK_IMPORTED_MODULE_46__["throwError"]; }); -/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(299); +/* harmony import */ var _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(371); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return _internal_observable_timer__WEBPACK_IMPORTED_MODULE_47__["timer"]; }); -/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(300); +/* harmony import */ var _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(372); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "using", function() { return _internal_observable_using__WEBPACK_IMPORTED_MODULE_48__["using"]; }); -/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(301); +/* harmony import */ var _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(373); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_observable_zip__WEBPACK_IMPORTED_MODULE_49__["zip"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return _internal_observable_empty__WEBPACK_IMPORTED_MODULE_31__["EMPTY"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return _internal_observable_never__WEBPACK_IMPORTED_MODULE_40__["NEVER"]; }); -/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(210); +/* harmony import */ var _internal_config__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(282); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "config", function() { return _internal_config__WEBPACK_IMPORTED_MODULE_50__["config"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -26081,16 +33499,16 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 204 */ +/* 276 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return Observable; }); -/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(205); -/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(219); -/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(220); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(210); +/* harmony import */ var _util_toSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(277); +/* harmony import */ var _internal_symbol_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(291); +/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(292); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(282); /** PURE_IMPORTS_START _util_toSubscriber,_internal_symbol_observable,_util_pipe,_config PURE_IMPORTS_END */ @@ -26204,15 +33622,15 @@ function getPromiseCtor(promiseCtor) { /***/ }), -/* 205 */ +/* 277 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toSubscriber", function() { return toSubscriber; }); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(206); -/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(218); -/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(209); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(278); +/* harmony import */ var _symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(290); +/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(281); /** PURE_IMPORTS_START _Subscriber,_symbol_rxSubscriber,_Observer PURE_IMPORTS_END */ @@ -26235,19 +33653,19 @@ function toSubscriber(nextOrObserver, error, complete) { /***/ }), -/* 206 */ +/* 278 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscriber", function() { return Subscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(208); -/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(209); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(212); -/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(218); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(210); -/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(211); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(280); +/* harmony import */ var _Observer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(281); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(284); +/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(290); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(282); +/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(283); /** PURE_IMPORTS_START tslib,_util_isFunction,_Observer,_Subscription,_internal_symbol_rxSubscriber,_config,_util_hostReportError PURE_IMPORTS_END */ @@ -26489,7 +33907,7 @@ function isTrustedSubscriber(obj) { /***/ }), -/* 207 */ +/* 279 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26702,7 +34120,7 @@ function __importDefault(mod) { /***/ }), -/* 208 */ +/* 280 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26716,14 +34134,14 @@ function isFunction(x) { /***/ }), -/* 209 */ +/* 281 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(210); -/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(211); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(282); +/* harmony import */ var _util_hostReportError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(283); /** PURE_IMPORTS_START _config,_util_hostReportError PURE_IMPORTS_END */ @@ -26744,7 +34162,7 @@ var empty = { /***/ }), -/* 210 */ +/* 282 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26772,7 +34190,7 @@ var config = { /***/ }), -/* 211 */ +/* 283 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26786,18 +34204,18 @@ function hostReportError(err) { /***/ }), -/* 212 */ +/* 284 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subscription", function() { return Subscription; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); -/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(214); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(216); -/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(217); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285); +/* harmony import */ var _util_isObject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(286); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(280); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(288); +/* harmony import */ var _util_UnsubscriptionError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(289); /** PURE_IMPORTS_START _util_isArray,_util_isObject,_util_isFunction,_util_tryCatch,_util_errorObject,_util_UnsubscriptionError PURE_IMPORTS_END */ @@ -26933,7 +34351,7 @@ function flattenUnsubscriptionErrors(errors) { /***/ }), -/* 213 */ +/* 285 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26945,7 +34363,7 @@ var isArray = Array.isArray || (function (x) { return x && typeof x.length === ' /***/ }), -/* 214 */ +/* 286 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26959,13 +34377,13 @@ function isObject(x) { /***/ }), -/* 215 */ +/* 287 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tryCatch", function() { return tryCatch; }); -/* harmony import */ var _errorObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(216); +/* harmony import */ var _errorObject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(288); /** PURE_IMPORTS_START _errorObject PURE_IMPORTS_END */ var tryCatchTarget; @@ -26986,7 +34404,7 @@ function tryCatch(fn) { /***/ }), -/* 216 */ +/* 288 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -26998,13 +34416,13 @@ var errorObject = { e: {} }; /***/ }), -/* 217 */ +/* 289 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UnsubscriptionError", function() { return UnsubscriptionError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var UnsubscriptionError = /*@__PURE__*/ (function (_super) { @@ -27024,7 +34442,7 @@ var UnsubscriptionError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 218 */ +/* 290 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27040,7 +34458,7 @@ var $$rxSubscriber = rxSubscriber; /***/ }), -/* 219 */ +/* 291 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27052,14 +34470,14 @@ var observable = typeof Symbol === 'function' && Symbol.observable || '@@observa /***/ }), -/* 220 */ +/* 292 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipe", function() { return pipe; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pipeFromArray", function() { return pipeFromArray; }); -/* harmony import */ var _noop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(221); +/* harmony import */ var _noop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(293); /** PURE_IMPORTS_START _noop PURE_IMPORTS_END */ function pipe() { @@ -27084,7 +34502,7 @@ function pipeFromArray(fns) { /***/ }), -/* 221 */ +/* 293 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27096,19 +34514,19 @@ function noop() { } /***/ }), -/* 222 */ +/* 294 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConnectableObservable", function() { return ConnectableObservable; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "connectableObservableDescriptor", function() { return connectableObservableDescriptor; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(212); -/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(226); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(284); +/* harmony import */ var _operators_refCount__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(298); /** PURE_IMPORTS_START tslib,_Subject,_Observable,_Subscriber,_Subscription,_operators_refCount PURE_IMPORTS_END */ @@ -27255,7 +34673,7 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 223 */ +/* 295 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -27263,13 +34681,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubjectSubscriber", function() { return SubjectSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Subject", function() { return Subject; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnonymousSubject", function() { return AnonymousSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(212); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(224); -/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(225); -/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(218); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(278); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(284); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(296); +/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(297); +/* harmony import */ var _internal_symbol_rxSubscriber__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(290); /** PURE_IMPORTS_START tslib,_Observable,_Subscriber,_Subscription,_util_ObjectUnsubscribedError,_SubjectSubscription,_internal_symbol_rxSubscriber PURE_IMPORTS_END */ @@ -27431,13 +34849,13 @@ var AnonymousSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 224 */ +/* 296 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObjectUnsubscribedError", function() { return ObjectUnsubscribedError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var ObjectUnsubscribedError = /*@__PURE__*/ (function (_super) { @@ -27455,14 +34873,14 @@ var ObjectUnsubscribedError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 225 */ +/* 297 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubjectSubscription", function() { return SubjectSubscription; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */ @@ -27498,14 +34916,14 @@ var SubjectSubscription = /*@__PURE__*/ (function (_super) { /***/ }), -/* 226 */ +/* 298 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return refCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -27567,18 +34985,18 @@ var RefCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 227 */ +/* 299 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return groupBy; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GroupedObservable", function() { return GroupedObservable; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(204); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(223); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(276); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(295); /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription,_Observable,_Subject PURE_IMPORTS_END */ @@ -27764,15 +35182,15 @@ var InnerRefCountSubscription = /*@__PURE__*/ (function (_super) { /***/ }), -/* 228 */ +/* 300 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BehaviorSubject", function() { return BehaviorSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(224); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(296); /** PURE_IMPORTS_START tslib,_Subject,_util_ObjectUnsubscribedError PURE_IMPORTS_END */ @@ -27819,19 +35237,19 @@ var BehaviorSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 229 */ +/* 301 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReplaySubject", function() { return ReplaySubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(230); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(212); -/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(237); -/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(224); -/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(225); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _scheduler_queue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(302); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(284); +/* harmony import */ var _operators_observeOn__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(309); +/* harmony import */ var _util_ObjectUnsubscribedError__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(296); +/* harmony import */ var _SubjectSubscription__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(297); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_queue,_Subscription,_operators_observeOn,_util_ObjectUnsubscribedError,_SubjectSubscription PURE_IMPORTS_END */ @@ -27952,14 +35370,14 @@ var ReplayEvent = /*@__PURE__*/ (function () { /***/ }), -/* 230 */ +/* 302 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "queue", function() { return queue; }); -/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(231); -/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(234); +/* harmony import */ var _QueueAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(303); +/* harmony import */ var _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(306); /** PURE_IMPORTS_START _QueueAction,_QueueScheduler PURE_IMPORTS_END */ @@ -27968,14 +35386,14 @@ var queue = /*@__PURE__*/ new _QueueScheduler__WEBPACK_IMPORTED_MODULE_1__["Queu /***/ }), -/* 231 */ +/* 303 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueAction", function() { return QueueAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304); /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */ @@ -28020,14 +35438,14 @@ var QueueAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 232 */ +/* 304 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncAction", function() { return AsyncAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(233); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Action__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(305); /** PURE_IMPORTS_START tslib,_Action PURE_IMPORTS_END */ @@ -28125,14 +35543,14 @@ var AsyncAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 233 */ +/* 305 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Action", function() { return Action; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); /** PURE_IMPORTS_START tslib,_Subscription PURE_IMPORTS_END */ @@ -28154,14 +35572,14 @@ var Action = /*@__PURE__*/ (function (_super) { /***/ }), -/* 234 */ +/* 306 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "QueueScheduler", function() { return QueueScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -28177,14 +35595,14 @@ var QueueScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 235 */ +/* 307 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncScheduler", function() { return AsyncScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(236); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Scheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(308); /** PURE_IMPORTS_START tslib,_Scheduler PURE_IMPORTS_END */ @@ -28246,7 +35664,7 @@ var AsyncScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 236 */ +/* 308 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28274,7 +35692,7 @@ var Scheduler = /*@__PURE__*/ (function () { /***/ }), -/* 237 */ +/* 309 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28283,9 +35701,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnOperator", function() { return ObserveOnOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnSubscriber", function() { return ObserveOnSubscriber; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ObserveOnMessage", function() { return ObserveOnMessage; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(238); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(310); /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -28355,15 +35773,15 @@ var ObserveOnMessage = /*@__PURE__*/ (function () { /***/ }), -/* 238 */ +/* 310 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Notification", function() { return Notification; }); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(239); -/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); -/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(245); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(311); +/* harmony import */ var _observable_of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(312); +/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(317); /** PURE_IMPORTS_START _observable_empty,_observable_of,_observable_throwError PURE_IMPORTS_END */ @@ -28437,7 +35855,7 @@ var Notification = /*@__PURE__*/ (function () { /***/ }), -/* 239 */ +/* 311 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28445,7 +35863,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EMPTY", function() { return EMPTY; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "empty", function() { return empty; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "emptyScheduled", function() { return emptyScheduled; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ var EMPTY = /*@__PURE__*/ new _Observable__WEBPACK_IMPORTED_MODULE_0__["Observable"](function (subscriber) { return subscriber.complete(); }); @@ -28459,16 +35877,16 @@ function emptyScheduled(scheduler) { /***/ }), -/* 240 */ +/* 312 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "of", function() { return of; }); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(241); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); -/* harmony import */ var _scalar__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(244); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(313); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(314); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311); +/* harmony import */ var _scalar__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(316); /** PURE_IMPORTS_START _util_isScheduler,_fromArray,_empty,_scalar PURE_IMPORTS_END */ @@ -28499,7 +35917,7 @@ function of() { /***/ }), -/* 241 */ +/* 313 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28513,15 +35931,15 @@ function isScheduler(value) { /***/ }), -/* 242 */ +/* 314 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromArray", function() { return fromArray; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); -/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(243); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); +/* harmony import */ var _util_subscribeToArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(315); /** PURE_IMPORTS_START _Observable,_Subscription,_util_subscribeToArray PURE_IMPORTS_END */ @@ -28552,7 +35970,7 @@ function fromArray(input, scheduler) { /***/ }), -/* 243 */ +/* 315 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28573,13 +35991,13 @@ var subscribeToArray = function (array) { /***/ }), -/* 244 */ +/* 316 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scalar", function() { return scalar; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function scalar(value) { @@ -28595,13 +36013,13 @@ function scalar(value) { /***/ }), -/* 245 */ +/* 317 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwError", function() { return throwError; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function throwError(error, scheduler) { @@ -28620,15 +36038,15 @@ function dispatch(_a) { /***/ }), -/* 246 */ +/* 318 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncSubject", function() { return AsyncSubject; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284); /** PURE_IMPORTS_START tslib,_Subject,_Subscription PURE_IMPORTS_END */ @@ -28679,14 +36097,14 @@ var AsyncSubject = /*@__PURE__*/ (function (_super) { /***/ }), -/* 247 */ +/* 319 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "asap", function() { return asap; }); -/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(248); -/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(250); +/* harmony import */ var _AsapAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(320); +/* harmony import */ var _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(322); /** PURE_IMPORTS_START _AsapAction,_AsapScheduler PURE_IMPORTS_END */ @@ -28695,15 +36113,15 @@ var asap = /*@__PURE__*/ new _AsapScheduler__WEBPACK_IMPORTED_MODULE_1__["AsapSc /***/ }), -/* 248 */ +/* 320 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapAction", function() { return AsapAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(249); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(232); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _util_Immediate__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(321); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(304); /** PURE_IMPORTS_START tslib,_util_Immediate,_AsyncAction PURE_IMPORTS_END */ @@ -28746,7 +36164,7 @@ var AsapAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 249 */ +/* 321 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -28776,14 +36194,14 @@ var Immediate = { /***/ }), -/* 250 */ +/* 322 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsapScheduler", function() { return AsapScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -28820,14 +36238,14 @@ var AsapScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 251 */ +/* 323 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "async", function() { return async; }); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(232); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(304); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307); /** PURE_IMPORTS_START _AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ @@ -28836,14 +36254,14 @@ var async = /*@__PURE__*/ new _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__["Asyn /***/ }), -/* 252 */ +/* 324 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "animationFrame", function() { return animationFrame; }); -/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(253); -/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(254); +/* harmony import */ var _AnimationFrameAction__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(325); +/* harmony import */ var _AnimationFrameScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(326); /** PURE_IMPORTS_START _AnimationFrameAction,_AnimationFrameScheduler PURE_IMPORTS_END */ @@ -28852,14 +36270,14 @@ var animationFrame = /*@__PURE__*/ new _AnimationFrameScheduler__WEBPACK_IMPORTE /***/ }), -/* 253 */ +/* 325 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameAction", function() { return AnimationFrameAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304); /** PURE_IMPORTS_START tslib,_AsyncAction PURE_IMPORTS_END */ @@ -28901,14 +36319,14 @@ var AnimationFrameAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 254 */ +/* 326 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AnimationFrameScheduler", function() { return AnimationFrameScheduler; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(235); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(307); /** PURE_IMPORTS_START tslib,_AsyncScheduler PURE_IMPORTS_END */ @@ -28945,16 +36363,16 @@ var AnimationFrameScheduler = /*@__PURE__*/ (function (_super) { /***/ }), -/* 255 */ +/* 327 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualTimeScheduler", function() { return VirtualTimeScheduler; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualAction", function() { return VirtualAction; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(232); -/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(235); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _AsyncAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304); +/* harmony import */ var _AsyncScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(307); /** PURE_IMPORTS_START tslib,_AsyncAction,_AsyncScheduler PURE_IMPORTS_END */ @@ -29066,7 +36484,7 @@ var VirtualAction = /*@__PURE__*/ (function (_super) { /***/ }), -/* 256 */ +/* 328 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29080,13 +36498,13 @@ function identity(x) { /***/ }), -/* 257 */ +/* 329 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isObservable", function() { return isObservable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function isObservable(obj) { @@ -29096,13 +36514,13 @@ function isObservable(obj) { /***/ }), -/* 258 */ +/* 330 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArgumentOutOfRangeError", function() { return ArgumentOutOfRangeError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var ArgumentOutOfRangeError = /*@__PURE__*/ (function (_super) { @@ -29120,13 +36538,13 @@ var ArgumentOutOfRangeError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 259 */ +/* 331 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmptyError", function() { return EmptyError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var EmptyError = /*@__PURE__*/ (function (_super) { @@ -29144,13 +36562,13 @@ var EmptyError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 260 */ +/* 332 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeoutError", function() { return TimeoutError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); /** PURE_IMPORTS_START tslib PURE_IMPORTS_END */ var TimeoutError = /*@__PURE__*/ (function (_super) { @@ -29168,17 +36586,17 @@ var TimeoutError = /*@__PURE__*/ (function (_super) { /***/ }), -/* 261 */ +/* 333 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindCallback", function() { return bindCallback; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(262); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(213); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(241); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(318); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(334); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(285); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(313); /** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_isArray,_util_isScheduler PURE_IMPORTS_END */ @@ -29281,15 +36699,15 @@ function dispatchError(state) { /***/ }), -/* 262 */ +/* 334 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "map", function() { return map; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MapOperator", function() { return MapOperator; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -29338,17 +36756,17 @@ var MapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 263 */ +/* 335 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bindNodeCallback", function() { return bindNodeCallback; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(246); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(262); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(241); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(213); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(318); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(334); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(313); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(285); /** PURE_IMPORTS_START _Observable,_AsyncSubject,_operators_map,_util_isScheduler,_util_isArray PURE_IMPORTS_END */ @@ -29459,7 +36877,7 @@ function dispatchError(arg) { /***/ }), -/* 264 */ +/* 336 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29467,12 +36885,12 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestOperator", function() { return CombineLatestOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CombineLatestSubscriber", function() { return CombineLatestSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(241); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(242); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(314); /** PURE_IMPORTS_START tslib,_util_isScheduler,_util_isArray,_OuterSubscriber,_util_subscribeToResult,_fromArray PURE_IMPORTS_END */ @@ -29577,14 +36995,14 @@ var CombineLatestSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 265 */ +/* 337 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "OuterSubscriber", function() { return OuterSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -29609,14 +37027,14 @@ var OuterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 266 */ +/* 338 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToResult", function() { return subscribeToResult; }); -/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(267); -/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(268); +/* harmony import */ var _InnerSubscriber__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(339); +/* harmony import */ var _subscribeTo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(340); /** PURE_IMPORTS_START _InnerSubscriber,_subscribeTo PURE_IMPORTS_END */ @@ -29628,14 +37046,14 @@ function subscribeToResult(outerSubscriber, result, outerValue, outerIndex) { /***/ }), -/* 267 */ +/* 339 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InnerSubscriber", function() { return InnerSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -29667,22 +37085,22 @@ var InnerSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 268 */ +/* 340 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeTo", function() { return subscribeTo; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(243); -/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(269); -/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(270); -/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(272); -/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(273); -/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(274); -/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(214); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(271); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(219); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _subscribeToArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(315); +/* harmony import */ var _subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(341); +/* harmony import */ var _subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(342); +/* harmony import */ var _subscribeToObservable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(344); +/* harmony import */ var _isArrayLike__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(345); +/* harmony import */ var _isPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(346); +/* harmony import */ var _isObject__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(286); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(343); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(291); /** PURE_IMPORTS_START _Observable,_subscribeToArray,_subscribeToPromise,_subscribeToIterable,_subscribeToObservable,_isArrayLike,_isPromise,_isObject,_symbol_iterator,_symbol_observable PURE_IMPORTS_END */ @@ -29730,13 +37148,13 @@ var subscribeTo = function (result) { /***/ }), -/* 269 */ +/* 341 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToPromise", function() { return subscribeToPromise; }); -/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(211); +/* harmony import */ var _hostReportError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(283); /** PURE_IMPORTS_START _hostReportError PURE_IMPORTS_END */ var subscribeToPromise = function (promise) { @@ -29755,13 +37173,13 @@ var subscribeToPromise = function (promise) { /***/ }), -/* 270 */ +/* 342 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToIterable", function() { return subscribeToIterable; }); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(271); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(343); /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */ var subscribeToIterable = function (iterable) { @@ -29792,7 +37210,7 @@ var subscribeToIterable = function (iterable) { /***/ }), -/* 271 */ +/* 343 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29813,13 +37231,13 @@ var $$iterator = iterator; /***/ }), -/* 272 */ +/* 344 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeToObservable", function() { return subscribeToObservable; }); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(219); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(291); /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */ var subscribeToObservable = function (obj) { @@ -29837,7 +37255,7 @@ var subscribeToObservable = function (obj) { /***/ }), -/* 273 */ +/* 345 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29849,7 +37267,7 @@ var isArrayLike = (function (x) { return x && typeof x.length === 'number' && ty /***/ }), -/* 274 */ +/* 346 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -29863,16 +37281,16 @@ function isPromise(value) { /***/ }), -/* 275 */ +/* 347 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; }); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(241); -/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276); -/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(282); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(313); +/* harmony import */ var _of__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(312); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(348); +/* harmony import */ var _operators_concatAll__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(354); /** PURE_IMPORTS_START _util_isScheduler,_of,_from,_operators_concatAll PURE_IMPORTS_END */ @@ -29892,22 +37310,22 @@ function concat() { /***/ }), -/* 276 */ +/* 348 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "from", function() { return from; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(274); -/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(273); -/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(277); -/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(278); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(242); -/* harmony import */ var _fromPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(279); -/* harmony import */ var _fromIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(280); -/* harmony import */ var _fromObservable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(281); -/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(268); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _util_isPromise__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(346); +/* harmony import */ var _util_isArrayLike__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(345); +/* harmony import */ var _util_isInteropObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(349); +/* harmony import */ var _util_isIterable__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(350); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(314); +/* harmony import */ var _fromPromise__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(351); +/* harmony import */ var _fromIterable__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(352); +/* harmony import */ var _fromObservable__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(353); +/* harmony import */ var _util_subscribeTo__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(340); /** PURE_IMPORTS_START _Observable,_util_isPromise,_util_isArrayLike,_util_isInteropObservable,_util_isIterable,_fromArray,_fromPromise,_fromIterable,_fromObservable,_util_subscribeTo PURE_IMPORTS_END */ @@ -29946,13 +37364,13 @@ function from(input, scheduler) { /***/ }), -/* 277 */ +/* 349 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isInteropObservable", function() { return isInteropObservable; }); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(219); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(291); /** PURE_IMPORTS_START _symbol_observable PURE_IMPORTS_END */ function isInteropObservable(input) { @@ -29962,13 +37380,13 @@ function isInteropObservable(input) { /***/ }), -/* 278 */ +/* 350 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isIterable", function() { return isIterable; }); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(271); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(343); /** PURE_IMPORTS_START _symbol_iterator PURE_IMPORTS_END */ function isIterable(input) { @@ -29978,15 +37396,15 @@ function isIterable(input) { /***/ }), -/* 279 */ +/* 351 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromPromise", function() { return fromPromise; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); -/* harmony import */ var _util_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(269); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); +/* harmony import */ var _util_subscribeToPromise__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(341); /** PURE_IMPORTS_START _Observable,_Subscription,_util_subscribeToPromise PURE_IMPORTS_END */ @@ -30016,16 +37434,16 @@ function fromPromise(input, scheduler) { /***/ }), -/* 280 */ +/* 352 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromIterable", function() { return fromIterable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); -/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(271); -/* harmony import */ var _util_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(270); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); +/* harmony import */ var _symbol_iterator__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(343); +/* harmony import */ var _util_subscribeToIterable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(342); /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_iterator,_util_subscribeToIterable PURE_IMPORTS_END */ @@ -30081,16 +37499,16 @@ function fromIterable(input, scheduler) { /***/ }), -/* 281 */ +/* 353 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromObservable", function() { return fromObservable; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); -/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(219); -/* harmony import */ var _util_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(272); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); +/* harmony import */ var _symbol_observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(291); +/* harmony import */ var _util_subscribeToObservable__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(344); /** PURE_IMPORTS_START _Observable,_Subscription,_symbol_observable,_util_subscribeToObservable PURE_IMPORTS_END */ @@ -30119,13 +37537,13 @@ function fromObservable(input, scheduler) { /***/ }), -/* 282 */ +/* 354 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return concatAll; }); -/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(283); +/* harmony import */ var _mergeAll__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(355); /** PURE_IMPORTS_START _mergeAll PURE_IMPORTS_END */ function concatAll() { @@ -30135,14 +37553,14 @@ function concatAll() { /***/ }), -/* 283 */ +/* 355 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return mergeAll; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(284); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(356); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); /** PURE_IMPORTS_START _mergeMap,_util_identity PURE_IMPORTS_END */ @@ -30156,7 +37574,7 @@ function mergeAll(concurrent) { /***/ }), -/* 284 */ +/* 356 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30164,11 +37582,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeMap", function() { return mergeMap; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapOperator", function() { return MergeMapOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeMapSubscriber", function() { return MergeMapSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(266); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(265); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(276); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(338); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(348); /** PURE_IMPORTS_START tslib,_util_subscribeToResult,_OuterSubscriber,_map,_observable_from PURE_IMPORTS_END */ @@ -30267,15 +37685,15 @@ var MergeMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 285 */ +/* 357 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defer", function() { return defer; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(348); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311); /** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */ @@ -30298,19 +37716,19 @@ function defer(observableFactory) { /***/ }), -/* 286 */ +/* 358 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "forkJoin", function() { return forkJoin; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(265); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(262); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(337); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(334); /** PURE_IMPORTS_START tslib,_Observable,_util_isArray,_empty,_util_subscribeToResult,_OuterSubscriber,_operators_map PURE_IMPORTS_END */ @@ -30388,16 +37806,16 @@ var ForkJoinSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 287 */ +/* 359 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromEvent", function() { return fromEvent; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(285); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(280); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334); /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */ @@ -30464,16 +37882,16 @@ function isEventTarget(sourceObj) { /***/ }), -/* 288 */ +/* 360 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fromEventPattern", function() { return fromEventPattern; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(208); -/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(285); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(280); +/* harmony import */ var _operators_map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334); /** PURE_IMPORTS_START _Observable,_util_isArray,_util_isFunction,_operators_map PURE_IMPORTS_END */ @@ -30509,15 +37927,15 @@ function fromEventPattern(addHandler, removeHandler, resultSelector) { /***/ }), -/* 289 */ +/* 361 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "generate", function() { return generate; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(241); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(313); /** PURE_IMPORTS_START _Observable,_util_identity,_util_isScheduler PURE_IMPORTS_END */ @@ -30646,14 +38064,14 @@ function dispatch(state) { /***/ }), -/* 290 */ +/* 362 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iif", function() { return iif; }); -/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(239); +/* harmony import */ var _defer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(357); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(311); /** PURE_IMPORTS_START _defer,_empty PURE_IMPORTS_END */ @@ -30670,15 +38088,15 @@ function iif(condition, trueResult, falseResult) { /***/ }), -/* 291 */ +/* 363 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "interval", function() { return interval; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(292); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(364); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric PURE_IMPORTS_END */ @@ -30710,13 +38128,13 @@ function dispatch(state) { /***/ }), -/* 292 */ +/* 364 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNumeric", function() { return isNumeric; }); -/* harmony import */ var _isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); +/* harmony import */ var _isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285); /** PURE_IMPORTS_START _isArray PURE_IMPORTS_END */ function isNumeric(val) { @@ -30726,16 +38144,16 @@ function isNumeric(val) { /***/ }), -/* 293 */ +/* 365 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(241); -/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(283); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(242); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(313); +/* harmony import */ var _operators_mergeAll__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(355); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(314); /** PURE_IMPORTS_START _Observable,_util_isScheduler,_operators_mergeAll,_fromArray PURE_IMPORTS_END */ @@ -30767,15 +38185,15 @@ function merge() { /***/ }), -/* 294 */ +/* 366 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NEVER", function() { return NEVER; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "never", function() { return never; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(221); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(293); /** PURE_IMPORTS_START _Observable,_util_noop PURE_IMPORTS_END */ @@ -30787,16 +38205,16 @@ function never() { /***/ }), -/* 295 */ +/* 367 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(348); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311); /** PURE_IMPORTS_START _Observable,_from,_util_isArray,_empty PURE_IMPORTS_END */ @@ -30827,15 +38245,15 @@ function onErrorResumeNext() { /***/ }), -/* 296 */ +/* 368 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pairs", function() { return pairs; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dispatch", function() { return dispatch; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); /** PURE_IMPORTS_START _Observable,_Subscription PURE_IMPORTS_END */ @@ -30878,7 +38296,7 @@ function dispatch(state) { /***/ }), -/* 297 */ +/* 369 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -30886,11 +38304,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceOperator", function() { return RaceOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RaceSubscriber", function() { return RaceSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(213); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(242); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(285); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(314); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_util_isArray,_fromArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -30972,14 +38390,14 @@ var RaceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 298 */ +/* 370 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "range", function() { return range; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dispatch", function() { return dispatch; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); /** PURE_IMPORTS_START _Observable PURE_IMPORTS_END */ function range(start, count, scheduler) { @@ -31030,16 +38448,16 @@ function dispatch(state) { /***/ }), -/* 299 */ +/* 371 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timer", function() { return timer; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(292); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(241); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(364); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(313); /** PURE_IMPORTS_START _Observable,_scheduler_async,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -31084,15 +38502,15 @@ function dispatch(state) { /***/ }), -/* 300 */ +/* 372 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "using", function() { return using; }); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(204); -/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); -/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(276); +/* harmony import */ var _from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(348); +/* harmony import */ var _empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311); /** PURE_IMPORTS_START _Observable,_from,_empty PURE_IMPORTS_END */ @@ -31129,7 +38547,7 @@ function using(resourceFactory, observableFactory) { /***/ }), -/* 301 */ +/* 373 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -31137,13 +38555,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipOperator", function() { return ZipOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ZipSubscriber", function() { return ZipSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(242); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); -/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(271); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _fromArray__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(314); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338); +/* harmony import */ var _internal_symbol_iterator__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(343); /** PURE_IMPORTS_START tslib,_fromArray,_util_isArray,_Subscriber,_OuterSubscriber,_util_subscribeToResult,_.._internal_symbol_iterator PURE_IMPORTS_END */ @@ -31363,320 +38781,320 @@ var ZipBufferIterator = /*@__PURE__*/ (function (_super) { /***/ }), -/* 302 */ +/* 374 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(303); +/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(375); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__["audit"]; }); -/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(304); +/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(376); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__["auditTime"]; }); -/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(305); +/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(377); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__["buffer"]; }); -/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(306); +/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(378); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__["bufferCount"]; }); -/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(307); +/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(379); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__["bufferTime"]; }); -/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(308); +/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(380); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__["bufferToggle"]; }); -/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(309); +/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(381); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__["bufferWhen"]; }); -/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(310); +/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(382); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__["catchError"]; }); -/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(311); +/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(383); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__["combineAll"]; }); -/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(312); +/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(384); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__["combineLatest"]; }); -/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(313); +/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(385); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__["concat"]; }); -/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(282); +/* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(354); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__["concatAll"]; }); -/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(314); +/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(386); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__["concatMap"]; }); -/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(315); +/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(387); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__["concatMapTo"]; }); -/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(316); +/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(388); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "count", function() { return _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__["count"]; }); -/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(317); +/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(389); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__["debounce"]; }); -/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(318); +/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(390); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__["debounceTime"]; }); -/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(319); +/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(391); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__["defaultIfEmpty"]; }); -/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(320); +/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(392); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__["delay"]; }); -/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(322); +/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(394); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__["delayWhen"]; }); -/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(323); +/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(395); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__["dematerialize"]; }); -/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(324); +/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(396); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__["distinct"]; }); -/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(325); +/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(397); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__["distinctUntilChanged"]; }); -/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(326); +/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(398); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__["distinctUntilKeyChanged"]; }); -/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(327); +/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(399); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__["elementAt"]; }); -/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(332); +/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(404); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__["endWith"]; }); -/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(333); +/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(405); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "every", function() { return _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__["every"]; }); -/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(334); +/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(406); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__["exhaust"]; }); -/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(335); +/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(407); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__["exhaustMap"]; }); -/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(336); +/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(408); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__["expand"]; }); -/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(328); +/* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(400); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__["filter"]; }); -/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(337); +/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(409); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__["finalize"]; }); -/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(338); +/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(410); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "find", function() { return _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__["find"]; }); -/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(339); +/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(411); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__["findIndex"]; }); -/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(340); +/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(412); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "first", function() { return _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__["first"]; }); -/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(227); +/* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(299); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__["groupBy"]; }); -/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(341); +/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(413); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__["ignoreElements"]; }); -/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(342); +/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(414); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__["isEmpty"]; }); -/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(343); +/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(415); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "last", function() { return _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__["last"]; }); -/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(262); +/* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(334); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "map", function() { return _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__["map"]; }); -/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(345); +/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(417); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__["mapTo"]; }); -/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(346); +/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(418); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__["materialize"]; }); -/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(347); +/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(419); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "max", function() { return _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__["max"]; }); -/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(350); +/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(422); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__["merge"]; }); -/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(283); +/* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(355); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeAll", function() { return _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__["mergeAll"]; }); -/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(284); +/* harmony import */ var _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(356); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["mergeMap"]; }); -/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(351); +/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(423); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__["mergeMapTo"]; }); -/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(352); +/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(424); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__["mergeScan"]; }); -/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(353); +/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(425); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "min", function() { return _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__["min"]; }); -/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(354); +/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(426); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__["multicast"]; }); -/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(237); +/* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(309); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observeOn", function() { return _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__["observeOn"]; }); -/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(355); +/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(427); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(356); +/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(428); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__["pairwise"]; }); -/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(357); +/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(429); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__["partition"]; }); -/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(359); +/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(431); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__["pluck"]; }); -/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(360); +/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(432); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__["publish"]; }); -/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(361); +/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(433); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__["publishBehavior"]; }); -/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(362); +/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(434); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__["publishLast"]; }); -/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(363); +/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(435); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__["publishReplay"]; }); -/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(364); +/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(436); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__["race"]; }); -/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(348); +/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(420); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__["reduce"]; }); -/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(365); +/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(437); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__["repeat"]; }); -/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(366); +/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(438); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__["repeatWhen"]; }); -/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(367); +/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(439); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__["retry"]; }); -/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(368); +/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(440); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__["retryWhen"]; }); -/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(226); +/* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(298); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__["refCount"]; }); -/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(369); +/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(441); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__["sample"]; }); -/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(370); +/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(442); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__["sampleTime"]; }); -/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(349); +/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(421); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__["scan"]; }); -/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(371); +/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(443); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__["sequenceEqual"]; }); -/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(372); +/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(444); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "share", function() { return _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__["share"]; }); -/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(373); +/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(445); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__["shareReplay"]; }); -/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(374); +/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(446); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "single", function() { return _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__["single"]; }); -/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(375); +/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(447); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__["skip"]; }); -/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(376); +/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(448); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__["skipLast"]; }); -/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(377); +/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(449); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__["skipUntil"]; }); -/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(378); +/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(450); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__["skipWhile"]; }); -/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(379); +/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(451); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__["startWith"]; }); -/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(380); +/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(452); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__["subscribeOn"]; }); -/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(382); +/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(454); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__["switchAll"]; }); -/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(383); +/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(455); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__["switchMap"]; }); -/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(384); +/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(456); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__["switchMapTo"]; }); -/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(331); +/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(403); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "take", function() { return _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__["take"]; }); -/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(344); +/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(416); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__["takeLast"]; }); -/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(385); +/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(457); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__["takeUntil"]; }); -/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(386); +/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(458); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__["takeWhile"]; }); -/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(330); +/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(402); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__["tap"]; }); -/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(387); +/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(459); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__["throttle"]; }); -/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(388); +/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(460); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__["throttleTime"]; }); -/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(329); +/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(401); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__["throwIfEmpty"]; }); -/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(389); +/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(461); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__["timeInterval"]; }); -/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(390); +/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(462); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__["timeout"]; }); -/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(391); +/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(463); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__["timeoutWith"]; }); -/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(392); +/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(464); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__["timestamp"]; }); -/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(393); +/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(465); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__["toArray"]; }); -/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(394); +/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(466); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "window", function() { return _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__["window"]; }); -/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(395); +/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(467); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__["windowCount"]; }); -/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(396); +/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(468); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__["windowTime"]; }); -/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(397); +/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(469); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__["windowToggle"]; }); -/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(398); +/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(470); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__["windowWhen"]; }); -/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(399); +/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(471); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__["withLatestFrom"]; }); -/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(400); +/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(472); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__["zip"]; }); -/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(401); +/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(473); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__["zipAll"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -31788,17 +39206,17 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 303 */ +/* 375 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return audit; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(216); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(288); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -31871,15 +39289,15 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 304 */ +/* 376 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return auditTime; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); -/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(303); -/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(299); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(323); +/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(375); +/* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(371); /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */ @@ -31894,15 +39312,15 @@ function auditTime(duration, scheduler) { /***/ }), -/* 305 */ +/* 377 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return buffer; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -31943,14 +39361,14 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 306 */ +/* 378 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return bufferCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -32044,16 +39462,16 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 307 */ +/* 379 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return bufferTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(206); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(241); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(278); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(313); /** PURE_IMPORTS_START tslib,_scheduler_async,_Subscriber,_util_isScheduler PURE_IMPORTS_END */ @@ -32205,16 +39623,16 @@ function dispatchBufferClose(arg) { /***/ }), -/* 308 */ +/* 380 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return bufferToggle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337); /** PURE_IMPORTS_START tslib,_Subscription,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */ @@ -32325,18 +39743,18 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 309 */ +/* 381 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return bufferWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(212); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(284); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_Subscription,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -32422,15 +39840,15 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 310 */ +/* 382 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return catchError; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -32479,13 +39897,13 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 311 */ +/* 383 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return combineAll; }); -/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(264); +/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(336); /** PURE_IMPORTS_START _observable_combineLatest PURE_IMPORTS_END */ function combineAll(project) { @@ -32495,15 +39913,15 @@ function combineAll(project) { /***/ }), -/* 312 */ +/* 384 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return combineLatest; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); -/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(264); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285); +/* harmony import */ var _observable_combineLatest__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(336); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(348); /** PURE_IMPORTS_START _util_isArray,_observable_combineLatest,_observable_from PURE_IMPORTS_END */ @@ -32527,13 +39945,13 @@ function combineLatest() { /***/ }), -/* 313 */ +/* 385 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return concat; }); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(275); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(347); /** PURE_IMPORTS_START _observable_concat PURE_IMPORTS_END */ function concat() { @@ -32547,13 +39965,13 @@ function concat() { /***/ }), -/* 314 */ +/* 386 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return concatMap; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(284); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(356); /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */ function concatMap(project, resultSelector) { @@ -32563,13 +39981,13 @@ function concatMap(project, resultSelector) { /***/ }), -/* 315 */ +/* 387 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return concatMapTo; }); -/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(314); +/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(386); /** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */ function concatMapTo(innerObservable, resultSelector) { @@ -32579,14 +39997,14 @@ function concatMapTo(innerObservable, resultSelector) { /***/ }), -/* 316 */ +/* 388 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "count", function() { return count; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -32644,15 +40062,15 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 317 */ +/* 389 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return debounce; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -32732,15 +40150,15 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 318 */ +/* 390 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return debounceTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */ @@ -32808,14 +40226,14 @@ function dispatchNext(subscriber) { /***/ }), -/* 319 */ +/* 391 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return defaultIfEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -32858,17 +40276,17 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 320 */ +/* 392 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return delay; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(321); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(238); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(393); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(310); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -32962,7 +40380,7 @@ var DelayMessage = /*@__PURE__*/ (function () { /***/ }), -/* 321 */ +/* 393 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -32976,17 +40394,17 @@ function isDate(value) { /***/ }), -/* 322 */ +/* 394 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return delayWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(204); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(276); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_Subscriber,_Observable,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -33117,14 +40535,14 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 323 */ +/* 395 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return dematerialize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -33155,16 +40573,16 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 324 */ +/* 396 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return distinct; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DistinctSubscriber", function() { return DistinctSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -33233,16 +40651,16 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 325 */ +/* 397 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return distinctUntilChanged; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288); /** PURE_IMPORTS_START tslib,_Subscriber,_util_tryCatch,_util_errorObject PURE_IMPORTS_END */ @@ -33305,13 +40723,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 326 */ +/* 398 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return distinctUntilKeyChanged; }); -/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(325); +/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(397); /** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */ function distinctUntilKeyChanged(key, compare) { @@ -33321,17 +40739,17 @@ function distinctUntilKeyChanged(key, compare) { /***/ }), -/* 327 */ +/* 399 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return elementAt; }); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(258); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(329); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(319); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(331); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(330); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(401); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(391); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(403); /** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */ @@ -33353,14 +40771,14 @@ function elementAt(index, defaultValue) { /***/ }), -/* 328 */ +/* 400 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return filter; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -33407,14 +40825,14 @@ var FilterSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 329 */ +/* 401 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return throwIfEmpty; }); -/* harmony import */ var _tap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(330); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(259); +/* harmony import */ var _tap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(402); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(331); /** PURE_IMPORTS_START _tap,_util_EmptyError PURE_IMPORTS_END */ @@ -33439,16 +40857,16 @@ function defaultErrorFactory() { /***/ }), -/* 330 */ +/* 402 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return tap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(221); -/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(208); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _util_noop__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(293); +/* harmony import */ var _util_isFunction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(280); /** PURE_IMPORTS_START tslib,_Subscriber,_util_noop,_util_isFunction PURE_IMPORTS_END */ @@ -33527,16 +40945,16 @@ var TapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 331 */ +/* 403 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "take", function() { return take; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(330); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */ @@ -33589,17 +41007,17 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 332 */ +/* 404 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return endWith; }); -/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); -/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(244); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(275); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(241); +/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(314); +/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(316); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(347); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(313); /** PURE_IMPORTS_START _observable_fromArray,_observable_scalar,_observable_empty,_observable_concat,_util_isScheduler PURE_IMPORTS_END */ @@ -33635,14 +41053,14 @@ function endWith() { /***/ }), -/* 333 */ +/* 405 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "every", function() { return every; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -33697,15 +41115,15 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 334 */ +/* 406 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return exhaust; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -33754,17 +41172,17 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 335 */ +/* 407 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return exhaustMap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(276); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(348); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */ @@ -33840,7 +41258,7 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 336 */ +/* 408 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -33848,11 +41266,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return expand; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandOperator", function() { return ExpandOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpandSubscriber", function() { return ExpandSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(216); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(288); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -33956,15 +41374,15 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 337 */ +/* 409 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return finalize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284); /** PURE_IMPORTS_START tslib,_Subscriber,_Subscription PURE_IMPORTS_END */ @@ -33994,7 +41412,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 338 */ +/* 410 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -34002,8 +41420,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "find", function() { return find; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FindValueOperator", function() { return FindValueOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FindValueSubscriber", function() { return FindValueSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34065,13 +41483,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 339 */ +/* 411 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return findIndex; }); -/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(338); +/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(410); /** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */ function findIndex(predicate, thisArg) { @@ -34081,18 +41499,18 @@ function findIndex(predicate, thisArg) { /***/ }), -/* 340 */ +/* 412 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "first", function() { return first; }); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(259); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(331); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(319); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(329); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(256); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(331); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(403); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(391); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(401); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(328); /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -34108,14 +41526,14 @@ function first(predicate, defaultValue) { /***/ }), -/* 341 */ +/* 413 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return ignoreElements; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34145,14 +41563,14 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 342 */ +/* 414 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return isEmpty; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34189,18 +41607,18 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 343 */ +/* 415 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "last", function() { return last; }); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(259); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(344); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(329); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(319); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(256); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(331); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(416); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(401); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(391); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(328); /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -34216,16 +41634,16 @@ function last(predicate, defaultValue) { /***/ }), -/* 344 */ +/* 416 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return takeLast; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(239); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(330); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(311); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError,_observable_empty PURE_IMPORTS_END */ @@ -34293,14 +41711,14 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 345 */ +/* 417 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return mapTo; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34332,15 +41750,15 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 346 */ +/* 418 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return materialize; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(238); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(310); /** PURE_IMPORTS_START tslib,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -34382,13 +41800,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 347 */ +/* 419 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "max", function() { return max; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(348); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(420); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function max(comparer) { @@ -34401,16 +41819,16 @@ function max(comparer) { /***/ }), -/* 348 */ +/* 420 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return reduce; }); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(349); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(344); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(319); -/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(220); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(421); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(416); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(391); +/* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(292); /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */ @@ -34432,14 +41850,14 @@ function reduce(accumulator, seed) { /***/ }), -/* 349 */ +/* 421 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return scan; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34514,13 +41932,13 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 350 */ +/* 422 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return merge; }); -/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(293); +/* harmony import */ var _observable_merge__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(365); /** PURE_IMPORTS_START _observable_merge PURE_IMPORTS_END */ function merge() { @@ -34534,13 +41952,13 @@ function merge() { /***/ }), -/* 351 */ +/* 423 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return mergeMapTo; }); -/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(284); +/* harmony import */ var _mergeMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(356); /** PURE_IMPORTS_START _mergeMap PURE_IMPORTS_END */ function mergeMapTo(innerObservable, resultSelector, concurrent) { @@ -34559,7 +41977,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) { /***/ }), -/* 352 */ +/* 424 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -34567,11 +41985,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return mergeScan; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanOperator", function() { return MergeScanOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MergeScanSubscriber", function() { return MergeScanSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(216); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(266); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(288); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(338); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337); /** PURE_IMPORTS_START tslib,_util_tryCatch,_util_errorObject,_util_subscribeToResult,_OuterSubscriber PURE_IMPORTS_END */ @@ -34666,13 +42084,13 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 353 */ +/* 425 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "min", function() { return min; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(348); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(420); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function min(comparer) { @@ -34685,14 +42103,14 @@ function min(comparer) { /***/ }), -/* 354 */ +/* 426 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return multicast; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MulticastOperator", function() { return MulticastOperator; }); -/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(222); +/* harmony import */ var _observable_ConnectableObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(294); /** PURE_IMPORTS_START _observable_ConnectableObservable PURE_IMPORTS_END */ function multicast(subjectOrSubjectFactory, selector) { @@ -34734,18 +42152,18 @@ var MulticastOperator = /*@__PURE__*/ (function () { /***/ }), -/* 355 */ +/* 427 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return onErrorResumeNext; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNextStatic", function() { return onErrorResumeNextStatic; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(213); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(348); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_observable_from,_util_isArray,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -34818,14 +42236,14 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 356 */ +/* 428 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return pairwise; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -34862,14 +42280,14 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 357 */ +/* 429 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return partition; }); -/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(358); -/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); +/* harmony import */ var _util_not__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(430); +/* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(400); /** PURE_IMPORTS_START _util_not,_filter PURE_IMPORTS_END */ @@ -34885,7 +42303,7 @@ function partition(predicate, thisArg) { /***/ }), -/* 358 */ +/* 430 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -34904,13 +42322,13 @@ function not(pred, thisArg) { /***/ }), -/* 359 */ +/* 431 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return pluck; }); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(262); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(334); /** PURE_IMPORTS_START _map PURE_IMPORTS_END */ function pluck() { @@ -34944,14 +42362,14 @@ function plucker(props, length) { /***/ }), -/* 360 */ +/* 432 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return publish; }); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(223); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(354); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(295); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426); /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */ @@ -34964,14 +42382,14 @@ function publish(selector) { /***/ }), -/* 361 */ +/* 433 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return publishBehavior; }); -/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(228); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(354); +/* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(300); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426); /** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */ @@ -34982,14 +42400,14 @@ function publishBehavior(value) { /***/ }), -/* 362 */ +/* 434 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return publishLast; }); -/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(246); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(354); +/* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(318); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426); /** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */ @@ -35000,14 +42418,14 @@ function publishLast() { /***/ }), -/* 363 */ +/* 435 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return publishReplay; }); -/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(229); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(354); +/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(301); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426); /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */ @@ -35023,14 +42441,14 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) { /***/ }), -/* 364 */ +/* 436 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "race", function() { return race; }); -/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(213); -/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(297); +/* harmony import */ var _util_isArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(285); +/* harmony import */ var _observable_race__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(369); /** PURE_IMPORTS_START _util_isArray,_observable_race PURE_IMPORTS_END */ @@ -35050,15 +42468,15 @@ function race() { /***/ }), -/* 365 */ +/* 437 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return repeat; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311); /** PURE_IMPORTS_START tslib,_Subscriber,_observable_empty PURE_IMPORTS_END */ @@ -35115,18 +42533,18 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 366 */ +/* 438 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return repeatWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -35211,14 +42629,14 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 367 */ +/* 439 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return retry; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -35264,18 +42682,18 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 368 */ +/* 440 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return retryWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -35353,15 +42771,15 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 369 */ +/* 441 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return sample; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -35410,15 +42828,15 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 370 */ +/* 442 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return sampleTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async PURE_IMPORTS_END */ @@ -35470,7 +42888,7 @@ function dispatchNotification(state) { /***/ }), -/* 371 */ +/* 443 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -35478,10 +42896,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return sequenceEqual; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualOperator", function() { return SequenceEqualOperator; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SequenceEqualSubscriber", function() { return SequenceEqualSubscriber; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288); /** PURE_IMPORTS_START tslib,_Subscriber,_util_tryCatch,_util_errorObject PURE_IMPORTS_END */ @@ -35589,15 +43007,15 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 372 */ +/* 444 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "share", function() { return share; }); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(354); -/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(226); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(223); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(426); +/* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(298); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(295); /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */ @@ -35612,13 +43030,13 @@ function share() { /***/ }), -/* 373 */ +/* 445 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return shareReplay; }); -/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(229); +/* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(301); /** PURE_IMPORTS_START _ReplaySubject PURE_IMPORTS_END */ function shareReplay(bufferSize, windowTime, scheduler) { @@ -35661,15 +43079,15 @@ function shareReplayOperator(bufferSize, windowTime, scheduler) { /***/ }), -/* 374 */ +/* 446 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "single", function() { return single; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(259); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(331); /** PURE_IMPORTS_START tslib,_Subscriber,_util_EmptyError PURE_IMPORTS_END */ @@ -35741,14 +43159,14 @@ var SingleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 375 */ +/* 447 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return skip; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -35783,15 +43201,15 @@ var SkipSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 376 */ +/* 448 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return skipLast; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(258); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(330); /** PURE_IMPORTS_START tslib,_Subscriber,_util_ArgumentOutOfRangeError PURE_IMPORTS_END */ @@ -35845,15 +43263,15 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 377 */ +/* 449 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return skipUntil; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -35897,14 +43315,14 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 378 */ +/* 450 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return skipWhile; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -35953,17 +43371,17 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 379 */ +/* 451 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return startWith; }); -/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(242); -/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(244); -/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(239); -/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(275); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(241); +/* harmony import */ var _observable_fromArray__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(314); +/* harmony import */ var _observable_scalar__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(316); +/* harmony import */ var _observable_empty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(311); +/* harmony import */ var _observable_concat__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(347); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(313); /** PURE_IMPORTS_START _observable_fromArray,_observable_scalar,_observable_empty,_observable_concat,_util_isScheduler PURE_IMPORTS_END */ @@ -35999,13 +43417,13 @@ function startWith() { /***/ }), -/* 380 */ +/* 452 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return subscribeOn; }); -/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(381); +/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(453); /** PURE_IMPORTS_START _observable_SubscribeOnObservable PURE_IMPORTS_END */ function subscribeOn(scheduler, delay) { @@ -36030,16 +43448,16 @@ var SubscribeOnOperator = /*@__PURE__*/ (function () { /***/ }), -/* 381 */ +/* 453 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SubscribeOnObservable", function() { return SubscribeOnObservable; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(204); -/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(247); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(292); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(276); +/* harmony import */ var _scheduler_asap__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(319); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(364); /** PURE_IMPORTS_START tslib,_Observable,_scheduler_asap,_util_isNumeric PURE_IMPORTS_END */ @@ -36094,14 +43512,14 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) { /***/ }), -/* 382 */ +/* 454 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return switchAll; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(383); -/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(256); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(455); +/* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(328); /** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */ @@ -36112,17 +43530,17 @@ function switchAll() { /***/ }), -/* 383 */ +/* 455 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return switchMap; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); -/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(276); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334); +/* harmony import */ var _observable_from__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(348); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult,_map,_observable_from PURE_IMPORTS_END */ @@ -36196,13 +43614,13 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 384 */ +/* 456 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return switchMapTo; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(383); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(455); /** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */ function switchMapTo(innerObservable, resultSelector) { @@ -36212,15 +43630,15 @@ function switchMapTo(innerObservable, resultSelector) { /***/ }), -/* 385 */ +/* 457 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return takeUntil; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -36259,14 +43677,14 @@ var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 386 */ +/* 458 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return takeWhile; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); /** PURE_IMPORTS_START tslib,_Subscriber PURE_IMPORTS_END */ @@ -36317,16 +43735,16 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 387 */ +/* 459 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "defaultThrottleConfig", function() { return defaultThrottleConfig; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return throttle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -36421,16 +43839,16 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 388 */ +/* 460 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return throttleTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); -/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(387); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323); +/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(459); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */ @@ -36515,17 +43933,17 @@ function dispatchNext(arg) { /***/ }), -/* 389 */ +/* 461 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return timeInterval; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeInterval", function() { return TimeInterval; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(349); -/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(285); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(262); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(323); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(421); +/* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(357); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(334); /** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */ @@ -36559,16 +43977,16 @@ var TimeInterval = /*@__PURE__*/ (function () { /***/ }), -/* 390 */ +/* 462 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return timeout; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); -/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(260); -/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(391); -/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(245); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(323); +/* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(332); +/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(463); +/* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(317); /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */ @@ -36584,17 +44002,17 @@ function timeout(due, scheduler) { /***/ }), -/* 391 */ +/* 463 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return timeoutWith; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(251); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(321); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(323); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(393); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -36666,15 +44084,15 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 392 */ +/* 464 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return timestamp; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Timestamp", function() { return Timestamp; }); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(251); -/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(262); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(323); +/* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(334); /** PURE_IMPORTS_START _scheduler_async,_map PURE_IMPORTS_END */ @@ -36696,13 +44114,13 @@ var Timestamp = /*@__PURE__*/ (function () { /***/ }), -/* 393 */ +/* 465 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return toArray; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(348); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(420); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function toArrayReducer(arr, item, index) { @@ -36719,16 +44137,16 @@ function toArray() { /***/ }), -/* 394 */ +/* 466 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "window", function() { return window; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_Subject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -36799,15 +44217,15 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 395 */ +/* 467 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return windowCount; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(206); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(223); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(278); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(295); /** PURE_IMPORTS_START tslib,_Subscriber,_Subject PURE_IMPORTS_END */ @@ -36889,18 +44307,18 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 396 */ +/* 468 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return windowTime; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(251); -/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(206); -/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(292); -/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(241); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(323); +/* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(278); +/* harmony import */ var _util_isNumeric__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(364); +/* harmony import */ var _util_isScheduler__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(313); /** PURE_IMPORTS_START tslib,_Subject,_scheduler_async,_Subscriber,_util_isNumeric,_util_isScheduler PURE_IMPORTS_END */ @@ -37059,19 +44477,19 @@ function dispatchWindowClose(state) { /***/ }), -/* 397 */ +/* 469 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return windowToggle; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(212); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(216); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _Subscription__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(284); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(288); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_Subject,_Subscription,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -37205,18 +44623,18 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 398 */ +/* 470 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return windowWhen; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(223); -/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(215); -/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(216); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(295); +/* harmony import */ var _util_tryCatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(287); +/* harmony import */ var _util_errorObject__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(288); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_Subject,_util_tryCatch,_util_errorObject,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -37304,15 +44722,15 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 399 */ +/* 471 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return withLatestFrom; }); -/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(207); -/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(265); -/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(266); +/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(279); +/* harmony import */ var _OuterSubscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(337); +/* harmony import */ var _util_subscribeToResult__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(338); /** PURE_IMPORTS_START tslib,_OuterSubscriber,_util_subscribeToResult PURE_IMPORTS_END */ @@ -37399,13 +44817,13 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 400 */ +/* 472 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return zip; }); -/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(301); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(373); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zip() { @@ -37421,13 +44839,13 @@ function zip() { /***/ }), -/* 401 */ +/* 473 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return zipAll; }); -/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(301); +/* harmony import */ var _observable_zip__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(373); /** PURE_IMPORTS_START _observable_zip PURE_IMPORTS_END */ function zipAll(project) { @@ -37437,7 +44855,7 @@ function zipAll(project) { /***/ }), -/* 402 */ +/* 474 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -37445,15 +44863,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(403); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(259); /* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(404); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(475); /* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(172); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(53); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(36); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(411); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(482); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -37531,47 +44949,13 @@ function toArray(value) { } /***/ }), -/* 403 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -module.exports = (str, count, opts) => { - // Support older versions: use the third parameter as options.indent - // TODO: Remove the workaround in the next major version - const options = typeof opts === 'object' ? Object.assign({indent: ' '}, opts) : {indent: opts || ' '}; - count = count === undefined ? 1 : count; - - if (typeof str !== 'string') { - throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof str}\``); - } - - if (typeof count !== 'number') { - throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof count}\``); - } - - if (typeof options.indent !== 'string') { - throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof options.indent}\``); - } - - if (count === 0) { - return str; - } - - const regex = options.includeEmptyLines ? /^/mg : /^(?!\s*$)/mg; - return str.replace(regex, options.indent.repeat(count)); -} -; - - -/***/ }), -/* 404 */ +/* 475 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringWidth = __webpack_require__(405); -const stripAnsi = __webpack_require__(409); +const stringWidth = __webpack_require__(476); +const stripAnsi = __webpack_require__(480); const ESCAPES = new Set([ '\u001B', @@ -37765,13 +45149,13 @@ module.exports = (str, cols, opts) => { /***/ }), -/* 405 */ +/* 476 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stripAnsi = __webpack_require__(406); -const isFullwidthCodePoint = __webpack_require__(408); +const stripAnsi = __webpack_require__(477); +const isFullwidthCodePoint = __webpack_require__(479); module.exports = str => { if (typeof str !== 'string' || str.length === 0) { @@ -37808,18 +45192,18 @@ module.exports = str => { /***/ }), -/* 406 */ +/* 477 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(407); +const ansiRegex = __webpack_require__(478); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 407 */ +/* 478 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -37836,7 +45220,7 @@ module.exports = () => { /***/ }), -/* 408 */ +/* 479 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -37889,18 +45273,18 @@ module.exports = x => { /***/ }), -/* 409 */ +/* 480 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(410); +const ansiRegex = __webpack_require__(481); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 410 */ +/* 481 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -37917,7 +45301,7 @@ module.exports = () => { /***/ }), -/* 411 */ +/* 482 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -38070,15 +45454,15 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 412 */ +/* 483 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(413); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(484); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(620); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(691); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -38103,13 +45487,13 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 413 */ +/* 484 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(414); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(485); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(174); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); @@ -38249,17 +45633,17 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 414 */ +/* 485 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const EventEmitter = __webpack_require__(46); const path = __webpack_require__(16); -const arrify = __webpack_require__(415); -const globby = __webpack_require__(416); -const cpFile = __webpack_require__(610); -const CpyError = __webpack_require__(618); +const arrify = __webpack_require__(486); +const globby = __webpack_require__(487); +const cpFile = __webpack_require__(681); +const CpyError = __webpack_require__(689); const preprocessSrcPath = (srcPath, options) => options.cwd ? path.resolve(options.cwd, srcPath) : srcPath; @@ -38364,7 +45748,7 @@ module.exports.default = cpy; /***/ }), -/* 415 */ +/* 486 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38379,17 +45763,17 @@ module.exports = function (val) { /***/ }), -/* 416 */ +/* 487 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(178); +const arrayUnion = __webpack_require__(488); const glob = __webpack_require__(37); -const fastGlob = __webpack_require__(417); -const dirGlob = __webpack_require__(603); -const gitignore = __webpack_require__(606); +const fastGlob = __webpack_require__(490); +const dirGlob = __webpack_require__(674); +const gitignore = __webpack_require__(677); const DEFAULT_FILTER = () => false; @@ -38534,10 +45918,92 @@ module.exports.gitignore = gitignore; /***/ }), -/* 417 */ +/* 488 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(418); +"use strict"; + +var arrayUniq = __webpack_require__(489); + +module.exports = function () { + return arrayUniq([].concat.apply([], arguments)); +}; + + +/***/ }), +/* 489 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +// there's 3 implementations written in increasing order of efficiency + +// 1 - no Set type is defined +function uniqNoSet(arr) { + var ret = []; + + for (var i = 0; i < arr.length; i++) { + if (ret.indexOf(arr[i]) === -1) { + ret.push(arr[i]); + } + } + + return ret; +} + +// 2 - a simple Set type is defined +function uniqSet(arr) { + var seen = new Set(); + return arr.filter(function (el) { + if (!seen.has(el)) { + seen.add(el); + return true; + } + + return false; + }); +} + +// 3 - a standard Set type is defined and it has a forEach method +function uniqSetWithForEach(arr) { + var ret = []; + + (new Set(arr)).forEach(function (el) { + ret.push(el); + }); + + return ret; +} + +// V8 currently has a broken implementation +// https://github.com/joyent/node/issues/8449 +function doesForEachActuallyWork() { + var ret = false; + + (new Set([true])).forEach(function (el) { + ret = el; + }); + + return ret === true; +} + +if ('Set' in global) { + if (typeof Set.prototype.forEach === 'function' && doesForEachActuallyWork()) { + module.exports = uniqSetWithForEach; + } else { + module.exports = uniqSet; + } +} else { + module.exports = uniqNoSet; +} + + +/***/ }), +/* 490 */ +/***/ (function(module, exports, __webpack_require__) { + +const pkg = __webpack_require__(491); module.exports = pkg.async; module.exports.default = pkg.async; @@ -38550,19 +46016,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 418 */ +/* 491 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(419); -var taskManager = __webpack_require__(420); -var reader_async_1 = __webpack_require__(573); -var reader_stream_1 = __webpack_require__(597); -var reader_sync_1 = __webpack_require__(598); -var arrayUtils = __webpack_require__(600); -var streamUtils = __webpack_require__(601); +var optionsManager = __webpack_require__(492); +var taskManager = __webpack_require__(493); +var reader_async_1 = __webpack_require__(645); +var reader_stream_1 = __webpack_require__(669); +var reader_sync_1 = __webpack_require__(670); +var arrayUtils = __webpack_require__(672); +var streamUtils = __webpack_require__(673); /** * Synchronous API. */ @@ -38628,7 +46094,7 @@ function isString(source) { /***/ }), -/* 419 */ +/* 492 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -38666,13 +46132,13 @@ exports.prepare = prepare; /***/ }), -/* 420 */ +/* 493 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(421); +var patternUtils = __webpack_require__(494); /** * Generate tasks based on parent directory of each pattern. */ @@ -38763,16 +46229,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 421 */ +/* 494 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var globParent = __webpack_require__(422); -var isGlob = __webpack_require__(426); -var micromatch = __webpack_require__(427); +var globParent = __webpack_require__(495); +var isGlob = __webpack_require__(498); +var micromatch = __webpack_require__(499); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -38918,15 +46384,15 @@ exports.matchAny = matchAny; /***/ }), -/* 422 */ +/* 495 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(16); -var isglob = __webpack_require__(423); -var pathDirname = __webpack_require__(425); +var isglob = __webpack_require__(496); +var pathDirname = __webpack_require__(497); var isWin32 = __webpack_require__(11).platform() === 'win32'; module.exports = function globParent(str) { @@ -38949,7 +46415,7 @@ module.exports = function globParent(str) { /***/ }), -/* 423 */ +/* 496 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -38959,7 +46425,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(424); +var isExtglob = __webpack_require__(188); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -38980,33 +46446,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 424 */ -/***/ (function(module, exports) { - -/*! - * is-extglob - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License. - */ - -module.exports = function isExtglob(str) { - if (typeof str !== 'string' || str === '') { - return false; - } - - var match; - while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { - if (match[2]) return true; - str = str.slice(match.index + match[0].length); - } - - return false; -}; - - -/***/ }), -/* 425 */ +/* 497 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39156,7 +46596,7 @@ module.exports.win32 = win32; /***/ }), -/* 426 */ +/* 498 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -39166,7 +46606,7 @@ module.exports.win32 = win32; * Released under the MIT License. */ -var isExtglob = __webpack_require__(424); +var isExtglob = __webpack_require__(188); var chars = { '{': '}', '(': ')', '[': ']'}; module.exports = function isGlob(str, options) { @@ -39208,7 +46648,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 427 */ +/* 499 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -39219,18 +46659,18 @@ module.exports = function isGlob(str, options) { */ var util = __webpack_require__(29); -var braces = __webpack_require__(428); -var toRegex = __webpack_require__(531); -var extend = __webpack_require__(539); +var braces = __webpack_require__(500); +var toRegex = __webpack_require__(603); +var extend = __webpack_require__(611); /** * Local dependencies */ -var compilers = __webpack_require__(542); -var parsers = __webpack_require__(569); -var cache = __webpack_require__(570); -var utils = __webpack_require__(571); +var compilers = __webpack_require__(614); +var parsers = __webpack_require__(641); +var cache = __webpack_require__(642); +var utils = __webpack_require__(643); var MAX_LENGTH = 1024 * 64; /** @@ -40092,7 +47532,7 @@ module.exports = micromatch; /***/ }), -/* 428 */ +/* 500 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40102,18 +47542,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(429); -var unique = __webpack_require__(441); -var extend = __webpack_require__(438); +var toRegex = __webpack_require__(501); +var unique = __webpack_require__(513); +var extend = __webpack_require__(510); /** * Local dependencies */ -var compilers = __webpack_require__(442); -var parsers = __webpack_require__(457); -var Braces = __webpack_require__(467); -var utils = __webpack_require__(443); +var compilers = __webpack_require__(514); +var parsers = __webpack_require__(529); +var Braces = __webpack_require__(539); +var utils = __webpack_require__(515); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -40417,15 +47857,15 @@ module.exports = braces; /***/ }), -/* 429 */ +/* 501 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(430); -var extend = __webpack_require__(438); -var not = __webpack_require__(440); +var define = __webpack_require__(502); +var extend = __webpack_require__(510); +var not = __webpack_require__(512); var MAX_LENGTH = 1024 * 64; /** @@ -40572,7 +48012,7 @@ module.exports.makeRe = makeRe; /***/ }), -/* 430 */ +/* 502 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40585,7 +48025,7 @@ module.exports.makeRe = makeRe; -var isDescriptor = __webpack_require__(431); +var isDescriptor = __webpack_require__(503); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -40610,7 +48050,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 431 */ +/* 503 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40623,9 +48063,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(432); -var isAccessor = __webpack_require__(433); -var isData = __webpack_require__(436); +var typeOf = __webpack_require__(504); +var isAccessor = __webpack_require__(505); +var isData = __webpack_require__(508); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -40639,7 +48079,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 432 */ +/* 504 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -40792,7 +48232,7 @@ function isBuffer(val) { /***/ }), -/* 433 */ +/* 505 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -40805,7 +48245,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(434); +var typeOf = __webpack_require__(506); // accessor descriptor properties var accessor = { @@ -40868,10 +48308,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 434 */ +/* 506 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(435); +var isBuffer = __webpack_require__(507); var toString = Object.prototype.toString; /** @@ -40990,7 +48430,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 435 */ +/* 507 */ /***/ (function(module, exports) { /*! @@ -41017,7 +48457,7 @@ function isSlowBuffer (obj) { /***/ }), -/* 436 */ +/* 508 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41030,7 +48470,7 @@ function isSlowBuffer (obj) { -var typeOf = __webpack_require__(437); +var typeOf = __webpack_require__(509); // data descriptor properties var data = { @@ -41079,10 +48519,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 437 */ +/* 509 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(435); +var isBuffer = __webpack_require__(507); var toString = Object.prototype.toString; /** @@ -41201,13 +48641,13 @@ module.exports = function kindOf(val) { /***/ }), -/* 438 */ +/* 510 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(439); +var isObject = __webpack_require__(511); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -41241,7 +48681,7 @@ function hasOwn(obj, key) { /***/ }), -/* 439 */ +/* 511 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41261,13 +48701,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 440 */ +/* 512 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(438); +var extend = __webpack_require__(510); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -41334,7 +48774,7 @@ module.exports = toRegex; /***/ }), -/* 441 */ +/* 513 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -41384,13 +48824,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 442 */ +/* 514 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(443); +var utils = __webpack_require__(515); module.exports = function(braces, options) { braces.compiler @@ -41673,25 +49113,25 @@ function hasQueue(node) { /***/ }), -/* 443 */ +/* 515 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(444); +var splitString = __webpack_require__(516); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(438); -utils.flatten = __webpack_require__(450); -utils.isObject = __webpack_require__(448); -utils.fillRange = __webpack_require__(451); -utils.repeat = __webpack_require__(456); -utils.unique = __webpack_require__(441); +utils.extend = __webpack_require__(510); +utils.flatten = __webpack_require__(522); +utils.isObject = __webpack_require__(520); +utils.fillRange = __webpack_require__(523); +utils.repeat = __webpack_require__(528); +utils.unique = __webpack_require__(513); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -42023,7 +49463,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 444 */ +/* 516 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42036,7 +49476,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(445); +var extend = __webpack_require__(517); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -42201,14 +49641,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 445 */ +/* 517 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(446); -var assignSymbols = __webpack_require__(449); +var isExtendable = __webpack_require__(518); +var assignSymbols = __webpack_require__(521); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -42268,7 +49708,7 @@ function isEnum(obj, key) { /***/ }), -/* 446 */ +/* 518 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42281,7 +49721,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(447); +var isPlainObject = __webpack_require__(519); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -42289,7 +49729,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 447 */ +/* 519 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42302,7 +49742,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(448); +var isObject = __webpack_require__(520); function isObjectObject(o) { return isObject(o) === true @@ -42333,7 +49773,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 448 */ +/* 520 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42352,7 +49792,7 @@ module.exports = function isObject(val) { /***/ }), -/* 449 */ +/* 521 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42399,7 +49839,7 @@ module.exports = function(receiver, objects) { /***/ }), -/* 450 */ +/* 522 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42428,7 +49868,7 @@ function flat(arr, res) { /***/ }), -/* 451 */ +/* 523 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42442,10 +49882,10 @@ function flat(arr, res) { var util = __webpack_require__(29); -var isNumber = __webpack_require__(452); -var extend = __webpack_require__(438); -var repeat = __webpack_require__(454); -var toRegex = __webpack_require__(455); +var isNumber = __webpack_require__(524); +var extend = __webpack_require__(510); +var repeat = __webpack_require__(526); +var toRegex = __webpack_require__(527); /** * Return a range of numbers or letters. @@ -42643,7 +50083,7 @@ module.exports = fillRange; /***/ }), -/* 452 */ +/* 524 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42656,7 +50096,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(453); +var typeOf = __webpack_require__(525); module.exports = function isNumber(num) { var type = typeOf(num); @@ -42672,10 +50112,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 453 */ +/* 525 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(435); +var isBuffer = __webpack_require__(507); var toString = Object.prototype.toString; /** @@ -42794,7 +50234,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 454 */ +/* 526 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42871,7 +50311,7 @@ function repeat(str, num) { /***/ }), -/* 455 */ +/* 527 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -42884,8 +50324,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(454); -var isNumber = __webpack_require__(452); +var repeat = __webpack_require__(526); +var isNumber = __webpack_require__(524); var cache = {}; function toRegexRange(min, max, options) { @@ -43172,7 +50612,7 @@ module.exports = toRegexRange; /***/ }), -/* 456 */ +/* 528 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -43197,14 +50637,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 457 */ +/* 529 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(458); -var utils = __webpack_require__(443); +var Node = __webpack_require__(530); +var utils = __webpack_require__(515); /** * Braces parsers @@ -43564,15 +51004,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 458 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(448); -var define = __webpack_require__(459); -var utils = __webpack_require__(466); +var isObject = __webpack_require__(520); +var define = __webpack_require__(531); +var utils = __webpack_require__(538); var ownNames; /** @@ -44063,7 +51503,7 @@ exports = module.exports = Node; /***/ }), -/* 459 */ +/* 531 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -44076,7 +51516,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(460); +var isDescriptor = __webpack_require__(532); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -44101,7 +51541,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 460 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -44114,9 +51554,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(461); -var isAccessor = __webpack_require__(462); -var isData = __webpack_require__(464); +var typeOf = __webpack_require__(533); +var isAccessor = __webpack_require__(534); +var isData = __webpack_require__(536); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -44130,7 +51570,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 461 */ +/* 533 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -44265,7 +51705,7 @@ function isBuffer(val) { /***/ }), -/* 462 */ +/* 534 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -44278,7 +51718,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(463); +var typeOf = __webpack_require__(535); // accessor descriptor properties var accessor = { @@ -44341,7 +51781,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 463 */ +/* 535 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -44476,7 +51916,7 @@ function isBuffer(val) { /***/ }), -/* 464 */ +/* 536 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -44489,7 +51929,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(465); +var typeOf = __webpack_require__(537); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -44532,7 +51972,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 465 */ +/* 537 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -44667,13 +52107,13 @@ function isBuffer(val) { /***/ }), -/* 466 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(453); +var typeOf = __webpack_require__(525); var utils = module.exports; /** @@ -45693,17 +53133,17 @@ function assert(val, message) { /***/ }), -/* 467 */ +/* 539 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(438); -var Snapdragon = __webpack_require__(468); -var compilers = __webpack_require__(442); -var parsers = __webpack_require__(457); -var utils = __webpack_require__(443); +var extend = __webpack_require__(510); +var Snapdragon = __webpack_require__(540); +var compilers = __webpack_require__(514); +var parsers = __webpack_require__(529); +var utils = __webpack_require__(515); /** * Customize Snapdragon parser and renderer @@ -45804,17 +53244,17 @@ module.exports = Braces; /***/ }), -/* 468 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(469); -var define = __webpack_require__(430); -var Compiler = __webpack_require__(498); -var Parser = __webpack_require__(528); -var utils = __webpack_require__(508); +var Base = __webpack_require__(541); +var define = __webpack_require__(502); +var Compiler = __webpack_require__(570); +var Parser = __webpack_require__(600); +var utils = __webpack_require__(580); var regexCache = {}; var cache = {}; @@ -45985,20 +53425,20 @@ module.exports.Parser = Parser; /***/ }), -/* 469 */ +/* 541 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var define = __webpack_require__(470); -var CacheBase = __webpack_require__(471); -var Emitter = __webpack_require__(472); -var isObject = __webpack_require__(448); -var merge = __webpack_require__(489); -var pascal = __webpack_require__(492); -var cu = __webpack_require__(493); +var define = __webpack_require__(542); +var CacheBase = __webpack_require__(543); +var Emitter = __webpack_require__(544); +var isObject = __webpack_require__(520); +var merge = __webpack_require__(561); +var pascal = __webpack_require__(564); +var cu = __webpack_require__(565); /** * Optionally define a custom `cache` namespace to use. @@ -46427,7 +53867,7 @@ module.exports.namespace = namespace; /***/ }), -/* 470 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -46440,7 +53880,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(460); +var isDescriptor = __webpack_require__(532); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -46465,21 +53905,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 471 */ +/* 543 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(448); -var Emitter = __webpack_require__(472); -var visit = __webpack_require__(473); -var toPath = __webpack_require__(476); -var union = __webpack_require__(477); -var del = __webpack_require__(481); -var get = __webpack_require__(479); -var has = __webpack_require__(486); -var set = __webpack_require__(480); +var isObject = __webpack_require__(520); +var Emitter = __webpack_require__(544); +var visit = __webpack_require__(545); +var toPath = __webpack_require__(548); +var union = __webpack_require__(549); +var del = __webpack_require__(553); +var get = __webpack_require__(551); +var has = __webpack_require__(558); +var set = __webpack_require__(552); /** * Create a `Cache` constructor that when instantiated will @@ -46733,7 +54173,7 @@ module.exports.namespace = namespace; /***/ }), -/* 472 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { @@ -46902,7 +54342,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 473 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -46915,8 +54355,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(474); -var mapVisit = __webpack_require__(475); +var visit = __webpack_require__(546); +var mapVisit = __webpack_require__(547); module.exports = function(collection, method, val) { var result; @@ -46939,7 +54379,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 474 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -46952,7 +54392,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(448); +var isObject = __webpack_require__(520); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -46979,14 +54419,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 475 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var visit = __webpack_require__(474); +var visit = __webpack_require__(546); /** * Map `visit` over an array of objects. @@ -47023,7 +54463,7 @@ function isObject(val) { /***/ }), -/* 476 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47036,7 +54476,7 @@ function isObject(val) { -var typeOf = __webpack_require__(453); +var typeOf = __webpack_require__(525); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -47063,16 +54503,16 @@ function filter(arr) { /***/ }), -/* 477 */ +/* 549 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(439); -var union = __webpack_require__(478); -var get = __webpack_require__(479); -var set = __webpack_require__(480); +var isObject = __webpack_require__(511); +var union = __webpack_require__(550); +var get = __webpack_require__(551); +var set = __webpack_require__(552); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -47100,7 +54540,7 @@ function arrayify(val) { /***/ }), -/* 478 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47136,7 +54576,7 @@ module.exports = function union(init) { /***/ }), -/* 479 */ +/* 551 */ /***/ (function(module, exports) { /*! @@ -47192,7 +54632,7 @@ function toString(val) { /***/ }), -/* 480 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47205,10 +54645,10 @@ function toString(val) { -var split = __webpack_require__(444); -var extend = __webpack_require__(438); -var isPlainObject = __webpack_require__(447); -var isObject = __webpack_require__(439); +var split = __webpack_require__(516); +var extend = __webpack_require__(510); +var isPlainObject = __webpack_require__(519); +var isObject = __webpack_require__(511); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -47254,7 +54694,7 @@ function isValidKey(key) { /***/ }), -/* 481 */ +/* 553 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47267,8 +54707,8 @@ function isValidKey(key) { -var isObject = __webpack_require__(448); -var has = __webpack_require__(482); +var isObject = __webpack_require__(520); +var has = __webpack_require__(554); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -47293,7 +54733,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 482 */ +/* 554 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47306,9 +54746,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(483); -var hasValues = __webpack_require__(485); -var get = __webpack_require__(479); +var isObject = __webpack_require__(555); +var hasValues = __webpack_require__(557); +var get = __webpack_require__(551); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -47319,7 +54759,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 483 */ +/* 555 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47332,7 +54772,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(484); +var isArray = __webpack_require__(556); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -47340,7 +54780,7 @@ module.exports = function isObject(val) { /***/ }), -/* 484 */ +/* 556 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -47351,7 +54791,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 485 */ +/* 557 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47394,7 +54834,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 486 */ +/* 558 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47407,9 +54847,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(448); -var hasValues = __webpack_require__(487); -var get = __webpack_require__(479); +var isObject = __webpack_require__(520); +var hasValues = __webpack_require__(559); +var get = __webpack_require__(551); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -47417,7 +54857,7 @@ module.exports = function(val, prop) { /***/ }), -/* 487 */ +/* 559 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47430,8 +54870,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(488); -var isNumber = __webpack_require__(452); +var typeOf = __webpack_require__(560); +var isNumber = __webpack_require__(524); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -47484,10 +54924,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 488 */ +/* 560 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(435); +var isBuffer = __webpack_require__(507); var toString = Object.prototype.toString; /** @@ -47609,14 +55049,14 @@ module.exports = function kindOf(val) { /***/ }), -/* 489 */ +/* 561 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(490); -var forIn = __webpack_require__(491); +var isExtendable = __webpack_require__(562); +var forIn = __webpack_require__(563); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -47680,7 +55120,7 @@ module.exports = mixinDeep; /***/ }), -/* 490 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47693,7 +55133,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(447); +var isPlainObject = __webpack_require__(519); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -47701,7 +55141,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 491 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -47724,7 +55164,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 492 */ +/* 564 */ /***/ (function(module, exports) { /*! @@ -47751,14 +55191,14 @@ module.exports = pascalcase; /***/ }), -/* 493 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var utils = __webpack_require__(494); +var utils = __webpack_require__(566); /** * Expose class utils @@ -48123,7 +55563,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 494 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48137,10 +55577,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(478); -utils.define = __webpack_require__(430); -utils.isObj = __webpack_require__(448); -utils.staticExtend = __webpack_require__(495); +utils.union = __webpack_require__(550); +utils.define = __webpack_require__(502); +utils.isObj = __webpack_require__(520); +utils.staticExtend = __webpack_require__(567); /** @@ -48151,7 +55591,7 @@ module.exports = utils; /***/ }), -/* 495 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48164,8 +55604,8 @@ module.exports = utils; -var copy = __webpack_require__(496); -var define = __webpack_require__(430); +var copy = __webpack_require__(568); +var define = __webpack_require__(502); var util = __webpack_require__(29); /** @@ -48248,15 +55688,15 @@ module.exports = extend; /***/ }), -/* 496 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(453); -var copyDescriptor = __webpack_require__(497); -var define = __webpack_require__(430); +var typeOf = __webpack_require__(525); +var copyDescriptor = __webpack_require__(569); +var define = __webpack_require__(502); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -48429,7 +55869,7 @@ module.exports.has = has; /***/ }), -/* 497 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48517,16 +55957,16 @@ function isObject(val) { /***/ }), -/* 498 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(499); -var define = __webpack_require__(430); -var debug = __webpack_require__(501)('snapdragon:compiler'); -var utils = __webpack_require__(508); +var use = __webpack_require__(571); +var define = __webpack_require__(502); +var debug = __webpack_require__(573)('snapdragon:compiler'); +var utils = __webpack_require__(580); /** * Create a new `Compiler` with the given `options`. @@ -48680,7 +56120,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(527); + var sourcemaps = __webpack_require__(599); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -48701,7 +56141,7 @@ module.exports = Compiler; /***/ }), -/* 499 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48714,7 +56154,7 @@ module.exports = Compiler; -var utils = __webpack_require__(500); +var utils = __webpack_require__(572); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -48829,7 +56269,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 500 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -48843,8 +56283,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(430); -utils.isObject = __webpack_require__(448); +utils.define = __webpack_require__(502); +utils.isObject = __webpack_require__(520); utils.isString = function(val) { @@ -48859,7 +56299,7 @@ module.exports = utils; /***/ }), -/* 501 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -48868,14 +56308,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(502); + module.exports = __webpack_require__(574); } else { - module.exports = __webpack_require__(505); + module.exports = __webpack_require__(577); } /***/ }), -/* 502 */ +/* 574 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -48884,7 +56324,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(503); +exports = module.exports = __webpack_require__(575); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -49066,7 +56506,7 @@ function localstorage() { /***/ }), -/* 503 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { @@ -49082,7 +56522,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(504); +exports.humanize = __webpack_require__(576); /** * The currently active debug mode names, and names to skip. @@ -49274,7 +56714,7 @@ function coerce(val) { /***/ }), -/* 504 */ +/* 576 */ /***/ (function(module, exports) { /** @@ -49432,14 +56872,14 @@ function plural(ms, n, name) { /***/ }), -/* 505 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { /** * Module dependencies. */ -var tty = __webpack_require__(506); +var tty = __webpack_require__(578); var util = __webpack_require__(29); /** @@ -49448,7 +56888,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(503); +exports = module.exports = __webpack_require__(575); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -49627,7 +57067,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(507); + var net = __webpack_require__(579); stream = new net.Socket({ fd: fd, readable: false, @@ -49686,19 +57126,19 @@ exports.enable(load()); /***/ }), -/* 506 */ +/* 578 */ /***/ (function(module, exports) { module.exports = require("tty"); /***/ }), -/* 507 */ +/* 579 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 508 */ +/* 580 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -49708,9 +57148,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(438); -exports.SourceMap = __webpack_require__(509); -exports.sourceMapResolve = __webpack_require__(520); +exports.extend = __webpack_require__(510); +exports.SourceMap = __webpack_require__(581); +exports.sourceMapResolve = __webpack_require__(592); /** * Convert backslash in the given string to forward slashes @@ -49753,7 +57193,7 @@ exports.last = function(arr, n) { /***/ }), -/* 509 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -49761,13 +57201,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(510).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(516).SourceMapConsumer; -exports.SourceNode = __webpack_require__(519).SourceNode; +exports.SourceMapGenerator = __webpack_require__(582).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(588).SourceMapConsumer; +exports.SourceNode = __webpack_require__(591).SourceNode; /***/ }), -/* 510 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -49777,10 +57217,10 @@ exports.SourceNode = __webpack_require__(519).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(511); -var util = __webpack_require__(513); -var ArraySet = __webpack_require__(514).ArraySet; -var MappingList = __webpack_require__(515).MappingList; +var base64VLQ = __webpack_require__(583); +var util = __webpack_require__(585); +var ArraySet = __webpack_require__(586).ArraySet; +var MappingList = __webpack_require__(587).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -50189,7 +57629,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 511 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50229,7 +57669,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(512); +var base64 = __webpack_require__(584); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -50335,7 +57775,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 512 */ +/* 584 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50408,7 +57848,7 @@ exports.decode = function (charCode) { /***/ }), -/* 513 */ +/* 585 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50831,7 +58271,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 514 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50841,7 +58281,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(513); +var util = __webpack_require__(585); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -50958,7 +58398,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 515 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -50968,7 +58408,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(513); +var util = __webpack_require__(585); /** * Determine whether mappingB is after mappingA with respect to generated @@ -51043,7 +58483,7 @@ exports.MappingList = MappingList; /***/ }), -/* 516 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -51053,11 +58493,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(513); -var binarySearch = __webpack_require__(517); -var ArraySet = __webpack_require__(514).ArraySet; -var base64VLQ = __webpack_require__(511); -var quickSort = __webpack_require__(518).quickSort; +var util = __webpack_require__(585); +var binarySearch = __webpack_require__(589); +var ArraySet = __webpack_require__(586).ArraySet; +var base64VLQ = __webpack_require__(583); +var quickSort = __webpack_require__(590).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -52131,7 +59571,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 517 */ +/* 589 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -52248,7 +59688,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 518 */ +/* 590 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -52368,7 +59808,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 519 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -52378,8 +59818,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(510).SourceMapGenerator; -var util = __webpack_require__(513); +var SourceMapGenerator = __webpack_require__(582).SourceMapGenerator; +var util = __webpack_require__(585); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -52787,17 +60227,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 520 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(521) -var resolveUrl = __webpack_require__(522) -var decodeUriComponent = __webpack_require__(523) -var urix = __webpack_require__(525) -var atob = __webpack_require__(526) +var sourceMappingURL = __webpack_require__(593) +var resolveUrl = __webpack_require__(594) +var decodeUriComponent = __webpack_require__(595) +var urix = __webpack_require__(597) +var atob = __webpack_require__(598) @@ -53095,7 +60535,7 @@ module.exports = { /***/ }), -/* 521 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -53158,7 +60598,7 @@ void (function(root, factory) { /***/ }), -/* 522 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -53176,13 +60616,13 @@ module.exports = resolveUrl /***/ }), -/* 523 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(524) +var decodeUriComponent = __webpack_require__(596) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -53193,7 +60633,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 524 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53294,7 +60734,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 525 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -53317,7 +60757,7 @@ module.exports = urix /***/ }), -/* 526 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53331,7 +60771,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 527 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -53339,8 +60779,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); -var define = __webpack_require__(430); -var utils = __webpack_require__(508); +var define = __webpack_require__(502); +var utils = __webpack_require__(580); /** * Expose `mixin()`. @@ -53483,19 +60923,19 @@ exports.comment = function(node) { /***/ }), -/* 528 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(499); +var use = __webpack_require__(571); var util = __webpack_require__(29); -var Cache = __webpack_require__(529); -var define = __webpack_require__(430); -var debug = __webpack_require__(501)('snapdragon:parser'); -var Position = __webpack_require__(530); -var utils = __webpack_require__(508); +var Cache = __webpack_require__(601); +var define = __webpack_require__(502); +var debug = __webpack_require__(573)('snapdragon:parser'); +var Position = __webpack_require__(602); +var utils = __webpack_require__(580); /** * Create a new `Parser` with the given `input` and `options`. @@ -54023,7 +61463,7 @@ module.exports = Parser; /***/ }), -/* 529 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54130,13 +61570,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 530 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(430); +var define = __webpack_require__(502); /** * Store position for a node @@ -54151,16 +61591,16 @@ module.exports = function Position(start, parser) { /***/ }), -/* 531 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(532); -var define = __webpack_require__(538); -var extend = __webpack_require__(539); -var not = __webpack_require__(541); +var safe = __webpack_require__(604); +var define = __webpack_require__(610); +var extend = __webpack_require__(611); +var not = __webpack_require__(613); var MAX_LENGTH = 1024 * 64; /** @@ -54313,10 +61753,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 532 */ +/* 604 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(533); +var parse = __webpack_require__(605); var types = parse.types; module.exports = function (re, opts) { @@ -54362,13 +61802,13 @@ function isRegExp (x) { /***/ }), -/* 533 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(534); -var types = __webpack_require__(535); -var sets = __webpack_require__(536); -var positions = __webpack_require__(537); +var util = __webpack_require__(606); +var types = __webpack_require__(607); +var sets = __webpack_require__(608); +var positions = __webpack_require__(609); module.exports = function(regexpStr) { @@ -54650,11 +62090,11 @@ module.exports.types = types; /***/ }), -/* 534 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(535); -var sets = __webpack_require__(536); +var types = __webpack_require__(607); +var sets = __webpack_require__(608); // All of these are private and only used by randexp. @@ -54767,7 +62207,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 535 */ +/* 607 */ /***/ (function(module, exports) { module.exports = { @@ -54783,10 +62223,10 @@ module.exports = { /***/ }), -/* 536 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(535); +var types = __webpack_require__(607); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -54871,10 +62311,10 @@ exports.anyChar = function() { /***/ }), -/* 537 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(535); +var types = __webpack_require__(607); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -54894,7 +62334,7 @@ exports.end = function() { /***/ }), -/* 538 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -54907,8 +62347,8 @@ exports.end = function() { -var isobject = __webpack_require__(448); -var isDescriptor = __webpack_require__(460); +var isobject = __webpack_require__(520); +var isDescriptor = __webpack_require__(532); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -54939,14 +62379,14 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 539 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(540); -var assignSymbols = __webpack_require__(449); +var isExtendable = __webpack_require__(612); +var assignSymbols = __webpack_require__(521); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -55006,7 +62446,7 @@ function isEnum(obj, key) { /***/ }), -/* 540 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55019,7 +62459,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(447); +var isPlainObject = __webpack_require__(519); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -55027,14 +62467,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 541 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(539); -var safe = __webpack_require__(532); +var extend = __webpack_require__(611); +var safe = __webpack_require__(604); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -55106,14 +62546,14 @@ module.exports = toRegex; /***/ }), -/* 542 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(543); -var extglob = __webpack_require__(558); +var nanomatch = __webpack_require__(615); +var extglob = __webpack_require__(630); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -55190,7 +62630,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 543 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -55201,17 +62641,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(29); -var toRegex = __webpack_require__(429); -var extend = __webpack_require__(544); +var toRegex = __webpack_require__(501); +var extend = __webpack_require__(616); /** * Local dependencies */ -var compilers = __webpack_require__(546); -var parsers = __webpack_require__(547); -var cache = __webpack_require__(550); -var utils = __webpack_require__(552); +var compilers = __webpack_require__(618); +var parsers = __webpack_require__(619); +var cache = __webpack_require__(622); +var utils = __webpack_require__(624); var MAX_LENGTH = 1024 * 64; /** @@ -56035,14 +63475,14 @@ module.exports = nanomatch; /***/ }), -/* 544 */ +/* 616 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(545); -var assignSymbols = __webpack_require__(449); +var isExtendable = __webpack_require__(617); +var assignSymbols = __webpack_require__(521); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -56102,7 +63542,7 @@ function isEnum(obj, key) { /***/ }), -/* 545 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56115,7 +63555,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(447); +var isPlainObject = __webpack_require__(519); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -56123,7 +63563,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 546 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56469,15 +63909,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 547 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(440); -var toRegex = __webpack_require__(429); -var isOdd = __webpack_require__(548); +var regexNot = __webpack_require__(512); +var toRegex = __webpack_require__(501); +var isOdd = __webpack_require__(620); /** * Characters to use in negation regex (we want to "not" match @@ -56863,7 +64303,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 548 */ +/* 620 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56876,7 +64316,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(549); +var isNumber = __webpack_require__(621); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -56890,7 +64330,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 549 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56918,14 +64358,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 550 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(551))(); +module.exports = new (__webpack_require__(623))(); /***/ }), -/* 551 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56938,7 +64378,7 @@ module.exports = new (__webpack_require__(551))(); -var MapCache = __webpack_require__(529); +var MapCache = __webpack_require__(601); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -57060,7 +64500,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 552 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57073,14 +64513,14 @@ var path = __webpack_require__(16); * Module dependencies */ -var isWindows = __webpack_require__(553)(); -var Snapdragon = __webpack_require__(468); -utils.define = __webpack_require__(554); -utils.diff = __webpack_require__(555); -utils.extend = __webpack_require__(544); -utils.pick = __webpack_require__(556); -utils.typeOf = __webpack_require__(557); -utils.unique = __webpack_require__(441); +var isWindows = __webpack_require__(625)(); +var Snapdragon = __webpack_require__(540); +utils.define = __webpack_require__(626); +utils.diff = __webpack_require__(627); +utils.extend = __webpack_require__(616); +utils.pick = __webpack_require__(628); +utils.typeOf = __webpack_require__(629); +utils.unique = __webpack_require__(513); /** * Returns true if the given value is effectively an empty string @@ -57446,7 +64886,7 @@ utils.unixify = function(options) { /***/ }), -/* 553 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -57474,7 +64914,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 554 */ +/* 626 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57487,8 +64927,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(448); -var isDescriptor = __webpack_require__(460); +var isobject = __webpack_require__(520); +var isDescriptor = __webpack_require__(532); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -57519,7 +64959,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 555 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57573,7 +65013,7 @@ function diffArray(one, two) { /***/ }), -/* 556 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57586,7 +65026,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(448); +var isObject = __webpack_require__(520); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -57615,7 +65055,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 557 */ +/* 629 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -57750,7 +65190,7 @@ function isBuffer(val) { /***/ }), -/* 558 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57760,18 +65200,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(438); -var unique = __webpack_require__(441); -var toRegex = __webpack_require__(429); +var extend = __webpack_require__(510); +var unique = __webpack_require__(513); +var toRegex = __webpack_require__(501); /** * Local dependencies */ -var compilers = __webpack_require__(559); -var parsers = __webpack_require__(565); -var Extglob = __webpack_require__(568); -var utils = __webpack_require__(567); +var compilers = __webpack_require__(631); +var parsers = __webpack_require__(637); +var Extglob = __webpack_require__(640); +var utils = __webpack_require__(639); var MAX_LENGTH = 1024 * 64; /** @@ -58088,13 +65528,13 @@ module.exports = extglob; /***/ }), -/* 559 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(560); +var brackets = __webpack_require__(632); /** * Extglob compilers @@ -58264,7 +65704,7 @@ module.exports = function(extglob) { /***/ }), -/* 560 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58274,17 +65714,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(561); -var parsers = __webpack_require__(563); +var compilers = __webpack_require__(633); +var parsers = __webpack_require__(635); /** * Module dependencies */ -var debug = __webpack_require__(501)('expand-brackets'); -var extend = __webpack_require__(438); -var Snapdragon = __webpack_require__(468); -var toRegex = __webpack_require__(429); +var debug = __webpack_require__(573)('expand-brackets'); +var extend = __webpack_require__(510); +var Snapdragon = __webpack_require__(540); +var toRegex = __webpack_require__(501); /** * Parses the given POSIX character class `pattern` and returns a @@ -58482,13 +65922,13 @@ module.exports = brackets; /***/ }), -/* 561 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(562); +var posix = __webpack_require__(634); module.exports = function(brackets) { brackets.compiler @@ -58576,7 +66016,7 @@ module.exports = function(brackets) { /***/ }), -/* 562 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -58605,14 +66045,14 @@ module.exports = { /***/ }), -/* 563 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(564); -var define = __webpack_require__(430); +var utils = __webpack_require__(636); +var define = __webpack_require__(502); /** * Text regex @@ -58831,14 +66271,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 564 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(429); -var regexNot = __webpack_require__(440); +var toRegex = __webpack_require__(501); +var regexNot = __webpack_require__(512); var cached; /** @@ -58872,15 +66312,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 565 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(560); -var define = __webpack_require__(566); -var utils = __webpack_require__(567); +var brackets = __webpack_require__(632); +var define = __webpack_require__(638); +var utils = __webpack_require__(639); /** * Characters to use in text regex (we want to "not" match @@ -59035,7 +66475,7 @@ module.exports = parsers; /***/ }), -/* 566 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59048,7 +66488,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(460); +var isDescriptor = __webpack_require__(532); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -59073,14 +66513,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 567 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(440); -var Cache = __webpack_require__(551); +var regex = __webpack_require__(512); +var Cache = __webpack_require__(623); /** * Utils @@ -59149,7 +66589,7 @@ utils.createRegex = function(str) { /***/ }), -/* 568 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59159,16 +66599,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(468); -var define = __webpack_require__(566); -var extend = __webpack_require__(438); +var Snapdragon = __webpack_require__(540); +var define = __webpack_require__(638); +var extend = __webpack_require__(510); /** * Local dependencies */ -var compilers = __webpack_require__(559); -var parsers = __webpack_require__(565); +var compilers = __webpack_require__(631); +var parsers = __webpack_require__(637); /** * Customize Snapdragon parser and renderer @@ -59234,16 +66674,16 @@ module.exports = Extglob; /***/ }), -/* 569 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(558); -var nanomatch = __webpack_require__(543); -var regexNot = __webpack_require__(440); -var toRegex = __webpack_require__(531); +var extglob = __webpack_require__(630); +var nanomatch = __webpack_require__(615); +var regexNot = __webpack_require__(512); +var toRegex = __webpack_require__(603); var not; /** @@ -59324,14 +66764,14 @@ function textRegex(pattern) { /***/ }), -/* 570 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(551))(); +module.exports = new (__webpack_require__(623))(); /***/ }), -/* 571 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59344,13 +66784,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var Snapdragon = __webpack_require__(468); -utils.define = __webpack_require__(538); -utils.diff = __webpack_require__(555); -utils.extend = __webpack_require__(539); -utils.pick = __webpack_require__(556); -utils.typeOf = __webpack_require__(572); -utils.unique = __webpack_require__(441); +var Snapdragon = __webpack_require__(540); +utils.define = __webpack_require__(610); +utils.diff = __webpack_require__(627); +utils.extend = __webpack_require__(611); +utils.pick = __webpack_require__(628); +utils.typeOf = __webpack_require__(644); +utils.unique = __webpack_require__(513); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -59647,7 +67087,7 @@ utils.unixify = function(options) { /***/ }), -/* 572 */ +/* 644 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -59782,7 +67222,7 @@ function isBuffer(val) { /***/ }), -/* 573 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59801,9 +67241,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(574); -var reader_1 = __webpack_require__(587); -var fs_stream_1 = __webpack_require__(591); +var readdir = __webpack_require__(646); +var reader_1 = __webpack_require__(659); +var fs_stream_1 = __webpack_require__(663); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -59864,15 +67304,15 @@ exports.default = ReaderAsync; /***/ }), -/* 574 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(575); -const readdirAsync = __webpack_require__(583); -const readdirStream = __webpack_require__(586); +const readdirSync = __webpack_require__(647); +const readdirAsync = __webpack_require__(655); +const readdirStream = __webpack_require__(658); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -59956,7 +67396,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 575 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -59964,11 +67404,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(576); +const DirectoryReader = __webpack_require__(648); let syncFacade = { - fs: __webpack_require__(581), - forEach: __webpack_require__(582), + fs: __webpack_require__(653), + forEach: __webpack_require__(654), sync: true }; @@ -59997,7 +67437,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 576 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60006,9 +67446,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(28).Readable; const EventEmitter = __webpack_require__(46).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(577); -const stat = __webpack_require__(579); -const call = __webpack_require__(580); +const normalizeOptions = __webpack_require__(649); +const stat = __webpack_require__(651); +const call = __webpack_require__(652); /** * Asynchronously reads the contents of a directory and streams the results @@ -60384,14 +67824,14 @@ module.exports = DirectoryReader; /***/ }), -/* 577 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(578); +const globToRegExp = __webpack_require__(650); module.exports = normalizeOptions; @@ -60568,7 +68008,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 578 */ +/* 650 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -60705,13 +68145,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 579 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(580); +const call = __webpack_require__(652); module.exports = stat; @@ -60786,7 +68226,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 580 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60847,14 +68287,14 @@ function callOnce (fn) { /***/ }), -/* 581 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(580); +const call = __webpack_require__(652); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -60918,7 +68358,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 582 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60947,7 +68387,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 583 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60955,12 +68395,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(584); -const DirectoryReader = __webpack_require__(576); +const maybe = __webpack_require__(656); +const DirectoryReader = __webpack_require__(648); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(585), + forEach: __webpack_require__(657), async: true }; @@ -61002,7 +68442,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 584 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61029,7 +68469,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 585 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61065,7 +68505,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 586 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61073,11 +68513,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(576); +const DirectoryReader = __webpack_require__(648); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(585), + forEach: __webpack_require__(657), async: true }; @@ -61097,16 +68537,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 587 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(588); -var entry_1 = __webpack_require__(590); -var pathUtil = __webpack_require__(589); +var deep_1 = __webpack_require__(660); +var entry_1 = __webpack_require__(662); +var pathUtil = __webpack_require__(661); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -61172,14 +68612,14 @@ exports.default = Reader; /***/ }), -/* 588 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(589); -var patternUtils = __webpack_require__(421); +var pathUtils = __webpack_require__(661); +var patternUtils = __webpack_require__(494); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -61262,7 +68702,7 @@ exports.default = DeepFilter; /***/ }), -/* 589 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61293,14 +68733,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 590 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(589); -var patternUtils = __webpack_require__(421); +var pathUtils = __webpack_require__(661); +var patternUtils = __webpack_require__(494); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -61385,7 +68825,7 @@ exports.default = EntryFilter; /***/ }), -/* 591 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61405,8 +68845,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(28); -var fsStat = __webpack_require__(592); -var fs_1 = __webpack_require__(596); +var fsStat = __webpack_require__(664); +var fs_1 = __webpack_require__(668); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -61456,14 +68896,14 @@ exports.default = FileSystemStream; /***/ }), -/* 592 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(593); -const statProvider = __webpack_require__(595); +const optionsManager = __webpack_require__(665); +const statProvider = __webpack_require__(667); /** * Asynchronous API. */ @@ -61494,13 +68934,13 @@ exports.statSync = statSync; /***/ }), -/* 593 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(594); +const fsAdapter = __webpack_require__(666); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -61513,7 +68953,7 @@ exports.prepare = prepare; /***/ }), -/* 594 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61536,7 +68976,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 595 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61588,7 +69028,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 596 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61619,7 +69059,7 @@ exports.default = FileSystem; /***/ }), -/* 597 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61639,9 +69079,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(28); -var readdir = __webpack_require__(574); -var reader_1 = __webpack_require__(587); -var fs_stream_1 = __webpack_require__(591); +var readdir = __webpack_require__(646); +var reader_1 = __webpack_require__(659); +var fs_stream_1 = __webpack_require__(663); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -61709,7 +69149,7 @@ exports.default = ReaderStream; /***/ }), -/* 598 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61728,9 +69168,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(574); -var reader_1 = __webpack_require__(587); -var fs_sync_1 = __webpack_require__(599); +var readdir = __webpack_require__(646); +var reader_1 = __webpack_require__(659); +var fs_sync_1 = __webpack_require__(671); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -61790,7 +69230,7 @@ exports.default = ReaderSync; /***/ }), -/* 599 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61809,8 +69249,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(592); -var fs_1 = __webpack_require__(596); +var fsStat = __webpack_require__(664); +var fs_1 = __webpack_require__(668); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -61856,7 +69296,7 @@ exports.default = FileSystemSync; /***/ }), -/* 600 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61872,13 +69312,13 @@ exports.flatten = flatten; /***/ }), -/* 601 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(602); +var merge2 = __webpack_require__(177); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -61893,127 +69333,13 @@ exports.merge = merge; /***/ }), -/* 602 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/* - * merge2 - * https://github.com/teambition/merge2 - * - * Copyright (c) 2014-2016 Teambition - * Licensed under the MIT license. - */ -const Stream = __webpack_require__(28) -const PassThrough = Stream.PassThrough -const slice = Array.prototype.slice - -module.exports = merge2 - -function merge2 () { - const streamsQueue = [] - let merging = false - const args = slice.call(arguments) - let options = args[args.length - 1] - - if (options && !Array.isArray(options) && options.pipe == null) args.pop() - else options = {} - - const doEnd = options.end !== false - if (options.objectMode == null) options.objectMode = true - if (options.highWaterMark == null) options.highWaterMark = 64 * 1024 - const mergedStream = PassThrough(options) - - function addStream () { - for (let i = 0, len = arguments.length; i < len; i++) { - streamsQueue.push(pauseStreams(arguments[i], options)) - } - mergeStream() - return this - } - - function mergeStream () { - if (merging) return - merging = true - - let streams = streamsQueue.shift() - if (!streams) { - process.nextTick(endStream) - return - } - if (!Array.isArray(streams)) streams = [streams] - - let pipesCount = streams.length + 1 - - function next () { - if (--pipesCount > 0) return - merging = false - mergeStream() - } - - function pipe (stream) { - function onend () { - stream.removeListener('merge2UnpipeEnd', onend) - stream.removeListener('end', onend) - next() - } - // skip ended stream - if (stream._readableState.endEmitted) return next() - - stream.on('merge2UnpipeEnd', onend) - stream.on('end', onend) - stream.pipe(mergedStream, { end: false }) - // compatible for old stream - stream.resume() - } - - for (let i = 0; i < streams.length; i++) pipe(streams[i]) - - next() - } - - function endStream () { - merging = false - // emit 'queueDrain' when all streams merged. - mergedStream.emit('queueDrain') - return doEnd && mergedStream.end() - } - - mergedStream.setMaxListeners(0) - mergedStream.add = addStream - mergedStream.on('unpipe', function (stream) { - stream.emit('merge2UnpipeEnd') - }) - - if (args.length) addStream.apply(null, args) - return mergedStream -} - -// check and pause streams for pipe. -function pauseStreams (streams, options) { - if (!Array.isArray(streams)) { - // Backwards-compat with old-style streams - if (!streams._readableState && streams.pipe) streams = streams.pipe(PassThrough(options)) - if (!streams._readableState || !streams.pause || !streams.pipe) { - throw new Error('Only readable stream can be merged.') - } - streams.pause() - } else { - for (let i = 0, len = streams.length; i < len; i++) streams[i] = pauseStreams(streams[i], options) - } - return streams -} - - -/***/ }), -/* 603 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(604); +const pathType = __webpack_require__(675); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -62079,13 +69405,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 604 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(605); +const pify = __webpack_require__(676); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -62128,7 +69454,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 605 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62219,17 +69545,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 606 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(417); -const gitIgnore = __webpack_require__(607); -const pify = __webpack_require__(608); -const slash = __webpack_require__(609); +const fastGlob = __webpack_require__(490); +const gitIgnore = __webpack_require__(678); +const pify = __webpack_require__(679); +const slash = __webpack_require__(680); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -62327,7 +69653,7 @@ module.exports.sync = options => { /***/ }), -/* 607 */ +/* 678 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -62796,7 +70122,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 608 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62871,7 +70197,7 @@ module.exports = (input, options) => { /***/ }), -/* 609 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62889,17 +70215,17 @@ module.exports = input => { /***/ }), -/* 610 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const {Buffer} = __webpack_require__(611); -const CpFileError = __webpack_require__(613); -const fs = __webpack_require__(615); -const ProgressEmitter = __webpack_require__(617); +const {Buffer} = __webpack_require__(682); +const CpFileError = __webpack_require__(684); +const fs = __webpack_require__(686); +const ProgressEmitter = __webpack_require__(688); const cpFile = (source, destination, options) => { if (!source || !destination) { @@ -63053,11 +70379,11 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 611 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { /* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(612) +var buffer = __webpack_require__(683) var Buffer = buffer.Buffer // alternative to using Object.keys for old browsers @@ -63121,18 +70447,18 @@ SafeBuffer.allocUnsafeSlow = function (size) { /***/ }), -/* 612 */ +/* 683 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 613 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(614); +const NestedError = __webpack_require__(685); class CpFileError extends NestedError { constructor(message, nested) { @@ -63146,7 +70472,7 @@ module.exports = CpFileError; /***/ }), -/* 614 */ +/* 685 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(44); @@ -63200,15 +70526,15 @@ module.exports = NestedError; /***/ }), -/* 615 */ +/* 686 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(22); const makeDir = __webpack_require__(115); -const pify = __webpack_require__(616); -const CpFileError = __webpack_require__(613); +const pify = __webpack_require__(687); +const CpFileError = __webpack_require__(684); const fsP = pify(fs); @@ -63353,7 +70679,7 @@ if (fs.copyFileSync) { /***/ }), -/* 616 */ +/* 687 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63428,7 +70754,7 @@ module.exports = (input, options) => { /***/ }), -/* 617 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63469,12 +70795,12 @@ module.exports = ProgressEmitter; /***/ }), -/* 618 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(619); +const NestedError = __webpack_require__(690); class CpyError extends NestedError { constructor(message, nested) { @@ -63488,7 +70814,7 @@ module.exports = CpyError; /***/ }), -/* 619 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -63544,7 +70870,7 @@ module.exports = NestedError; /***/ }), -/* 620 */ +/* 691 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/packages/kbn-pm/package.json b/packages/kbn-pm/package.json index 9d258af96996b..dafe73ec7d1d6 100644 --- a/packages/kbn-pm/package.json +++ b/packages/kbn-pm/package.json @@ -39,7 +39,7 @@ "cmd-shim": "^2.1.0", "cpy": "^7.3.0", "dedent": "^0.7.0", - "del": "^4.1.1", + "del": "^5.1.0", "execa": "^3.2.0", "getopts": "^2.2.4", "glob": "^7.1.2", diff --git a/packages/kbn-pm/src/utils/projects.test.ts b/packages/kbn-pm/src/utils/projects.test.ts index 1b839440b9449..093f178f1813a 100644 --- a/packages/kbn-pm/src/utils/projects.test.ts +++ b/packages/kbn-pm/src/utils/projects.test.ts @@ -19,7 +19,7 @@ import { mkdir, symlink } from 'fs'; import { join, resolve } from 'path'; -import rmdir from 'rimraf'; +import del from 'del'; import { promisify } from 'util'; import { getProjectPaths } from '../config'; @@ -33,20 +33,20 @@ import { topologicallyBatchProjects, } from './projects'; -const rootPath = resolve(`${__dirname}/__fixtures__/kibana`); +const rootPath = resolve(__dirname, '__fixtures__/kibana'); const rootPlugins = join(rootPath, 'plugins'); describe('#getProjects', () => { beforeAll(async () => { await promisify(mkdir)(rootPlugins); - return promisify(symlink)( + await promisify(symlink)( join(__dirname, '__fixtures__/symlinked-plugins/corge'), join(rootPlugins, 'corge') ); }); - afterAll(() => promisify(rmdir)(rootPlugins)); + afterAll(async () => await del(rootPlugins)); test('find all packages in the packages directory', async () => { const projects = await getProjects(rootPath, ['packages/*']); diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index 86a81207a9fa9..113783f66bc59 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -20,7 +20,7 @@ "dependencies": { "chalk": "^2.4.2", "dedent": "^0.7.0", - "del": "^4.1.1", + "del": "^5.1.0", "getopts": "^2.2.4", "glob": "^7.1.2", "parse-link-header": "^1.0.1", diff --git a/packages/kbn-utility-types/package.json b/packages/kbn-utility-types/package.json index b665fa20ff1ff..a79d08677020b 100644 --- a/packages/kbn-utility-types/package.json +++ b/packages/kbn-utility-types/package.json @@ -10,12 +10,13 @@ "kbn:bootstrap": "tsc", "kbn:watch": "tsc --watch", "test": "tsd", - "clean": "rimraf target" + "clean": "del target" }, "dependencies": { "utility-types": "^3.7.0" }, "devDependencies": { + "del-cli": "^3.0.0", "tsd": "^0.7.4" } } diff --git a/renovate.json5 b/renovate.json5 index 12e101fd31d77..deb513d57c85e 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -529,14 +529,6 @@ '@types/request', ], }, - { - groupSlug: 'rimraf', - groupName: 'rimraf related packages', - packageNames: [ - 'rimraf', - '@types/rimraf', - ], - }, { groupSlug: 'selenium-webdriver', groupName: 'selenium-webdriver related packages', diff --git a/src/cli/serve/integration_tests/reload_logging_config.test.js b/src/cli/serve/integration_tests/reload_logging_config.test.js index 8e8bdb15abc68..8558a5eb6c910 100644 --- a/src/cli/serve/integration_tests/reload_logging_config.test.js +++ b/src/cli/serve/integration_tests/reload_logging_config.test.js @@ -21,7 +21,7 @@ import { spawn } from 'child_process'; import fs from 'fs'; import path from 'path'; import os from 'os'; -import rimraf from 'rimraf'; +import del from 'del'; import { safeDump } from 'js-yaml'; import { createMapStream, createSplitStream, createPromiseFromStreams } from '../../../legacy/utils/streams'; @@ -70,7 +70,7 @@ describe('Server logging configuration', function () { child = undefined; } - rimraf.sync(tempDir); + del.sync(tempDir, { force: true }); }); const isWindows = /^win/.test(process.platform); diff --git a/src/cli_plugin/install/cleanup.js b/src/cli_plugin/install/cleanup.js index 631257fba7271..55251e6a0a0db 100644 --- a/src/cli_plugin/install/cleanup.js +++ b/src/cli_plugin/install/cleanup.js @@ -17,7 +17,7 @@ * under the License. */ -import rimraf from 'rimraf'; +import del from 'del'; import fs from 'fs'; export function cleanPrevious(settings, logger) { @@ -27,7 +27,7 @@ export function cleanPrevious(settings, logger) { logger.log('Found previous install attempt. Deleting...'); try { - rimraf.sync(settings.workingPath); + del.sync(settings.workingPath); } catch (e) { reject(e); } @@ -44,8 +44,8 @@ export function cleanArtifacts(settings) { // delete the working directory. // At this point we're bailing, so swallow any errors on delete. try { - rimraf.sync(settings.workingPath); - rimraf.sync(settings.plugins[0].path); + del.sync(settings.workingPath); + del.sync(settings.plugins[0].path); } catch (e) {} // eslint-disable-line no-empty } diff --git a/src/cli_plugin/install/cleanup.test.js b/src/cli_plugin/install/cleanup.test.js index a0f5f5064102c..bb2771920b39c 100644 --- a/src/cli_plugin/install/cleanup.test.js +++ b/src/cli_plugin/install/cleanup.test.js @@ -19,7 +19,7 @@ import sinon from 'sinon'; import fs from 'fs'; -import rimraf from 'rimraf'; +import del from 'del'; import { cleanPrevious, cleanArtifacts } from './cleanup'; import Logger from '../lib/logger'; @@ -48,11 +48,11 @@ describe('kibana cli', function () { logger.log.restore(); logger.error.restore(); fs.statSync.restore(); - rimraf.sync.restore(); + del.sync.restore(); }); it('should resolve if the working path does not exist', function () { - sinon.stub(rimraf, 'sync'); + sinon.stub(del, 'sync'); sinon.stub(fs, 'statSync').callsFake(() => { const error = new Error('ENOENT'); error.code = 'ENOENT'; @@ -67,7 +67,7 @@ describe('kibana cli', function () { }); it('should rethrow any exception except ENOENT from fs.statSync', function () { - sinon.stub(rimraf, 'sync'); + sinon.stub(del, 'sync'); sinon.stub(fs, 'statSync').throws(new Error('An Unhandled Error')); errorStub = sinon.stub(); @@ -79,7 +79,7 @@ describe('kibana cli', function () { }); it('should log a message if there was a working directory', function () { - sinon.stub(rimraf, 'sync'); + sinon.stub(del, 'sync'); sinon.stub(fs, 'statSync'); return cleanPrevious(settings, logger) @@ -89,9 +89,9 @@ describe('kibana cli', function () { }); }); - it('should rethrow any exception from rimraf.sync', function () { + it('should rethrow any exception from del.sync', function () { sinon.stub(fs, 'statSync'); - sinon.stub(rimraf, 'sync').throws(new Error('I am an error thrown by rimraf')); + sinon.stub(del, 'sync').throws(new Error('I am an error thrown by del')); errorStub = sinon.stub(); return cleanPrevious(settings, logger) @@ -102,7 +102,7 @@ describe('kibana cli', function () { }); it('should resolve if the working path is deleted', function () { - sinon.stub(rimraf, 'sync'); + sinon.stub(del, 'sync'); sinon.stub(fs, 'statSync'); return cleanPrevious(settings, logger) @@ -117,18 +117,18 @@ describe('kibana cli', function () { beforeEach(function () {}); afterEach(function () { - rimraf.sync.restore(); + del.sync.restore(); }); it('should attempt to delete the working directory', function () { - sinon.stub(rimraf, 'sync'); + sinon.stub(del, 'sync'); cleanArtifacts(settings); - expect(rimraf.sync.calledWith(settings.workingPath)).toBe(true); + expect(del.sync.calledWith(settings.workingPath)).toBe(true); }); - it('should swallow any errors thrown by rimraf.sync', function () { - sinon.stub(rimraf, 'sync').throws(new Error('Something bad happened.')); + it('should swallow any errors thrown by del.sync', function () { + sinon.stub(del, 'sync').throws(new Error('Something bad happened.')); expect(() => cleanArtifacts(settings)).not.toThrow(); }); diff --git a/src/cli_plugin/install/download.test.js b/src/cli_plugin/install/download.test.js index 9de6491f3c957..0769e5351a5d2 100644 --- a/src/cli_plugin/install/download.test.js +++ b/src/cli_plugin/install/download.test.js @@ -20,7 +20,7 @@ import sinon from 'sinon'; import nock from 'nock'; import glob from 'glob-all'; -import rimraf from 'rimraf'; +import del from 'del'; import Fs from 'fs'; import Logger from '../lib/logger'; import { UnsupportedProtocolError } from '../lib/errors'; @@ -63,14 +63,14 @@ describe('kibana cli', function () { beforeEach(function () { sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); - rimraf.sync(testWorkingPath); + del.sync(testWorkingPath); Fs.mkdirSync(testWorkingPath, { recursive: true }); }); afterEach(function () { logger.log.restore(); logger.error.restore(); - rimraf.sync(testWorkingPath); + del.sync(testWorkingPath); }); describe('_downloadSingle', function () { diff --git a/src/cli_plugin/install/install.js b/src/cli_plugin/install/install.js index 10816591f7d71..a62d8525f2495 100644 --- a/src/cli_plugin/install/install.js +++ b/src/cli_plugin/install/install.js @@ -25,7 +25,7 @@ import path from 'path'; import { cleanPrevious, cleanArtifacts } from './cleanup'; import { extract, getPackData } from './pack'; import { renamePlugin } from './rename'; -import { sync as rimrafSync } from 'rimraf'; +import del from 'del'; import { errorIfXPackInstall } from '../lib/error_if_x_pack'; import { existingInstall, assertVersion } from './kibana'; import { prepareExternalProjectDependencies } from '@kbn/pm'; @@ -46,7 +46,7 @@ export default async function install(settings, logger) { await extract(settings, logger); - rimrafSync(settings.tempArchiveFile); + del.sync(settings.tempArchiveFile); existingInstall(settings, logger); diff --git a/src/cli_plugin/install/kibana.test.js b/src/cli_plugin/install/kibana.test.js index 64de96b34e807..f5485846274ce 100644 --- a/src/cli_plugin/install/kibana.test.js +++ b/src/cli_plugin/install/kibana.test.js @@ -17,19 +17,19 @@ * under the License. */ -jest.mock('fs', () => ({ - statSync: jest.fn().mockImplementation(() => require('fs').statSync), - unlinkSync: jest.fn().mockImplementation(() => require('fs').unlinkSync), - mkdirSync: jest.fn().mockImplementation(() => require('fs').mkdirSync), -})); - import sinon from 'sinon'; import Logger from '../lib/logger'; import { join } from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import fs from 'fs'; import { existingInstall, assertVersion } from './kibana'; +jest.spyOn(fs, 'statSync'); + +beforeEach(() => { + jest.clearAllMocks(); +}); + describe('kibana cli', function () { describe('plugin installer', function () { @@ -53,7 +53,7 @@ describe('kibana cli', function () { describe('assertVersion', function () { beforeEach(function () { - rimraf.sync(testWorkingPath); + del.sync(testWorkingPath); fs.mkdirSync(testWorkingPath, { recursive: true }); sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); @@ -62,7 +62,7 @@ describe('kibana cli', function () { afterEach(function () { logger.log.restore(); logger.error.restore(); - rimraf.sync(testWorkingPath); + del.sync(testWorkingPath); }); it('should succeed with exact match', function () { @@ -124,14 +124,14 @@ describe('kibana cli', function () { }); it('should throw an error if the plugin already exists.', function () { - fs.statSync = jest.fn().mockImplementationOnce(() => true); + fs.statSync.mockImplementationOnce(() => true); existingInstall(settings, logger); expect(logger.error.firstCall.args[0]).toMatch(/already exists/); expect(process.exit.called).toBe(true); }); it('should not throw an error if the plugin does not exist.', function () { - fs.statSync = jest.fn().mockImplementationOnce(() => { + fs.statSync.mockImplementationOnce(() => { throw { code: 'ENOENT' }; }); existingInstall(settings, logger); diff --git a/src/cli_plugin/install/pack.test.js b/src/cli_plugin/install/pack.test.js index 1bc2504397fb5..b599934b1d99b 100644 --- a/src/cli_plugin/install/pack.test.js +++ b/src/cli_plugin/install/pack.test.js @@ -21,7 +21,7 @@ import Fs from 'fs'; import sinon from 'sinon'; import glob from 'glob-all'; -import rimraf from 'rimraf'; +import del from 'del'; import Logger from '../lib/logger'; import { extract, getPackData } from './pack'; import { _downloadSingle } from './download'; @@ -41,7 +41,7 @@ describe('kibana cli', function () { beforeEach(function () { //These tests are dependent on the file system, and I had some inconsistent - //behavior with rimraf.sync show up. Until these tests are re-written to not + //behavior with del.sync show up. Until these tests are re-written to not //depend on the file system, I make sure that each test uses a different //working directory. testNum += 1; @@ -65,7 +65,7 @@ describe('kibana cli', function () { afterEach(function () { logger.log.restore(); logger.error.restore(); - rimraf.sync(workingPathRoot); + del.sync(workingPathRoot); }); function copyReplyFile(filename) { diff --git a/src/cli_plugin/install/zip.test.js b/src/cli_plugin/install/zip.test.js index 340dec196eef5..0bcc1c182ff0d 100644 --- a/src/cli_plugin/install/zip.test.js +++ b/src/cli_plugin/install/zip.test.js @@ -17,7 +17,7 @@ * under the License. */ -import rimraf from 'rimraf'; +import del from 'del'; import path from 'path'; import os from 'os'; import glob from 'glob'; @@ -38,7 +38,7 @@ describe('kibana cli', function () { }); afterEach(() => { - rimraf.sync(tempPath); + del.sync(tempPath, { force: true }); }); describe('analyzeArchive', function () { diff --git a/src/cli_plugin/list/list.test.js b/src/cli_plugin/list/list.test.js index 425a6bee5394e..5a40fcc793e08 100644 --- a/src/cli_plugin/list/list.test.js +++ b/src/cli_plugin/list/list.test.js @@ -18,7 +18,7 @@ */ import sinon from 'sinon'; -import rimraf from 'rimraf'; +import del from 'del'; import Logger from '../lib/logger'; import list from './list'; import { join } from 'path'; @@ -46,14 +46,14 @@ describe('kibana cli', function () { logger = new Logger(settings); sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); - rimraf.sync(pluginDir); + del.sync(pluginDir); mkdirSync(pluginDir, { recursive: true }); }); afterEach(function () { logger.log.restore(); logger.error.restore(); - rimraf.sync(pluginDir); + del.sync(pluginDir); }); it('list all of the folders in the plugin folder', function () { diff --git a/src/cli_plugin/remove/remove.js b/src/cli_plugin/remove/remove.js index 7aaccd8ca05fe..8432d0f44836b 100644 --- a/src/cli_plugin/remove/remove.js +++ b/src/cli_plugin/remove/remove.js @@ -20,7 +20,7 @@ import { statSync } from 'fs'; import { errorIfXPackRemove } from '../lib/error_if_x_pack'; -import rimraf from 'rimraf'; +import del from 'del'; export default function remove(settings, logger) { try { @@ -37,7 +37,7 @@ export default function remove(settings, logger) { } logger.log(`Removing ${settings.plugin}...`); - rimraf.sync(settings.pluginPath); + del.sync(settings.pluginPath); logger.log('Plugin removal complete'); } catch (err) { logger.error(`Unable to remove plugin because of error: "${err.message}"`); diff --git a/src/cli_plugin/remove/remove.test.js b/src/cli_plugin/remove/remove.test.js index 5d936d0278521..c063a713f47ac 100644 --- a/src/cli_plugin/remove/remove.test.js +++ b/src/cli_plugin/remove/remove.test.js @@ -19,7 +19,7 @@ import sinon from 'sinon'; import glob from 'glob-all'; -import rimraf from 'rimraf'; +import del from 'del'; import Logger from '../lib/logger'; import remove from './remove'; import { join } from 'path'; @@ -40,7 +40,7 @@ describe('kibana cli', function () { logger = new Logger(settings); sinon.stub(logger, 'log'); sinon.stub(logger, 'error'); - rimraf.sync(pluginDir); + del.sync(pluginDir); mkdirSync(pluginDir, { recursive: true }); }); @@ -48,7 +48,7 @@ describe('kibana cli', function () { processExitStub.restore(); logger.log.restore(); logger.error.restore(); - rimraf.sync(pluginDir); + del.sync(pluginDir); }); it('throw an error if the plugin is not installed.', function () { diff --git a/src/optimize/dynamic_dll_plugin/dll_compiler.js b/src/optimize/dynamic_dll_plugin/dll_compiler.js index 5b9dd2d04a550..3f3bb3e4e196c 100644 --- a/src/optimize/dynamic_dll_plugin/dll_compiler.js +++ b/src/optimize/dynamic_dll_plugin/dll_compiler.js @@ -25,13 +25,12 @@ import fs from 'fs'; import webpack from 'webpack'; import { promisify } from 'util'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; const readFileAsync = promisify(fs.readFile); const mkdirAsync = promisify(fs.mkdir); const existsAsync = promisify(fs.exists); const writeFileAsync = promisify(fs.writeFile); -const rimrafAsync = promisify(rimraf); export class DllCompiler { static getRawDllConfig(uiBundles = {}, babelLoaderCacheDir = '', threadLoaderPoolConfig = {}) { @@ -267,7 +266,7 @@ export class DllCompiler { // Delete the built dll, as it contains invalid modules, and reject listing // all the not allowed modules try { - await rimrafAsync(this.rawDllConfig.outputPath); + await del(this.rawDllConfig.outputPath); } catch (e) { return reject(e); } diff --git a/tasks/docker_docs.js b/tasks/docker_docs.js index 1c35f44eb6538..814a5a7e12bb9 100644 --- a/tasks/docker_docs.js +++ b/tasks/docker_docs.js @@ -17,7 +17,7 @@ * under the License. */ -import rimraf from 'rimraf'; +import del from 'del'; import { join } from 'path'; import { execFileSync as exec } from 'child_process'; @@ -46,7 +46,7 @@ export default function (grunt) { ], { env })).trim(); grunt.log.write('Clearing old docs ... '); - rimraf.sync(htmlDocsDir); + del.sync(htmlDocsDir); grunt.log.writeln('done'); grunt.log.write('Copying new docs ... '); diff --git a/x-pack/legacy/plugins/code/server/__tests__/clone_worker.ts b/x-pack/legacy/plugins/code/server/__tests__/clone_worker.ts index 09a039636bb4e..820075ede736c 100644 --- a/x-pack/legacy/plugins/code/server/__tests__/clone_worker.ts +++ b/x-pack/legacy/plugins/code/server/__tests__/clone_worker.ts @@ -7,7 +7,7 @@ import assert from 'assert'; import { delay } from 'bluebird'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import sinon from 'sinon'; import { prepareProjectByCloning as prepareProject } from '../test_utils'; import { CloneWorkerResult, Repository } from '../../model'; @@ -28,18 +28,14 @@ const esQueue = {}; const serverOptions = createTestServerOption(); const gitOps = new GitOperations(serverOptions.repoPath); -function cleanWorkspace() { - return new Promise(resolve => { - rimraf(serverOptions.workspacePath, resolve); - }); +async function cleanWorkspace() { + await del(serverOptions.workspacePath); } describe('clone_worker_tests', () => { // @ts-ignore before(async () => { - return new Promise(resolve => { - rimraf(serverOptions.repoPath, resolve); - }); + await del(serverOptions.repoPath); }); beforeEach(async function() { diff --git a/x-pack/legacy/plugins/code/server/__tests__/commit_indexer.ts b/x-pack/legacy/plugins/code/server/__tests__/commit_indexer.ts index c8fd117ec8a97..62eb06b6c792a 100644 --- a/x-pack/legacy/plugins/code/server/__tests__/commit_indexer.ts +++ b/x-pack/legacy/plugins/code/server/__tests__/commit_indexer.ts @@ -6,7 +6,7 @@ import assert from 'assert'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import sinon from 'sinon'; import { prepareProjectByCloning as prepareProject } from '../test_utils'; import { GitOperations } from '../git_operations'; @@ -36,10 +36,8 @@ const repoUri = 'github.com/elastic/TypeScript-Node-Starter'; const serverOptions = createTestServerOption(); const gitOps = new GitOperations(serverOptions.repoPath); -function cleanWorkspace() { - return new Promise(resolve => { - rimraf(serverOptions.workspacePath, resolve); - }); +async function cleanWorkspace() { + await del(serverOptions.workspacePath); } function setupEsClientSpy() { @@ -84,9 +82,7 @@ describe('Commit indexer unit tests', function(this: any) { // @ts-ignore before(async () => { - return new Promise(resolve => { - rimraf(serverOptions.repoPath, resolve); - }); + await del(serverOptions.repoPath); }); beforeEach(async function() { diff --git a/x-pack/legacy/plugins/code/server/__tests__/git_operations.ts b/x-pack/legacy/plugins/code/server/__tests__/git_operations.ts index 9391a8aafc131..8c2662041c7b1 100644 --- a/x-pack/legacy/plugins/code/server/__tests__/git_operations.ts +++ b/x-pack/legacy/plugins/code/server/__tests__/git_operations.ts @@ -9,7 +9,7 @@ import assert from 'assert'; import { execSync } from 'child_process'; import fs from 'fs'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import { GitOperations } from '../git_operations'; import { createTestServerOption } from '../test_utils'; import { prepareProjectByCloning as cloneProject, prepareProjectByInit } from '../test_utils'; @@ -40,7 +40,7 @@ describe('git_operations', () => { const headCommit = await g.getCommitInfo(repoUri, 'HEAD'); assert.strictEqual(headRevision, headCommit!.id); } finally { - rimraf.sync(repoDir); + del.sync(repoDir); } }); diff --git a/x-pack/legacy/plugins/code/server/__tests__/lsp_incremental_indexer.ts b/x-pack/legacy/plugins/code/server/__tests__/lsp_incremental_indexer.ts index aafdf8ebce85b..9e7801ba83ba0 100644 --- a/x-pack/legacy/plugins/code/server/__tests__/lsp_incremental_indexer.ts +++ b/x-pack/legacy/plugins/code/server/__tests__/lsp_incremental_indexer.ts @@ -6,7 +6,7 @@ import assert from 'assert'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import sinon from 'sinon'; import { DiffKind } from '../../common/git_diff'; @@ -42,10 +42,8 @@ const serverOptions = createTestServerOption(); const server = createTestHapiServer(); const gitOps = new GitOperations(serverOptions.repoPath); -function cleanWorkspace() { - return new Promise(resolve => { - rimraf(serverOptions.workspacePath, resolve); - }); +async function cleanWorkspace() { + await del(serverOptions.workspacePath); } function setupEsClientSpy() { @@ -109,9 +107,7 @@ function setupLsServiceSendRequestSpy(): sinon.SinonSpy { describe('LSP incremental indexer unit tests', () => { // @ts-ignore before(async () => { - return new Promise(resolve => { - rimraf(serverOptions.repoPath, resolve); - }); + await del(serverOptions.repoPath); }); beforeEach(async function() { diff --git a/x-pack/legacy/plugins/code/server/__tests__/lsp_indexer.ts b/x-pack/legacy/plugins/code/server/__tests__/lsp_indexer.ts index ec7e539d1912e..6cc6ff2972e7a 100644 --- a/x-pack/legacy/plugins/code/server/__tests__/lsp_indexer.ts +++ b/x-pack/legacy/plugins/code/server/__tests__/lsp_indexer.ts @@ -6,7 +6,7 @@ import assert from 'assert'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import sinon from 'sinon'; import { prepareProjectByCloning as prepareProject } from '../test_utils'; @@ -41,10 +41,8 @@ const serverOptions = createTestServerOption(); const server = createTestHapiServer(); const gitOps = new GitOperations(serverOptions.repoPath); -function cleanWorkspace() { - return new Promise(resolve => { - rimraf(serverOptions.workspacePath, resolve); - }); +async function cleanWorkspace() { + await del(serverOptions.workspacePath); } function setupEsClientSpy() { @@ -110,22 +108,18 @@ describe('LSP indexer unit tests', function(this: any) { // @ts-ignore before(async () => { - return new Promise(resolve => { - rimraf(serverOptions.repoPath, resolve); - }); + await del(serverOptions.repoPath); }); beforeEach(async function() { // @ts-ignore this.timeout(200000); - return await prepareProject( - `https://${repoUri}.git`, - path.join(serverOptions.repoPath, repoUri) - ); + await prepareProject(`https://${repoUri}.git`, path.join(serverOptions.repoPath, repoUri)); }); + // @ts-ignore - after(() => { - return cleanWorkspace(); + after(async () => { + await cleanWorkspace(); }); afterEach(() => { diff --git a/x-pack/legacy/plugins/code/server/__tests__/repository_service.ts b/x-pack/legacy/plugins/code/server/__tests__/repository_service.ts index b28b9650e2adf..4bbc39b803ece 100644 --- a/x-pack/legacy/plugins/code/server/__tests__/repository_service.ts +++ b/x-pack/legacy/plugins/code/server/__tests__/repository_service.ts @@ -9,7 +9,7 @@ import assert from 'assert'; import fs from 'fs'; import * as os from 'os'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import { RepositoryUtils } from '../../common/repository_utils'; import { RepositoryService } from '../repository_service'; import { ConsoleLogger } from '../utils/console_logger'; @@ -26,8 +26,9 @@ describe('repository service test', () => { }); // @ts-ignore after(() => { - return rimraf.sync(baseDir); + del.sync(baseDir); }); + const service = new RepositoryService(repoDir, credsDir, log); it('can not clone a repo by ssh without a key', async () => { diff --git a/x-pack/legacy/plugins/code/server/__tests__/workspace_handler.ts b/x-pack/legacy/plugins/code/server/__tests__/workspace_handler.ts index 0f1245b135076..8369d07c2d69b 100644 --- a/x-pack/legacy/plugins/code/server/__tests__/workspace_handler.ts +++ b/x-pack/legacy/plugins/code/server/__tests__/workspace_handler.ts @@ -8,7 +8,7 @@ import path from 'path'; import assert from 'assert'; import * as os from 'os'; -import rimraf from 'rimraf'; +import del from 'del'; import { ResponseMessage } from 'vscode-jsonrpc/lib/messages'; import { LspRequest } from '../../model'; @@ -163,6 +163,6 @@ describe('workspace_handler tests', () => { // @ts-ignore after(() => { - rimraf.sync(baseDir); + del.sync(baseDir); }); }); diff --git a/x-pack/legacy/plugins/code/server/lsp/controller.test.ts b/x-pack/legacy/plugins/code/server/lsp/controller.test.ts index 212381b36ca6e..34cb2a3302c2f 100644 --- a/x-pack/legacy/plugins/code/server/lsp/controller.test.ts +++ b/x-pack/legacy/plugins/code/server/lsp/controller.test.ts @@ -7,7 +7,7 @@ import fs from 'fs'; import * as os from 'os'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import sinon from 'sinon'; import { LanguageServerStatus } from '../../common/language_server'; @@ -109,7 +109,7 @@ beforeEach(async () => { ); }); afterAll(() => { - rimraf.sync(baseDir); + del.sync(baseDir, { force: true }); }); function mockRequest(repo: string, file: string) { diff --git a/x-pack/legacy/plugins/code/server/lsp/install_manager.test.ts b/x-pack/legacy/plugins/code/server/lsp/install_manager.test.ts index 6aa80899a7008..6fdfb37ca9a6c 100644 --- a/x-pack/legacy/plugins/code/server/lsp/install_manager.test.ts +++ b/x-pack/legacy/plugins/code/server/lsp/install_manager.test.ts @@ -9,7 +9,7 @@ import fs from 'fs'; import { Server } from 'hapi'; import os from 'os'; import path from 'path'; -import rimraf from 'rimraf'; +import del from 'del'; import { LanguageServers } from './language_servers'; import { InstallManager } from './install_manager'; @@ -46,7 +46,7 @@ beforeAll(() => { }); afterAll(() => { - rimraf.sync(fakeTestDir); + del.sync(fakeTestDir, { force: true }); }); test('install language server by plugin', async () => { diff --git a/x-pack/legacy/plugins/code/server/lsp/request_expander.test.ts b/x-pack/legacy/plugins/code/server/lsp/request_expander.test.ts index cf3999ec244f5..1a3f8fd9e2988 100644 --- a/x-pack/legacy/plugins/code/server/lsp/request_expander.test.ts +++ b/x-pack/legacy/plugins/code/server/lsp/request_expander.test.ts @@ -5,7 +5,7 @@ */ import fs from 'fs'; -import rimraf from 'rimraf'; +import del from 'del'; import sinon from 'sinon'; import { pathToFileURL } from 'url'; @@ -25,10 +25,8 @@ beforeEach(async () => { } }); -afterEach(() => { - return new Promise(resolve => { - rimraf(options.workspacePath, resolve); - }); +afterEach(async () => { + await del(options.workspacePath, { force: true }); }); function createMockProxy(initDelay: number = 0, requestDelay: number = 0) { diff --git a/x-pack/legacy/plugins/code/server/lsp/test_repo_manager.ts b/x-pack/legacy/plugins/code/server/lsp/test_repo_manager.ts index 8c0594a0f1851..e2f01dd09554d 100644 --- a/x-pack/legacy/plugins/code/server/lsp/test_repo_manager.ts +++ b/x-pack/legacy/plugins/code/server/lsp/test_repo_manager.ts @@ -3,10 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -/* eslint-disable no-console */ import fs from 'fs'; -import rimraf from 'rimraf'; +import del from 'del'; import { TestConfig, Repo } from '../../model/test_config'; import { prepareProjectByCloning } from '../test_utils'; @@ -25,19 +24,15 @@ export class TestRepoManager { } public async cleanAllRepos() { - this.repos.forEach(repo => { - this.cleanRepo(repo.path); - }); + for (const repo of this.repos) { + await this.cleanRepo(repo.path); + } } - public async cleanRepo(path: string) { - return new Promise(resolve => { - if (fs.existsSync(path)) { - rimraf(path, resolve); - } else { - resolve(true); - } - }); + private async cleanRepo(path: string) { + if (fs.existsSync(path)) { + await del(path); + } } public getRepo(language: string): Repo { diff --git a/x-pack/legacy/plugins/code/server/lsp/workspace_handler.test.ts b/x-pack/legacy/plugins/code/server/lsp/workspace_handler.test.ts index d959eda2aa6dc..14b5249de5e22 100644 --- a/x-pack/legacy/plugins/code/server/lsp/workspace_handler.test.ts +++ b/x-pack/legacy/plugins/code/server/lsp/workspace_handler.test.ts @@ -7,7 +7,7 @@ import fs from 'fs'; import path from 'path'; import * as os from 'os'; -import rimraf from 'rimraf'; +import del from 'del'; import { ResponseMessage } from 'vscode-jsonrpc/lib/messages'; import { LspRequest } from '../../model'; @@ -143,5 +143,5 @@ beforeAll(() => { }); afterAll(() => { - rimraf.sync(baseDir); + del.sync(baseDir, { force: true }); }); diff --git a/x-pack/legacy/plugins/code/server/test_utils.ts b/x-pack/legacy/plugins/code/server/test_utils.ts index 6276515fae1b6..c08ac1317a256 100644 --- a/x-pack/legacy/plugins/code/server/test_utils.ts +++ b/x-pack/legacy/plugins/code/server/test_utils.ts @@ -10,23 +10,20 @@ import * as os from 'os'; import path from 'path'; import { simplegit } from '@elastic/simple-git/dist'; -import rimraf from 'rimraf'; +import del from 'del'; import { AnyObject } from './lib/esqueue'; import { ServerOptions } from './server_options'; import { ServerFacade } from '..'; -export function prepareProjectByCloning(url: string, p: string) { - return new Promise(resolve => { - if (!fs.existsSync(p)) { - rimraf(p, error => { - fs.mkdirSync(p, { recursive: true }); - const git = simplegit(p); - git.clone(url, p, ['--bare']).then(resolve); - }); - } else { - resolve(); - } - }); +export async function prepareProjectByCloning(url: string, p: string) { + if (fs.existsSync(p)) { + return; + } + + await del(p); + fs.mkdirSync(p, { recursive: true }); + const git = simplegit(p); + return await git.clone(url, p, ['--bare']); } export async function prepareProjectByInit( diff --git a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts index 50bed7a8edb64..f16485537f53a 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/chromium/driver_factory/index.ts @@ -13,7 +13,7 @@ import { ConsoleMessage, Request as PuppeteerRequest, } from 'puppeteer'; -import rimraf from 'rimraf'; +import del from 'del'; import * as Rx from 'rxjs'; import { ignoreElements, mergeMap, tap } from 'rxjs/operators'; import { InnerSubscriber } from 'rxjs/internal/InnerSubscriber'; @@ -166,12 +166,8 @@ export class HeadlessChromiumDriverFactory { this.logger.debug(`deleting chromium user data directory at [${userDataDir}]`); // the unsubscribe function isn't `async` so we're going to make our best effort at // deleting the userDataDir and if it fails log an error. - rimraf(userDataDir, err => { - if (err) { - return this.logger.error( - `error deleting user data directory at [${userDataDir}]: [${err}]` - ); - } + del(userDataDir).catch(error => { + this.logger.error(`error deleting user data directory at [${userDataDir}]: [${error}]`); }); }); }); diff --git a/x-pack/legacy/plugins/reporting/server/browsers/download/clean.ts b/x-pack/legacy/plugins/reporting/server/browsers/download/clean.ts index 394b76d772531..4355a6a0a1773 100644 --- a/x-pack/legacy/plugins/reporting/server/browsers/download/clean.ts +++ b/x-pack/legacy/plugins/reporting/server/browsers/download/clean.ts @@ -7,8 +7,7 @@ import { readdirSync } from 'fs'; import { resolve as resolvePath } from 'path'; -import { fromNode as fcb } from 'bluebird'; -import rimraf from 'rimraf'; +import del from 'del'; import { log, asyncMap } from './util'; @@ -32,7 +31,7 @@ export async function clean(dir: string, expectedPaths: string[]) { const path = resolvePath(dir, filename); if (!expectedPaths.includes(path)) { log(`Deleting unexpected file ${path}`); - await fcb(cb => rimraf(path, cb)); + await del(path); } }); } diff --git a/x-pack/package.json b/x-pack/package.json index f58496361b482..4d1e6f52411a3 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -98,7 +98,6 @@ "@types/recompose": "^0.30.6", "@types/reduce-reducers": "^0.3.0", "@types/redux-actions": "^2.2.1", - "@types/rimraf": "^2.0.2", "@types/sinon": "^7.0.13", "@types/storybook__addon-actions": "^3.4.3", "@types/storybook__addon-info": "^4.1.2", @@ -128,7 +127,6 @@ "commander": "3.0.0", "copy-webpack-plugin": "^5.0.4", "cypress": "^3.4.1", - "del": "^4.1.1", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.14.0", "enzyme-adapter-utils": "^1.12.0", @@ -245,6 +243,7 @@ "d3-scale": "1.0.7", "dataloader": "^1.4.0", "dedent": "^0.7.0", + "del": "^5.1.0", "dragselect": "1.13.1", "elasticsearch": "^16.4.0", "extract-zip": "1.6.7", @@ -351,7 +350,6 @@ "request": "^2.88.0", "reselect": "3.0.1", "resize-observer-polyfill": "^1.5.0", - "rimraf": "^2.7.1", "rison-node": "0.3.1", "rxjs": "^6.2.1", "semver": "5.7.0", diff --git a/yarn.lock b/yarn.lock index 744ea2c22a44a..dd12623b1bd23 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3987,14 +3987,6 @@ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.10.2.tgz#bd1740c4ad51966609b058803ee6874577848b37" integrity sha512-LqJkY4VQ7S09XhI7kA3ON71AxauROhSv74639VsNXC9ish4IWHnIi98if+nP1MxQV3RMPqXSCYgpPsDHjlg9UQ== -"@types/rimraf@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" - integrity sha512-Hm/bnWq0TCy7jmjeN5bKYij9vw5GrDFWME4IuxV08278NtU/VdGbzsBohcCUJ7+QMqmUq5hpRKB39HeQWJjztQ== - dependencies: - "@types/glob" "*" - "@types/node" "*" - "@types/selenium-webdriver@^4.0.3": version "4.0.3" resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.0.3.tgz#388f12c464cc1fff5d4c84cb372f19b9ab9b5c81" @@ -10003,6 +9995,14 @@ defined@~1.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= +del-cli@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/del-cli/-/del-cli-3.0.0.tgz#327a15d4c18d6b7e5c849a53ef0d17901bc28197" + integrity sha512-J4HDC2mpcN5aopya4VdkyiFXZaqAoo7ua9VpKbciX3DDUSbtJbPMc3ivggJsAAgS6EqonmbenIiMhBGtJPW9FA== + dependencies: + del "^5.1.0" + meow "^5.0.0" + del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -24719,7 +24719,7 @@ rimraf@2.6.3, rimraf@^2.6.3, rimraf@~2.6.2: dependencies: glob "^7.1.3" -rimraf@2.7.1, rimraf@^2.7.1: +rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== From d9133c1327df3bef81f00f591b54f79e53b008cf Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 24 Oct 2019 15:48:13 +0100 Subject: [PATCH 119/191] [ML] Fixing filtering of categorization fields (#49184) --- .../common/job_creator/util/general.ts | 5 +- .../components/time_field/time_field.tsx | 4 +- .../time_field/time_field_select.tsx | 8 +-- .../categorization_field.tsx | 4 +- .../categorization_field_select.tsx | 10 +--- .../services/new_job_capabilities_service.ts | 51 +++++++++++++++---- 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/general.ts b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/general.ts index 10a9260598dea..71535ab98c74f 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/general.ts +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/common/job_creator/util/general.ts @@ -77,10 +77,9 @@ export function getRichDetectors( }); } -export function createFieldOptions(fields: Field[], filterOverride?: (f: Field) => boolean) { - const filter = filterOverride || (f => f.id !== EVENT_RATE_FIELD_ID); +export function createFieldOptions(fields: Field[]) { return fields - .filter(filter) + .filter(f => f.id !== EVENT_RATE_FIELD_ID) .map(f => ({ label: f.name, })) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field.tsx index 71e48a7afb359..86005dd140fed 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field.tsx @@ -15,7 +15,7 @@ import { Description } from './description'; export const TimeField: FC = () => { const { jobCreator: jc, jobCreatorUpdate, jobCreatorUpdated } = useContext(JobCreatorContext); const jobCreator = jc as AdvancedJobCreator; - const { fields } = newJobCapsService; + const { dateFields } = newJobCapsService; const [timeFieldName, setTimeFieldName] = useState(jobCreator.timeFieldName); useEffect(() => { @@ -30,7 +30,7 @@ export const TimeField: FC = () => { return ( diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx index d81ceca567313..3b1993f8e2c7e 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/datafeed_step/components/time_field/time_field_select.tsx @@ -7,8 +7,7 @@ import React, { FC } from 'react'; import { EuiComboBox, EuiComboBoxOptionProps } from '@elastic/eui'; -import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../../common/types/fields'; -import { ES_FIELD_TYPES } from '../../../../../../../../../../../../src/plugins/data/public'; +import { Field } from '../../../../../../../../common/types/fields'; import { createFieldOptions } from '../../../../../common/job_creator/util/general'; interface Props { @@ -18,10 +17,7 @@ interface Props { } export const TimeFieldSelect: FC = ({ fields, changeHandler, selectedField }) => { - const options: EuiComboBoxOptionProps[] = createFieldOptions( - fields, - f => f.id !== EVENT_RATE_FIELD_ID && f.type === ES_FIELD_TYPES.DATE - ); + const options: EuiComboBoxOptionProps[] = createFieldOptions(fields); const selection: EuiComboBoxOptionProps[] = []; if (selectedField !== null) { diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field.tsx index 996fa8cd3f862..f9edf79364c97 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field.tsx @@ -19,7 +19,7 @@ import { Description } from './description'; export const CategorizationField: FC = () => { const { jobCreator: jc, jobCreatorUpdate, jobCreatorUpdated } = useContext(JobCreatorContext); const jobCreator = jc as MultiMetricJobCreator | PopulationJobCreator | AdvancedJobCreator; - const { fields } = newJobCapsService; + const { catFields } = newJobCapsService; const [categorizationFieldName, setCategorizationFieldName] = useState( jobCreator.categorizationFieldName ); @@ -36,7 +36,7 @@ export const CategorizationField: FC = () => { return ( diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx index 9d9972a0b533a..f9fdba31a0ad4 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/categorization_field/categorization_field_select.tsx @@ -8,8 +8,7 @@ import React, { FC, useContext } from 'react'; import { EuiComboBox, EuiComboBoxOptionProps } from '@elastic/eui'; import { JobCreatorContext } from '../../../job_creator_context'; -import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../../common/types/fields'; -import { ES_FIELD_TYPES } from '../../../../../../../../../../../../src/plugins/data/public'; +import { Field } from '../../../../../../../../common/types/fields'; import { createFieldOptions, createScriptFieldOptions, @@ -24,12 +23,7 @@ interface Props { export const CategorizationFieldSelect: FC = ({ fields, changeHandler, selectedField }) => { const { jobCreator } = useContext(JobCreatorContext); const options: EuiComboBoxOptionProps[] = [ - ...createFieldOptions( - fields, - f => - f.id !== EVENT_RATE_FIELD_ID && - (f.type === ES_FIELD_TYPES.KEYWORD || f.type === ES_FIELD_TYPES.TEXT) - ), + ...createFieldOptions(fields), ...createScriptFieldOptions(jobCreator.scriptFields), ]; diff --git a/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts b/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts index f404d23618cef..ded9aa410766e 100644 --- a/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts +++ b/x-pack/legacy/plugins/ml/public/services/new_job_capabilities_service.ts @@ -51,6 +51,8 @@ const categoryFieldTypes = [ES_FIELD_TYPES.TEXT, ES_FIELD_TYPES.KEYWORD, ES_FIEL class NewJobCapsService { private _fields: Field[] = []; + private _catFields: Field[] = []; + private _dateFields: Field[] = []; private _aggs: Aggregation[] = []; private _includeEventRateField: boolean = true; private _removeTextFields: boolean = true; @@ -59,6 +61,14 @@ class NewJobCapsService { return this._fields; } + public get catFields(): Field[] { + return this._catFields; + } + + public get dateFields(): Field[] { + return this._dateFields; + } + public get aggs(): Aggregation[] { return this._aggs; } @@ -84,16 +94,28 @@ class NewJobCapsService { this._removeTextFields = removeTextFields; const resp = await ml.jobs.newJobCaps(indexPattern.title, indexPattern.type === 'rollup'); - const { fields, aggs } = createObjects(resp, indexPattern.title); + const { fields: allFields, aggs } = createObjects(resp, indexPattern.title); if (this._includeEventRateField === true) { - addEventRateField(aggs, fields); + addEventRateField(aggs, allFields); } - // remove any text fields which have a keyword equivalents - const processedFields = this._removeTextFields ? processTextFields(fields) : fields; - - this._fields = processedFields; + const { fieldsPreferringKeyword, fieldsPreferringText } = processTextAndKeywordFields( + allFields + ); + const catFields = fieldsPreferringText.filter( + f => f.type === ES_FIELD_TYPES.KEYWORD || f.type === ES_FIELD_TYPES.TEXT + ); + const dateFields = fieldsPreferringText.filter(f => f.type === ES_FIELD_TYPES.DATE); + const fields = this._removeTextFields ? fieldsPreferringKeyword : allFields; + + // set the main fields list to contain fields which have been filtered to prefer + // keyword fields over text fields. + // e.g. if foo.keyword and foo exist, don't add foo to the list. + this._fields = fields; + // set the category fields to contain fields which have been filtered to prefer text fields. + this._catFields = catFields; + this._dateFields = dateFields; this._aggs = aggs; } catch (error) { console.error('Unable to load new job capabilities', error); // eslint-disable-line no-console @@ -204,14 +226,25 @@ function addEventRateField(aggs: Aggregation[], fields: Field[]) { fields.splice(0, 0, eventRateField); } -// remove fields which are text and have a keyword equivalent -function processTextFields(fields: Field[]) { +// create two lists, one removing text fields if there are keyword equivalents and vice versa +function processTextAndKeywordFields(fields: Field[]) { const keywordIds = fields.filter(f => f.type === ES_FIELD_TYPES.KEYWORD).map(f => f.id); - return fields.filter( + const textIds = fields.filter(f => f.type === ES_FIELD_TYPES.TEXT).map(f => f.id); + + const fieldsPreferringKeyword = fields.filter( f => f.type !== ES_FIELD_TYPES.TEXT || (f.type === ES_FIELD_TYPES.TEXT && keywordIds.includes(`${f.id}.keyword`) === false) ); + + const fieldsPreferringText = fields.filter( + f => + f.type !== ES_FIELD_TYPES.KEYWORD || + (f.type === ES_FIELD_TYPES.KEYWORD && + textIds.includes(f.id.replace(/\.keyword$/, '')) === false) + ); + + return { fieldsPreferringKeyword, fieldsPreferringText }; } export const newJobCapsService = new NewJobCapsService(); From 841abd1162f1eb6aaebf27d004c92e8344636d91 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 24 Oct 2019 10:50:19 -0400 Subject: [PATCH 120/191] [a11y] fix page heading structure in management apps (#48936) --- .../application/containers/main/main.tsx | 10 +++++++- .../components/cold_phase/cold_phase.js | 8 +++---- .../components/delete_phase/delete_phase.js | 4 ++-- .../components/hot_phase/hot_phase.js | 4 ++-- .../components/set_priority_input.js | 4 ++-- .../components/warm_phase/warm_phase.js | 12 +++++----- .../sections/edit_policy/edit_policy.js | 6 ++--- .../template_form/steps/step_aliases.tsx | 4 ++-- .../template_form/steps/step_logistics.tsx | 6 ++--- .../template_form/steps/step_mappings.tsx | 4 ++-- .../template_form/steps/step_review.tsx | 4 ++-- .../template_form/steps/step_settings.tsx | 4 ++-- .../__snapshots__/license_status.test.js.snap | 4 ++-- .../license_status/license_status.js | 2 +- .../sections/job_create/job_create.js | 2 +- .../job_create/steps/step_date_histogram.js | 4 ++-- .../job_create/steps/step_histogram.js | 8 +++---- .../job_create/steps/step_logistics.js | 24 +++++++++---------- .../sections/job_create/steps/step_metrics.js | 4 ++-- .../sections/job_create/steps/step_review.js | 4 ++-- .../sections/job_create/steps/step_terms.js | 4 ++-- .../policy_form/steps/step_logistics.tsx | 4 ++-- .../policy_form/steps/step_retention.tsx | 4 ++-- .../policy_form/steps/step_review.tsx | 4 ++-- .../policy_form/steps/step_settings.tsx | 4 ++-- .../components/repository_form/step_one.tsx | 12 +++++----- .../steps/step_logistics.tsx | 4 ++-- .../steps/step_review.tsx | 4 ++-- .../steps/step_settings.tsx | 4 ++-- .../json_watch_edit_simulate.tsx | 16 ++++++------- .../threshold_watch_action_panel.tsx | 4 ++-- .../threshold_watch_edit.tsx | 4 ++-- 32 files changed, 99 insertions(+), 91 deletions(-) diff --git a/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx index 82256cf739882..4e5afbdb5821e 100644 --- a/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx +++ b/src/legacy/core_plugins/console/np_ready/public/application/containers/main/main.tsx @@ -19,7 +19,8 @@ import React, { useCallback, useState } from 'react'; import { debounce } from 'lodash'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { EditorOutput, Editor, ConsoleHistory } from '../editor'; import { Settings } from '../settings'; @@ -77,6 +78,13 @@ export function Main() { responsive={false} > + +

+ {i18n.translate('console.pageHeading', { + defaultMessage: 'Console', + })} +

+
setShowHistory(!showingHistory), diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js index 493da3e19b9f3..91fbb4f63cbc3 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js @@ -58,12 +58,12 @@ export class ColdPhase extends PureComponent { - +

- {' '} +

{' '} {phaseData[PHASE_ENABLED] && !isShowingErrors ? : null}
@@ -162,12 +162,12 @@ export class ColdPhase extends PureComponent { +

-

+

} description={ diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js index 0e7663a6aef7d..d5eb76889494c 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js @@ -43,12 +43,12 @@ export class DeletePhase extends PureComponent { - +

- {' '} +

{' '} {phaseData[PHASE_ENABLED] && !isShowingErrors ? ( ) : null} diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js index 69370ab2d0a38..e7ac890a20ebc 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js @@ -54,12 +54,12 @@ export class HotPhase extends PureComponent { - +

- {' '} +

{' '} {isShowingErrors ? null : } diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js index 3f4c32b05a2dc..c2c2b002a7693 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/set_priority_input.js @@ -21,12 +21,12 @@ export const SetPriorityInput = props => { return ( +

-

+

} description={ diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js index 2f88578e128ef..77afd4f7051dc 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js @@ -77,12 +77,12 @@ export class WarmPhase extends PureComponent { - +

- {' '} +

{' '} {phaseData[PHASE_ENABLED] && !isShowingErrors ? : null} @@ -202,12 +202,12 @@ export class WarmPhase extends PureComponent { +

-

+

} description={ @@ -270,12 +270,12 @@ export class WarmPhase extends PureComponent {
+

-

+

} description={ diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js index 2b07e9615030f..ef9b6de84f1e4 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js @@ -157,8 +157,8 @@ export class EditPolicy extends Component { verticalPosition="center" horizontalPosition="center" > - -

+ +

{isNewPolicy ? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', { defaultMessage: 'Create an index lifecycle policy' @@ -167,7 +167,7 @@ export class EditPolicy extends Component { defaultMessage: 'Edit index lifecycle policy {originalPolicyName}', values: { originalPolicyName } })} -

+

diff --git a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_aliases.tsx b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_aliases.tsx index 6c7a5a0ce922c..96abbae93d0f4 100644 --- a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_aliases.tsx +++ b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_aliases.tsx @@ -39,12 +39,12 @@ export const StepAliases: React.FunctionComponent = ({ -

+

-

+
diff --git a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_logistics.tsx b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_logistics.tsx index 1b20da3a0ee4c..86ef102dcec44 100644 --- a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_logistics.tsx +++ b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_logistics.tsx @@ -22,7 +22,7 @@ import { schemas } from '../template_form_schemas'; // Create or Form components with partial props that are common to all instances const UseField = getUseField({ component: Field }); -const FormRow = getFormRow({ titleTag: 'h4' }); +const FormRow = getFormRow({ titleTag: 'h3' }); const fieldsMeta = { name: { @@ -97,12 +97,12 @@ export const StepLogistics: React.FunctionComponent = ({ -

+

-

+
diff --git a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_mappings.tsx b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_mappings.tsx index 17d4a06418a70..74cb09b1c8e69 100644 --- a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_mappings.tsx +++ b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_mappings.tsx @@ -39,12 +39,12 @@ export const StepMappings: React.FunctionComponent = ({ -

+

-

+
diff --git a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_review.tsx b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_review.tsx index a639785c3837c..2c7fe939cc759 100644 --- a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_review.tsx +++ b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_review.tsx @@ -188,13 +188,13 @@ export const StepReview: React.FunctionComponent = ({ template, updat return (
-

+

-

+
diff --git a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_settings.tsx b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_settings.tsx index 850f312f0d1c6..9509ca38003ba 100644 --- a/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_settings.tsx +++ b/x-pack/legacy/plugins/index_management/public/components/template_form/steps/step_settings.tsx @@ -39,12 +39,12 @@ export const StepSettings: React.FunctionComponent = ({ -

+

-

+
diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap index ee9abb1d1f125..b0bd05349a50c 100644 --- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap +++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/license_status.test.js.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`LicenseStatus component should display display warning is expired 1`] = `"

Your Platinum license has expired

Your license expired on
"`; +exports[`LicenseStatus component should display display warning is expired 1`] = `"

Your Platinum license has expired

Your license expired on
"`; -exports[`LicenseStatus component should display normally when license is active 1`] = `"

Your Gold license is active

Your license will expire on October 12, 2099 7:00 PM EST
"`; +exports[`LicenseStatus component should display normally when license is active 1`] = `"

Your Gold license is active

Your license will expire on October 12, 2099 7:00 PM EST
"`; diff --git a/x-pack/legacy/plugins/license_management/public/sections/license_dashboard/license_status/license_status.js b/x-pack/legacy/plugins/license_management/public/sections/license_dashboard/license_status/license_status.js index 9f6d1226e4dbf..0b7867ba45e2a 100644 --- a/x-pack/legacy/plugins/license_management/public/sections/license_dashboard/license_status/license_status.js +++ b/x-pack/legacy/plugins/license_management/public/sections/license_dashboard/license_status/license_status.js @@ -87,7 +87,7 @@ export class LicenseStatus extends React.PureComponent { {icon} -

{title}

+

{title}

diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.js index 3e7d5603ca95b..1d7d0c1dd8dea 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.js +++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/job_create.js @@ -549,7 +549,7 @@ export class JobCreateUi extends Component { - +

-

+

-

+

diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js index 991280b4e10de..38aac71c86a23 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js +++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_histogram.js @@ -82,12 +82,12 @@ export class StepHistogramUi extends Component { -

+

-

+
@@ -179,12 +179,12 @@ export class StepHistogramUi extends Component { -

+

-

+
)} description={( diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js index c3cf39bec5fad..75c70ab6ce20a 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js +++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_logistics.js @@ -233,12 +233,12 @@ export class StepLogisticsUi extends Component { -

+

-

+
@@ -276,12 +276,12 @@ export class StepLogisticsUi extends Component { -

+

-

+ } description={ @@ -316,12 +316,12 @@ export class StepLogisticsUi extends Component { -

+

-

+ } description={ @@ -393,12 +393,12 @@ export class StepLogisticsUi extends Component { -

+

-

+ } description={ @@ -415,12 +415,12 @@ export class StepLogisticsUi extends Component { -
+

-

+ } description={ @@ -456,12 +456,12 @@ export class StepLogisticsUi extends Component { -
+

-

+ } description={ diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js index 7fd4052bd45f1..1ccdcceabe47a 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js +++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_metrics.js @@ -358,12 +358,12 @@ export class StepMetricsUi extends Component { -

+

-

+
diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js index 213a1938432fc..1f3172d8ee848 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js +++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_review.js @@ -104,13 +104,13 @@ export class StepReviewUi extends Component { return ( -

+

-

+
{this.renderTabs()} diff --git a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js index d4a07dd312483..6ea8607aa9632 100644 --- a/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js +++ b/x-pack/legacy/plugins/rollup/public/crud_app/sections/job_create/steps/step_terms.js @@ -81,12 +81,12 @@ export class StepTermsUi extends Component { -

+

-

+
diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_logistics.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_logistics.tsx index 80240ae0e7718..7c3036b3d79c2 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_logistics.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_logistics.tsx @@ -476,12 +476,12 @@ export const PolicyStepLogistics: React.FunctionComponent = ({ -

+

-

+
diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_retention.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_retention.tsx index 3944cd52c7ee2..c88cbd2736df6 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_retention.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_retention.tsx @@ -206,12 +206,12 @@ export const PolicyStepRetention: React.FunctionComponent = ({ -

+

-

+
diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_review.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_review.tsx index 52667ee7ebc87..3ddbcd94009ac 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_review.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/policy_form/steps/step_review.tsx @@ -362,12 +362,12 @@ export const PolicyStepReview: React.FunctionComponent = ({ return ( -

+

-

+
= ({ -

+

-

+
diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/step_one.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/step_one.tsx index d8cf346dcdc43..8f6b465b2fe5f 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/step_one.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/repository_form/step_one.tsx @@ -88,12 +88,12 @@ export const RepositoryFormStepOne: React.FunctionComponent = ({ -

+

-

+ } description={ @@ -227,12 +227,12 @@ export const RepositoryFormStepOne: React.FunctionComponent = ({ return ( -

+

-

+
@@ -274,12 +274,12 @@ export const RepositoryFormStepOne: React.FunctionComponent = ({ -

+

-

+ } description={ diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_logistics.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_logistics.tsx index 8a0d8039bb7cd..f5a3180adbd6e 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_logistics.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_logistics.tsx @@ -96,12 +96,12 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = -

+

-

+
diff --git a/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_review.tsx b/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_review.tsx index 65a3918d29940..92b0ee48fef01 100644 --- a/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_review.tsx +++ b/x-pack/legacy/plugins/snapshot_restore/public/app/components/restore_snapshot_form/steps/step_review.tsx @@ -350,12 +350,12 @@ export const RestoreSnapshotStepReview: React.FunctionComponent = ({ return ( -

+

-

+
= ( -

+

-

+
diff --git a/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx b/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx index 5d16ac3aa18f0..e57a875aa4356 100644 --- a/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx +++ b/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx @@ -158,12 +158,12 @@ export const JsonWatchEditSimulate = ({ +

{i18n.translate( 'xpack.watcher.sections.watchEdit.simulate.form.triggerOverridesTitle', { defaultMessage: 'Trigger' } )} -

+ } description={i18n.translate( 'xpack.watcher.sections.watchEdit.simulate.form.triggerOverridesDescription', @@ -247,12 +247,12 @@ export const JsonWatchEditSimulate = ({ +

{i18n.translate( 'xpack.watcher.sections.watchEdit.simulate.form.conditionOverridesTitle', { defaultMessage: 'Condition' } )} -

+ } description={i18n.translate( 'xpack.watcher.sections.watchEdit.simulate.form.conditionOverridesDescription', @@ -283,12 +283,12 @@ export const JsonWatchEditSimulate = ({ fullWidth idAria="simulateExecutionActionModesDescription" title={ -

+

{i18n.translate( 'xpack.watcher.sections.watchEdit.simulate.form.actionOverridesTitle', { defaultMessage: 'Actions' } )} -

+ } description={ +

{i18n.translate( 'xpack.watcher.sections.watchEdit.simulate.form.inputOverridesTitle', { defaultMessage: 'Input' } )} -

+ } description={i18n.translate( 'xpack.watcher.sections.watchEdit.simulate.form.inputOverridesDescription', diff --git a/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_panel.tsx b/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_panel.tsx index 504c5e10ed665..a2e46652429ea 100644 --- a/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_panel.tsx +++ b/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/threshold_watch_edit/threshold_watch_action_panel.tsx @@ -29,7 +29,7 @@ export const WatchActionsPanel: React.FunctionComponent = ({ actionErrors -

+

{i18n.translate('xpack.watcher.sections.watchEdit.actions.title', { defaultMessage: 'Perform {watchActionsCount, plural, one{# action} other {# actions}} when condition is met', @@ -37,7 +37,7 @@ export const WatchActionsPanel: React.FunctionComponent = ({ actionErrors watchActionsCount: watch.actions.length, }, })} -

+
diff --git a/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx b/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx index c479cad1bc825..ee89d9bfc176a 100644 --- a/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx +++ b/x-pack/legacy/plugins/watcher/public/sections/watch_edit/components/threshold_watch_edit/threshold_watch_edit.tsx @@ -441,12 +441,12 @@ export const ThresholdWatchEdit = ({ pageTitle }: { pageTitle: string }) => { {shouldShowThresholdExpression ? ( -

+

-

+
From 9e58b27d59cc8f632c927b624dfa944153fbc407 Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 24 Oct 2019 10:14:17 -0500 Subject: [PATCH 121/191] Upgrade EUI to 14.7.0 (#49110) * eui 14.7.0 * icon updates * snapshot updates * storyshot updates * remove config addition --- package.json | 2 +- .../plugins/kbn_tp_run_pipeline/package.json | 2 +- .../kbn_tp_custom_visualizations/package.json | 2 +- .../kbn_tp_embeddable_explorer/package.json | 2 +- .../kbn_tp_sample_panel_action/package.json | 2 +- .../kbn_tp_visualize_embedding/package.json | 2 +- .../__test__/__snapshots__/List.test.tsx.snap | 167 ++++++++++++++++-- .../ServiceOverview.test.tsx.snap | 8 +- .../TransactionActionMenu.tsx | 14 +- .../__snapshots__/asset.examples.storyshot | 22 +-- .../__snapshots__/file_tree.test.tsx.snap | 12 -- .../__snapshots__/symbol_tree.test.tsx.snap | 12 -- x-pack/legacy/plugins/infra/index.ts | 6 +- .../metrics_explorer/chart_context_menu.tsx | 4 +- .../plugins/infra/public/register_feature.ts | 4 +- .../plugins/infra/server/kibana.index.ts | 4 +- .../modules/logs_ui_analysis/logo.json | 2 +- .../logs/__snapshots__/logs.test.js.snap | 8 +- .../monitoring/public/components/logs/logs.js | 2 +- .../report_listing.test.tsx.snap | 50 ++++++ .../integration_group.test.tsx.snap | 24 +-- .../functional/integration_group.tsx | 12 +- .../functional/integration_link.tsx | 2 +- .../watcher/common/types/action_types.ts | 2 +- .../public/models/action/logging_action.js | 2 +- x-pack/package.json | 2 +- yarn.lock | 8 +- 27 files changed, 275 insertions(+), 104 deletions(-) diff --git a/package.json b/package.json index 63f780fe21da1..d64307ade9247 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "@elastic/charts": "^13.5.7", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", - "@elastic/eui": "14.5.0", + "@elastic/eui": "14.7.0", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.3.3", diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json index 68641c2fd6b1f..21b49a9823f62 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.5.0", + "@elastic/eui": "14.7.0", "react": "^16.8.0", "react-dom": "^16.8.0" } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json index a03849129192f..7aacfbc22ceee 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.5.0", + "@elastic/eui": "14.7.0", "react": "^16.8.0" } } diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json index 18b14516b9be4..80ec89fb0078a 100644 --- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json +++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.5.0", + "@elastic/eui": "14.7.0", "react": "^16.8.0" }, "scripts": { diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json index b147da6a448ae..54aba07079eeb 100644 --- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json +++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json @@ -8,7 +8,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.5.0", + "@elastic/eui": "14.7.0", "react": "^16.8.0" }, "scripts": { diff --git a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json b/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json index 10f122823353c..121f69ada329b 100644 --- a/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json +++ b/test/plugin_functional/plugins/kbn_tp_visualize_embedding/package.json @@ -7,7 +7,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@elastic/eui": "14.5.0", + "@elastic/eui": "14.7.0", "react": "^16.8.0", "react-dom": "^16.8.0" } diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap index 7f562efcf64aa..c663c52d7d639 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap +++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/__snapshots__/List.test.tsx.snap @@ -132,7 +132,11 @@ exports[`ErrorGroupOverview -> List should render empty state 1`] = ` data-test-subj="tableHeaderCell_groupId_0" role="columnheader" scope="col" - width="96px" + style={ + Object { + "width": "96px", + } + } >
List should render empty state 1`] = ` data-test-subj="tableHeaderCell_message_1" role="columnheader" scope="col" - width="50%" + style={ + Object { + "width": "50%", + } + } >
List should render empty state 1`] = ` data-test-subj="tableHeaderCell_handled_2" role="columnheader" scope="col" + style={ + Object { + "width": undefined, + } + } >
List should render empty state 1`] = ` data-test-subj="tableHeaderCell_occurrenceCount_3" role="columnheader" scope="col" + style={ + Object { + "width": undefined, + } + } >
- - - - - } className="euiSideNavItemButton" >
- - - - - } className="euiSideNavItemButton" > ({ defaultMessage: 'Explore infrastructure metrics and logs for common servers, containers, and services.', }), - icon: 'infraApp', + icon: 'metricsApp', path: `/app/${APP_ID}#infrastructure`, showOnHomePage: true, category: FeatureCatalogueCategory.DATA, @@ -36,7 +36,7 @@ FeatureCatalogueRegistryProvider.register((i18n: I18nServiceType) => ({ defaultMessage: 'Stream logs in real time or scroll through historical views in a console-like experience.', }), - icon: 'loggingApp', + icon: 'logsApp', path: `/app/${APP_ID}#logs`, showOnHomePage: true, category: FeatureCatalogueCategory.DATA, diff --git a/x-pack/legacy/plugins/infra/server/kibana.index.ts b/x-pack/legacy/plugins/infra/server/kibana.index.ts index 59e3ffb3cb33d..48ef846ec5275 100644 --- a/x-pack/legacy/plugins/infra/server/kibana.index.ts +++ b/x-pack/legacy/plugins/infra/server/kibana.index.ts @@ -35,7 +35,7 @@ export const initServerWithKibana = (kbnServer: KbnServer) => { name: i18n.translate('xpack.infra.featureRegistry.linkInfrastructureTitle', { defaultMessage: 'Metrics', }), - icon: 'infraApp', + icon: 'metricsApp', navLinkId: 'infra:home', app: ['infra', 'kibana'], catalogue: ['infraops'], @@ -73,7 +73,7 @@ export const initServerWithKibana = (kbnServer: KbnServer) => { name: i18n.translate('xpack.infra.featureRegistry.linkLogsTitle', { defaultMessage: 'Logs', }), - icon: 'loggingApp', + icon: 'logsApp', navLinkId: 'infra:logs', app: ['infra', 'kibana'], catalogue: ['infralogging'], diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json index ead765e474720..26b404ff331c6 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json +++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/logo.json @@ -1,3 +1,3 @@ { - "icon": "loggingApp" + "icon": "logsApp" } diff --git a/x-pack/legacy/plugins/monitoring/public/components/logs/__snapshots__/logs.test.js.snap b/x-pack/legacy/plugins/monitoring/public/components/logs/__snapshots__/logs.test.js.snap index b108746a422bb..4affadd127530 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/logs/__snapshots__/logs.test.js.snap +++ b/x-pack/legacy/plugins/monitoring/public/components/logs/__snapshots__/logs.test.js.snap @@ -2,7 +2,7 @@ exports[`Logs should render a link to filter by cluster uuid 1`] = ` @@ -26,7 +26,7 @@ exports[`Logs should render a link to filter by cluster uuid 1`] = ` exports[`Logs should render a link to filter by cluster uuid and index uuid 1`] = ` @@ -50,7 +50,7 @@ exports[`Logs should render a link to filter by cluster uuid and index uuid 1`] exports[`Logs should render a link to filter by cluster uuid and node uuid 1`] = ` @@ -275,7 +275,7 @@ exports[`Logs should render normally 1`] = ` size="m" /> diff --git a/x-pack/legacy/plugins/monitoring/public/components/logs/logs.js b/x-pack/legacy/plugins/monitoring/public/components/logs/logs.js index c59a3d595b14f..50e3cbd9af6c9 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/logs/logs.js +++ b/x-pack/legacy/plugins/monitoring/public/components/logs/logs.js @@ -169,7 +169,7 @@ export class Logs extends PureComponent { title={i18n.translate('xpack.monitoring.logs.listing.calloutTitle', { defaultMessage: 'Want to see more log entries?' })} - iconType="loggingApp" + iconType="logsApp" >

@@ -15,7 +15,7 @@ exports[`IntegrationGroup will not display APM links when APM is unavailable 1`] @@ -23,7 +23,7 @@ exports[`IntegrationGroup will not display APM links when APM is unavailable 1`] @@ -31,7 +31,7 @@ exports[`IntegrationGroup will not display APM links when APM is unavailable 1`] @@ -39,7 +39,7 @@ exports[`IntegrationGroup will not display APM links when APM is unavailable 1`] @@ -47,7 +47,7 @@ exports[`IntegrationGroup will not display APM links when APM is unavailable 1`] @@ -71,7 +71,7 @@ exports[`IntegrationGroup will not display infra links when infra is unavailable @@ -79,7 +79,7 @@ exports[`IntegrationGroup will not display infra links when infra is unavailable @@ -87,7 +87,7 @@ exports[`IntegrationGroup will not display infra links when infra is unavailable @@ -111,7 +111,7 @@ exports[`IntegrationGroup will not display logging links when logging is unavail @@ -119,7 +119,7 @@ exports[`IntegrationGroup will not display logging links when logging is unavail @@ -127,7 +127,7 @@ exports[`IntegrationGroup will not display logging links when logging is unavail diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/integration_group.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/integration_group.tsx index 2dd3d24a3cd8d..da66235e37f1a 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/integration_group.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/integration_group.tsx @@ -87,7 +87,7 @@ export const IntegrationGroup = ({ } )} href={getInfraIpHref(summary, basePath)} - iconType="infraApp" + iconType="metricsApp" message={i18n.translate( 'xpack.uptime.monitorList.infraIntegrationAction.ip.message', { @@ -116,7 +116,7 @@ export const IntegrationGroup = ({ } )} href={getInfraKubernetesHref(summary, basePath)} - iconType="infraApp" + iconType="metricsApp" message={i18n.translate( 'xpack.uptime.monitorList.infraIntegrationAction.kubernetes.message', { @@ -145,7 +145,7 @@ export const IntegrationGroup = ({ } )} href={getInfraContainerHref(summary, basePath)} - iconType="infraApp" + iconType="metricsApp" message={i18n.translate( 'xpack.uptime.monitorList.infraIntegrationAction.container.message', { @@ -177,7 +177,7 @@ export const IntegrationGroup = ({ } )} href={getLoggingIpHref(summary, basePath)} - iconType="loggingApp" + iconType="logsApp" message={i18n.translate( 'xpack.uptime.monitorList.loggingIntegrationAction.ip.message', { @@ -200,7 +200,7 @@ export const IntegrationGroup = ({ } )} href={getLoggingKubernetesHref(summary, basePath)} - iconType="loggingApp" + iconType="logsApp" message={i18n.translate( 'xpack.uptime.monitorList.loggingIntegrationAction.kubernetes.message', { @@ -227,7 +227,7 @@ export const IntegrationGroup = ({ } )} href={getLoggingContainerHref(summary, basePath)} - iconType="loggingApp" + iconType="logsApp" message={i18n.translate( 'xpack.uptime.monitorList.loggingIntegrationAction.container.message', { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/integration_link.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/integration_link.tsx index 63a3053afc601..a545cd7c42927 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/integration_link.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/integration_link.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; interface IntegrationLinkProps { ariaLabel: string; href: string | undefined; - iconType: 'apmApp' | 'infraApp' | 'loggingApp'; + iconType: 'apmApp' | 'metricsApp' | 'logsApp'; message: string; tooltipContent: string; } diff --git a/x-pack/legacy/plugins/watcher/common/types/action_types.ts b/x-pack/legacy/plugins/watcher/common/types/action_types.ts index 8247df3293d17..123bf0f58db9d 100644 --- a/x-pack/legacy/plugins/watcher/common/types/action_types.ts +++ b/x-pack/legacy/plugins/watcher/common/types/action_types.ts @@ -34,7 +34,7 @@ export interface EmailAction extends BaseAction { export interface LoggingAction extends BaseAction { type: LoggingActionType; - iconClass: 'loggingApp'; + iconClass: 'logsApp'; text: string; } diff --git a/x-pack/legacy/plugins/watcher/public/models/action/logging_action.js b/x-pack/legacy/plugins/watcher/public/models/action/logging_action.js index e11ebedc874c0..477ee9e2230b4 100644 --- a/x-pack/legacy/plugins/watcher/public/models/action/logging_action.js +++ b/x-pack/legacy/plugins/watcher/public/models/action/logging_action.js @@ -68,7 +68,7 @@ export class LoggingAction extends BaseAction { static typeName = i18n.translate('xpack.watcher.models.loggingAction.typeName', { defaultMessage: 'Logging', }); - static iconClass = 'loggingApp'; + static iconClass = 'logsApp'; static selectMessage = i18n.translate('xpack.watcher.models.loggingAction.selectMessageText', { defaultMessage: 'Add an item to the logs.', }); diff --git a/x-pack/package.json b/x-pack/package.json index 4d1e6f52411a3..c8f7345450aa6 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -192,7 +192,7 @@ "@elastic/ctags-langserver": "^0.1.11", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", - "@elastic/eui": "14.5.0", + "@elastic/eui": "14.7.0", "@elastic/filesaver": "1.1.2", "@elastic/javascript-typescript-langserver": "^0.3.3", "@elastic/lsp-extension": "^0.1.2", diff --git a/yarn.lock b/yarn.lock index dd12623b1bd23..b949aa07608c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1151,10 +1151,10 @@ tabbable "^1.1.0" uuid "^3.1.0" -"@elastic/eui@14.5.0": - version "14.5.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-14.5.0.tgz#1b27559cd644403e2692cab1549082cbd3421dab" - integrity sha512-QpmfO6Unt4evb4P18CyWzassLFrw/4CUPFYZXQK12IChDOs6GrwQ6xZM8f0wjN/NXwjRjlWzMhtCWHYmrI6NGg== +"@elastic/eui@14.7.0": + version "14.7.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-14.7.0.tgz#dcbd3e9a9307e52a2fdca5833a116de5940de06d" + integrity sha512-IjYjUqhfqjqG6cbaTANiuHyWq3U62ODzcOnIKACxHOGCK2JVwiDvtDByAuj3PvD0wG/cDN49oNbUZ/o0QCapVw== dependencies: "@types/lodash" "^4.14.116" "@types/numeral" "^0.0.25" From a149497b73d7046628c1c75490538173f11f4a09 Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Thu, 24 Oct 2019 08:59:45 -0700 Subject: [PATCH 122/191] NP Security HTTP Interceptors (#39477) * We have a NP plugin! :celebration: * Redirecting to login on all 401s * Adding commented out code for when credentials are omitted * Fixing types * Respond 403 when user changes password with incorrect current password * Adding AnonymousPaths where we ignore all 401s * Adding anonymous path tests * Extracted a dedicated SessionExpires class and added tests * Fixing plugin after refactoring to add SessionExpired * Beginning to work on the session timeout interceptor * Fixing UnauthorizedResponseInterceptor anonymous path test * Removing test anonymous path * Trying to improve readability * Displaying session logout warning * Mocking out the base path * Revert "Mocking out the base path" This reverts commit 824086c168aec5cc55c04e5866ceaafdb2ec12f9. * Changing coreMock to use a concrete instance of BasePath * Adding session timeout interceptor tests * Adding session timeout tests * Adding more tests for short session timeouts * Moving some files to a session folder * More thrashing around: renaming and reorganizing * Renaming Interceptor to HttpInterceptor * Fixing some type errors * Fixing legacy chrome API tests * Fixing other tests to use the concrete instance of BasePath * Adjusting some types * Putting DeeplyMocked back, I don't get how DeeplyMockedKeys works * Moving anonymousPaths to public core http * Reading sessionTimeout from injected vars and supporting null timeout * Doesn't extend session when there is no response * Updating docs and snapshots * Casting sessionTimeout injectedVar to "number | null" * Fixing i18n issues * Update x-pack/plugins/security/public/plugin.ts Co-Authored-By: Larry Gregory * Adding milliseconds postfix to SessionTimeout private fields * Even better anonymous paths, with some validation * Adjusting public method docs for IAnonymousPaths * Adjusting spelling of base-path to basePath * Update x-pack/plugins/security/public/session/session_timeout.tsx Co-Authored-By: Larry Gregory * Update src/core/public/http/anonymous_paths.ts Co-Authored-By: Josh Dover * Update src/core/public/http/anonymous_paths.ts Co-Authored-By: Josh Dover * AnonymousPaths implements IAnonymousPaths and uses IBasePath * Removing DeeplyMocked * Removing TODOs * Fixing types... * Now, ever more normal --- ...n-public.httpservicebase.anonymouspaths.md | 13 ++ .../kibana-plugin-public.httpservicebase.md | 1 + ...ugin-public.ianonymouspaths.isanonymous.md | 24 +++ .../kibana-plugin-public.ianonymouspaths.md | 21 +++ ...-plugin-public.ianonymouspaths.register.md | 24 +++ .../core/public/kibana-plugin-public.md | 1 + src/core/public/http/anonymous_paths.test.ts | 107 +++++++++++ src/core/public/http/anonymous_paths.ts | 53 ++++++ src/core/public/http/http_service.mock.ts | 11 +- src/core/public/http/http_setup.ts | 3 + src/core/public/http/types.ts | 20 ++ src/core/public/index.ts | 1 + src/core/public/mocks.ts | 14 +- .../notifications_service.mock.ts | 6 +- src/core/public/public.api.md | 9 + .../ui_settings_service.test.ts.snap | 18 +- .../query_bar_input.test.tsx.snap | 108 ++++++++--- .../public/chrome/api/base_path.test.mocks.ts | 2 +- .../ui/public/chrome/api/base_path.test.ts | 22 +-- x-pack/.i18nrc.json | 2 +- x-pack/dev-tools/jest/setup/polyfills.js | 1 + .../lens/public/app_plugin/app.test.tsx | 5 +- .../change_password_form.tsx | 2 +- .../public/hacks/on_session_timeout.js | 56 +----- .../server/routes/api/v1/__tests__/users.js | 6 +- .../security/server/routes/api/v1/users.js | 2 +- x-pack/package.json | 1 + x-pack/plugins/security/kibana.json | 2 +- x-pack/plugins/security/public/index.ts | 11 ++ x-pack/plugins/security/public/plugin.ts | 43 +++++ .../plugins/security/public/session/index.ts | 10 + .../public/session/session_expired.mock.ts} | 8 +- .../public/session/session_expired.test.ts | 46 +++++ .../public/session/session_expired.ts | 24 +++ .../public/session/session_timeout.mock.ts | 13 ++ .../public/session/session_timeout.test.tsx | 171 ++++++++++++++++++ .../public/session/session_timeout.tsx | 79 ++++++++ .../session_timeout_http_interceptor.test.ts | 120 ++++++++++++ .../session_timeout_http_interceptor.ts | 50 +++++ .../session/session_timeout_warning.test.tsx} | 6 +- .../session/session_timeout_warning.tsx} | 6 +- ...thorized_response_http_interceptor.test.ts | 89 +++++++++ .../unauthorized_response_http_interceptor.ts | 42 +++++ .../translations/translations/ja-JP.json | 8 +- .../translations/translations/zh-CN.json | 8 +- 45 files changed, 1126 insertions(+), 143 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-public.httpservicebase.anonymouspaths.md create mode 100644 docs/development/core/public/kibana-plugin-public.ianonymouspaths.isanonymous.md create mode 100644 docs/development/core/public/kibana-plugin-public.ianonymouspaths.md create mode 100644 docs/development/core/public/kibana-plugin-public.ianonymouspaths.register.md create mode 100644 src/core/public/http/anonymous_paths.test.ts create mode 100644 src/core/public/http/anonymous_paths.ts create mode 100644 x-pack/plugins/security/public/index.ts create mode 100644 x-pack/plugins/security/public/plugin.ts create mode 100644 x-pack/plugins/security/public/session/index.ts rename x-pack/{legacy/plugins/security/public/components/session_expiration_warning/index.ts => plugins/security/public/session/session_expired.mock.ts} (58%) create mode 100644 x-pack/plugins/security/public/session/session_expired.test.ts create mode 100644 x-pack/plugins/security/public/session/session_expired.ts create mode 100644 x-pack/plugins/security/public/session/session_timeout.mock.ts create mode 100644 x-pack/plugins/security/public/session/session_timeout.test.tsx create mode 100644 x-pack/plugins/security/public/session/session_timeout.tsx create mode 100644 x-pack/plugins/security/public/session/session_timeout_http_interceptor.test.ts create mode 100644 x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts rename x-pack/{legacy/plugins/security/public/components/session_expiration_warning/session_expiration_warning.test.tsx => plugins/security/public/session/session_timeout_warning.test.tsx} (74%) rename x-pack/{legacy/plugins/security/public/components/session_expiration_warning/session_expiration_warning.tsx => plugins/security/public/session/session_timeout_warning.tsx} (81%) create mode 100644 x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts create mode 100644 x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts diff --git a/docs/development/core/public/kibana-plugin-public.httpservicebase.anonymouspaths.md b/docs/development/core/public/kibana-plugin-public.httpservicebase.anonymouspaths.md new file mode 100644 index 0000000000000..e94757c5eb031 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.httpservicebase.anonymouspaths.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [HttpServiceBase](./kibana-plugin-public.httpservicebase.md) > [anonymousPaths](./kibana-plugin-public.httpservicebase.anonymouspaths.md) + +## HttpServiceBase.anonymousPaths property + +APIs for denoting certain paths for not requiring authentication + +Signature: + +```typescript +anonymousPaths: IAnonymousPaths; +``` diff --git a/docs/development/core/public/kibana-plugin-public.httpservicebase.md b/docs/development/core/public/kibana-plugin-public.httpservicebase.md index a1eef3db42b7d..9ea77c95b343e 100644 --- a/docs/development/core/public/kibana-plugin-public.httpservicebase.md +++ b/docs/development/core/public/kibana-plugin-public.httpservicebase.md @@ -15,6 +15,7 @@ export interface HttpServiceBase | Property | Type | Description | | --- | --- | --- | +| [anonymousPaths](./kibana-plugin-public.httpservicebase.anonymouspaths.md) | IAnonymousPaths | APIs for denoting certain paths for not requiring authentication | | [basePath](./kibana-plugin-public.httpservicebase.basepath.md) | IBasePath | APIs for manipulating the basePath on URL segments. | | [delete](./kibana-plugin-public.httpservicebase.delete.md) | HttpHandler | Makes an HTTP request with the DELETE method. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | | [fetch](./kibana-plugin-public.httpservicebase.fetch.md) | HttpHandler | Makes an HTTP request. Defaults to a GET request unless overriden. See [HttpHandler](./kibana-plugin-public.httphandler.md) for options. | diff --git a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.isanonymous.md b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.isanonymous.md new file mode 100644 index 0000000000000..92a87668b6ef0 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.isanonymous.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) > [isAnonymous](./kibana-plugin-public.ianonymouspaths.isanonymous.md) + +## IAnonymousPaths.isAnonymous() method + +Determines whether the provided path doesn't require authentication + +Signature: + +```typescript +isAnonymous(path: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| path | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.md b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.md new file mode 100644 index 0000000000000..3e5caf49695c2 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) + +## IAnonymousPaths interface + +APIs for denoting paths as not requiring authentication + +Signature: + +```typescript +export interface IAnonymousPaths +``` + +## Methods + +| Method | Description | +| --- | --- | +| [isAnonymous(path)](./kibana-plugin-public.ianonymouspaths.isanonymous.md) | Determines whether the provided path doesn't require authentication | +| [register(path)](./kibana-plugin-public.ianonymouspaths.register.md) | Register path as not requiring authentication | + diff --git a/docs/development/core/public/kibana-plugin-public.ianonymouspaths.register.md b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.register.md new file mode 100644 index 0000000000000..88c615da05155 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.ianonymouspaths.register.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) > [register](./kibana-plugin-public.ianonymouspaths.register.md) + +## IAnonymousPaths.register() method + +Register `path` as not requiring authentication + +Signature: + +```typescript +register(path: string): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| path | string | | + +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index e787621c3aaf9..57ab8bedde95e 100644 --- a/docs/development/core/public/kibana-plugin-public.md +++ b/docs/development/core/public/kibana-plugin-public.md @@ -57,6 +57,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [HttpResponse](./kibana-plugin-public.httpresponse.md) | | | [HttpServiceBase](./kibana-plugin-public.httpservicebase.md) | | | [I18nStart](./kibana-plugin-public.i18nstart.md) | I18nStart.Context is required by any localizable React component from @kbn/i18n and @elastic/eui packages and is supposed to be used as the topmost component for any i18n-compatible React tree. | +| [IAnonymousPaths](./kibana-plugin-public.ianonymouspaths.md) | APIs for denoting paths as not requiring authentication | | [IBasePath](./kibana-plugin-public.ibasepath.md) | APIs for manipulating the basePath on URL segments. | | [IContextContainer](./kibana-plugin-public.icontextcontainer.md) | An object that handles registration of context providers and configuring handlers with context. | | [IHttpFetchError](./kibana-plugin-public.ihttpfetcherror.md) | | diff --git a/src/core/public/http/anonymous_paths.test.ts b/src/core/public/http/anonymous_paths.test.ts new file mode 100644 index 0000000000000..bf9212f625f1e --- /dev/null +++ b/src/core/public/http/anonymous_paths.test.ts @@ -0,0 +1,107 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { AnonymousPaths } from './anonymous_paths'; +import { BasePath } from './base_path_service'; + +describe('#register', () => { + it(`allows paths that don't start with /`, () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('bar'); + }); + + it(`allows paths that end with '/'`, () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar/'); + }); +}); + +describe('#isAnonymous', () => { + it('returns true for registered paths', () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar'); + expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); + }); + + it('returns true for paths registered with a trailing slash, but call "isAnonymous" with no trailing slash', () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar/'); + expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); + }); + + it('returns true for paths registered without a trailing slash, but call "isAnonymous" with a trailing slash', () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar'); + expect(anonymousPaths.isAnonymous('/foo/bar/')).toBe(true); + }); + + it('returns true for paths registered without a starting slash', () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('bar'); + expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); + }); + + it('returns true for paths registered with a starting slash', () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar'); + expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); + }); + + it('when there is no basePath and calling "isAnonymous" without a starting slash, returns true for paths registered with a starting slash', () => { + const basePath = new BasePath('/'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar'); + expect(anonymousPaths.isAnonymous('bar')).toBe(true); + }); + + it('when there is no basePath and calling "isAnonymous" with a starting slash, returns true for paths registered with a starting slash', () => { + const basePath = new BasePath('/'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar'); + expect(anonymousPaths.isAnonymous('/bar')).toBe(true); + }); + + it('returns true for paths whose capitalization is different', () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/BAR'); + expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); + }); + + it('returns false for other paths', () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar'); + expect(anonymousPaths.isAnonymous('/foo/foo')).toBe(false); + }); + + it('returns false for sub-paths of registered paths', () => { + const basePath = new BasePath('/foo'); + const anonymousPaths = new AnonymousPaths(basePath); + anonymousPaths.register('/bar'); + expect(anonymousPaths.isAnonymous('/foo/bar/baz')).toBe(false); + }); +}); diff --git a/src/core/public/http/anonymous_paths.ts b/src/core/public/http/anonymous_paths.ts new file mode 100644 index 0000000000000..300c4d64df353 --- /dev/null +++ b/src/core/public/http/anonymous_paths.ts @@ -0,0 +1,53 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { IAnonymousPaths, IBasePath } from 'src/core/public'; + +export class AnonymousPaths implements IAnonymousPaths { + private readonly paths = new Set(); + + constructor(private basePath: IBasePath) {} + + public isAnonymous(path: string): boolean { + const pathWithoutBasePath = this.basePath.remove(path); + return this.paths.has(this.normalizePath(pathWithoutBasePath)); + } + + public register(path: string) { + this.paths.add(this.normalizePath(path)); + } + + private normalizePath(path: string) { + // always lower-case it + let normalized = path.toLowerCase(); + + // remove the slash from the end + if (normalized.endsWith('/')) { + normalized = normalized.slice(0, normalized.length - 1); + } + + // put a slash at the start + if (!normalized.startsWith('/')) { + normalized = `/${normalized}`; + } + + // it's normalized!!! + return normalized; + } +} diff --git a/src/core/public/http/http_service.mock.ts b/src/core/public/http/http_service.mock.ts index a94543414acfa..52f188c7b20a0 100644 --- a/src/core/public/http/http_service.mock.ts +++ b/src/core/public/http/http_service.mock.ts @@ -20,9 +20,11 @@ import { HttpService } from './http_service'; import { HttpSetup } from './types'; import { BehaviorSubject } from 'rxjs'; +import { BasePath } from './base_path_service'; +import { AnonymousPaths } from './anonymous_paths'; type ServiceSetupMockType = jest.Mocked & { - basePath: jest.Mocked; + basePath: BasePath; }; const createServiceMock = ({ basePath = '' } = {}): ServiceSetupMockType => ({ @@ -34,11 +36,8 @@ const createServiceMock = ({ basePath = '' } = {}): ServiceSetupMockType => ({ patch: jest.fn(), delete: jest.fn(), options: jest.fn(), - basePath: { - get: jest.fn(() => basePath), - prepend: jest.fn(path => `${basePath}${path}`), - remove: jest.fn(), - }, + basePath: new BasePath(basePath), + anonymousPaths: new AnonymousPaths(new BasePath(basePath)), addLoadingCount: jest.fn(), getLoadingCount$: jest.fn().mockReturnValue(new BehaviorSubject(0)), stop: jest.fn(), diff --git a/src/core/public/http/http_setup.ts b/src/core/public/http/http_setup.ts index a10358926de1f..602382e3a5a60 100644 --- a/src/core/public/http/http_setup.ts +++ b/src/core/public/http/http_setup.ts @@ -36,6 +36,7 @@ import { HttpInterceptController } from './http_intercept_controller'; import { HttpFetchError } from './http_fetch_error'; import { HttpInterceptHaltError } from './http_intercept_halt_error'; import { BasePath } from './base_path_service'; +import { AnonymousPaths } from './anonymous_paths'; const JSON_CONTENT = /^(application\/(json|x-javascript)|text\/(x-)?javascript|x-json)(;.*)?$/; const NDJSON_CONTENT = /^(application\/ndjson)(;.*)?$/; @@ -57,6 +58,7 @@ export const setup = ( const interceptors = new Set(); const kibanaVersion = injectedMetadata.getKibanaVersion(); const basePath = new BasePath(injectedMetadata.getBasePath()); + const anonymousPaths = new AnonymousPaths(basePath); function intercept(interceptor: HttpInterceptor) { interceptors.add(interceptor); @@ -318,6 +320,7 @@ export const setup = ( return { stop, basePath, + anonymousPaths, intercept, removeAllInterceptors, fetch, diff --git a/src/core/public/http/types.ts b/src/core/public/http/types.ts index 96500d566b3e5..870d4af8f9e86 100644 --- a/src/core/public/http/types.ts +++ b/src/core/public/http/types.ts @@ -29,6 +29,11 @@ export interface HttpServiceBase { */ basePath: IBasePath; + /** + * APIs for denoting certain paths for not requiring authentication + */ + anonymousPaths: IAnonymousPaths; + /** * Adds a new {@link HttpInterceptor} to the global HTTP client. * @param interceptor a {@link HttpInterceptor} @@ -92,6 +97,21 @@ export interface IBasePath { remove: (url: string) => string; } +/** + * APIs for denoting paths as not requiring authentication + */ +export interface IAnonymousPaths { + /** + * Determines whether the provided path doesn't require authentication. `path` should include the current basePath. + */ + isAnonymous(path: string): boolean; + + /** + * Register `path` as not requiring authentication. `path` should not include the current basePath. + */ + register(path: string): void; +} + /** * See {@link HttpServiceBase} * @public diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 3d8714a001158..24201ff0253cb 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -110,6 +110,7 @@ export { HttpHandler, HttpBody, IBasePath, + IAnonymousPaths, IHttpInterceptController, IHttpFetchError, InterceptedHttpResponse, diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index 8345980b6869d..b9cd2577c2217 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -18,7 +18,7 @@ */ import { applicationServiceMock } from './application/application_service.mock'; import { chromeServiceMock } from './chrome/chrome_service.mock'; -import { CoreContext, CoreSetup, CoreStart, PluginInitializerContext } from '.'; +import { CoreContext, CoreSetup, CoreStart, PluginInitializerContext, NotificationsSetup } from '.'; import { docLinksServiceMock } from './doc_links/doc_links_service.mock'; import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock'; import { httpServiceMock } from './http/http_service.mock'; @@ -41,12 +41,12 @@ export { notificationServiceMock } from './notifications/notifications_service.m export { overlayServiceMock } from './overlays/overlay_service.mock'; export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; -function createCoreSetupMock() { - const mock: MockedKeys = { +function createCoreSetupMock({ basePath = '' } = {}) { + const mock: MockedKeys & { notifications: MockedKeys } = { application: applicationServiceMock.createSetupContract(), context: contextServiceMock.createSetupContract(), fatalErrors: fatalErrorsServiceMock.createSetupContract(), - http: httpServiceMock.createSetupContract(), + http: httpServiceMock.createSetupContract({ basePath }), notifications: notificationServiceMock.createSetupContract(), uiSettings: uiSettingsServiceMock.createSetupContract(), injectedMetadata: { @@ -57,12 +57,12 @@ function createCoreSetupMock() { return mock; } -function createCoreStartMock() { - const mock: MockedKeys = { +function createCoreStartMock({ basePath = '' } = {}) { + const mock: MockedKeys & { notifications: MockedKeys } = { application: applicationServiceMock.createStartContract(), chrome: chromeServiceMock.createStartContract(), docLinks: docLinksServiceMock.createStartContract(), - http: httpServiceMock.createStartContract(), + http: httpServiceMock.createStartContract({ basePath }), i18n: i18nServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), overlays: overlayServiceMock.createStartContract(), diff --git a/src/core/public/notifications/notifications_service.mock.ts b/src/core/public/notifications/notifications_service.mock.ts index 8f4a1d5bcd400..464f47e20aa3b 100644 --- a/src/core/public/notifications/notifications_service.mock.ts +++ b/src/core/public/notifications/notifications_service.mock.ts @@ -23,10 +23,8 @@ import { } from './notifications_service'; import { toastsServiceMock } from './toasts/toasts_service.mock'; -type DeeplyMocked = { [P in keyof T]: jest.Mocked }; - const createSetupContractMock = () => { - const setupContract: DeeplyMocked = { + const setupContract: MockedKeys = { // we have to suppress type errors until decide how to mock es6 class toasts: toastsServiceMock.createSetupContract(), }; @@ -34,7 +32,7 @@ const createSetupContractMock = () => { }; const createStartContractMock = () => { - const startContract: DeeplyMocked = { + const startContract: MockedKeys = { // we have to suppress type errors until decide how to mock es6 class toasts: toastsServiceMock.createStartContract(), }; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index ec8a22fe5953c..11a1b5c0d1d9b 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -488,6 +488,7 @@ export interface HttpResponse extends InterceptedHttpResponse { // @public (undocumented) export interface HttpServiceBase { addLoadingCount(countSource$: Observable): void; + anonymousPaths: IAnonymousPaths; basePath: IBasePath; delete: HttpHandler; fetch: HttpHandler; @@ -517,6 +518,14 @@ export interface I18nStart { }) => JSX.Element; } +// Warning: (ae-missing-release-tag) "IAnonymousPaths" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface IAnonymousPaths { + isAnonymous(path: string): boolean; + register(path: string): void; +} + // @public export interface IBasePath { get: () => string; diff --git a/src/core/public/ui_settings/__snapshots__/ui_settings_service.test.ts.snap b/src/core/public/ui_settings/__snapshots__/ui_settings_service.test.ts.snap index f607c924a9e68..84f9a5ab7c5cd 100644 --- a/src/core/public/ui_settings/__snapshots__/ui_settings_service.test.ts.snap +++ b/src/core/public/ui_settings/__snapshots__/ui_settings_service.test.ts.snap @@ -20,10 +20,20 @@ exports[`#setup constructs UiSettingsClient and UiSettingsApi: UiSettingsApi arg }, ], }, - "basePath": Object { - "get": [MockFunction], - "prepend": [MockFunction], - "remove": [MockFunction], + "anonymousPaths": AnonymousPaths { + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + }, + "paths": Set {}, + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], }, "delete": [MockFunction], "fetch": [MockFunction], diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap index 06f9e6081e522..f59afc7165bab 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap @@ -229,10 +229,20 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto }, "http": Object { "addLoadingCount": [MockFunction], - "basePath": Object { - "get": [MockFunction], - "prepend": [MockFunction], - "remove": [MockFunction], + "anonymousPaths": AnonymousPaths { + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + }, + "paths": Set {}, + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], }, "delete": [MockFunction], "fetch": [MockFunction], @@ -775,10 +785,20 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto }, "http": Object { "addLoadingCount": [MockFunction], - "basePath": Object { - "get": [MockFunction], - "prepend": [MockFunction], - "remove": [MockFunction], + "anonymousPaths": AnonymousPaths { + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + }, + "paths": Set {}, + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], }, "delete": [MockFunction], "fetch": [MockFunction], @@ -1309,10 +1329,20 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1 }, "http": Object { "addLoadingCount": [MockFunction], - "basePath": Object { - "get": [MockFunction], - "prepend": [MockFunction], - "remove": [MockFunction], + "anonymousPaths": AnonymousPaths { + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + }, + "paths": Set {}, + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], }, "delete": [MockFunction], "fetch": [MockFunction], @@ -1852,10 +1882,20 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1 }, "http": Object { "addLoadingCount": [MockFunction], - "basePath": Object { - "get": [MockFunction], - "prepend": [MockFunction], - "remove": [MockFunction], + "anonymousPaths": AnonymousPaths { + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + }, + "paths": Set {}, + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], }, "delete": [MockFunction], "fetch": [MockFunction], @@ -2386,10 +2426,20 @@ exports[`QueryBarInput Should render the given query 1`] = ` }, "http": Object { "addLoadingCount": [MockFunction], - "basePath": Object { - "get": [MockFunction], - "prepend": [MockFunction], - "remove": [MockFunction], + "anonymousPaths": AnonymousPaths { + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + }, + "paths": Set {}, + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], }, "delete": [MockFunction], "fetch": [MockFunction], @@ -2929,10 +2979,20 @@ exports[`QueryBarInput Should render the given query 1`] = ` }, "http": Object { "addLoadingCount": [MockFunction], - "basePath": Object { - "get": [MockFunction], - "prepend": [MockFunction], - "remove": [MockFunction], + "anonymousPaths": AnonymousPaths { + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], + }, + "paths": Set {}, + }, + "basePath": BasePath { + "basePath": "", + "get": [Function], + "prepend": [Function], + "remove": [Function], }, "delete": [MockFunction], "fetch": [MockFunction], diff --git a/src/legacy/ui/public/chrome/api/base_path.test.mocks.ts b/src/legacy/ui/public/chrome/api/base_path.test.mocks.ts index c362b1709fba6..f2c5fd5734b10 100644 --- a/src/legacy/ui/public/chrome/api/base_path.test.mocks.ts +++ b/src/legacy/ui/public/chrome/api/base_path.test.mocks.ts @@ -19,7 +19,7 @@ import { httpServiceMock } from '../../../../../core/public/mocks'; -export const newPlatformHttp = httpServiceMock.createSetupContract(); +const newPlatformHttp = httpServiceMock.createSetupContract({ basePath: 'npBasePath' }); jest.doMock('ui/new_platform', () => ({ npSetup: { core: { http: newPlatformHttp }, diff --git a/src/legacy/ui/public/chrome/api/base_path.test.ts b/src/legacy/ui/public/chrome/api/base_path.test.ts index 812635ba36483..d3cfc6a3168a8 100644 --- a/src/legacy/ui/public/chrome/api/base_path.test.ts +++ b/src/legacy/ui/public/chrome/api/base_path.test.ts @@ -16,8 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -import { newPlatformHttp } from './base_path.test.mocks'; +import './base_path.test.mocks'; import { initChromeBasePathApi } from './base_path'; function initChrome() { @@ -26,10 +25,6 @@ function initChrome() { return chrome; } -newPlatformHttp.basePath.get.mockImplementation(() => 'gotBasePath'); -newPlatformHttp.basePath.prepend.mockImplementation(() => 'addedToPath'); -newPlatformHttp.basePath.remove.mockImplementation(() => 'removedFromPath'); - beforeEach(() => { jest.clearAllMocks(); }); @@ -37,29 +32,20 @@ beforeEach(() => { describe('#getBasePath()', () => { it('proxies to newPlatformHttp.basePath.get()', () => { const chrome = initChrome(); - expect(newPlatformHttp.basePath.prepend).not.toHaveBeenCalled(); - expect(chrome.getBasePath()).toBe('gotBasePath'); - expect(newPlatformHttp.basePath.get).toHaveBeenCalledTimes(1); - expect(newPlatformHttp.basePath.get).toHaveBeenCalledWith(); + expect(chrome.getBasePath()).toBe('npBasePath'); }); }); describe('#addBasePath()', () => { it('proxies to newPlatformHttp.basePath.prepend(path)', () => { const chrome = initChrome(); - expect(newPlatformHttp.basePath.prepend).not.toHaveBeenCalled(); - expect(chrome.addBasePath('foo/bar')).toBe('addedToPath'); - expect(newPlatformHttp.basePath.prepend).toHaveBeenCalledTimes(1); - expect(newPlatformHttp.basePath.prepend).toHaveBeenCalledWith('foo/bar'); + expect(chrome.addBasePath('/foo/bar')).toBe('npBasePath/foo/bar'); }); }); describe('#removeBasePath', () => { it('proxies to newPlatformBasePath.basePath.remove(path)', () => { const chrome = initChrome(); - expect(newPlatformHttp.basePath.remove).not.toHaveBeenCalled(); - expect(chrome.removeBasePath('foo/bar')).toBe('removedFromPath'); - expect(newPlatformHttp.basePath.remove).toHaveBeenCalledTimes(1); - expect(newPlatformHttp.basePath.remove).toHaveBeenCalledWith('foo/bar'); + expect(chrome.removeBasePath('npBasePath/foo/bar')).toBe('/foo/bar'); }); }); diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 735ee0b6b67b5..79a482c470367 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -31,7 +31,7 @@ "xpack.rollupJobs": "legacy/plugins/rollup", "xpack.searchProfiler": "legacy/plugins/searchprofiler", "xpack.siem": "legacy/plugins/siem", - "xpack.security": "legacy/plugins/security", + "xpack.security": ["legacy/plugins/security", "plugins/security"], "xpack.server": "legacy/server", "xpack.snapshotRestore": "legacy/plugins/snapshot_restore", "xpack.spaces": ["legacy/plugins/spaces", "plugins/spaces"], diff --git a/x-pack/dev-tools/jest/setup/polyfills.js b/x-pack/dev-tools/jest/setup/polyfills.js index 8e5c5a8025b82..566e4701eeaac 100644 --- a/x-pack/dev-tools/jest/setup/polyfills.js +++ b/x-pack/dev-tools/jest/setup/polyfills.js @@ -14,5 +14,6 @@ bluebird.Promise.setScheduler(function (fn) { global.setImmediate.call(global, f const MutationObserver = require('mutation-observer'); Object.defineProperty(window, 'MutationObserver', { value: MutationObserver }); +require('whatwg-fetch'); const URL = { createObjectURL: () => '' }; Object.defineProperty(window, 'URL', { value: URL }); diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx index 77d0d5a5305aa..0e3e6b0381309 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx @@ -127,7 +127,7 @@ describe('Lens App', () => { beforeEach(() => { frame = createMockFrame(); - core = coreMock.createStart(); + core = coreMock.createStart({ basePath: '/testbasepath' }); core.uiSettings.get.mockImplementation( jest.fn(type => { @@ -140,9 +140,6 @@ describe('Lens App', () => { } }) ); - - (core.http.basePath.get as jest.Mock).mockReturnValue(`/testbasepath`); - (core.http.basePath.prepend as jest.Mock).mockImplementation(s => `/testbasepath${s}`); }); it('renders the editor frame', () => { diff --git a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx b/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx index 9521cbdc58a78..61c0b77decd56 100644 --- a/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx +++ b/x-pack/legacy/plugins/security/public/components/management/change_password_form/change_password_form.tsx @@ -314,7 +314,7 @@ export class ChangePasswordForm extends Component { }; private handleChangePasswordFailure = (error: Record) => { - if (error.body && error.body.statusCode === 401) { + if (error.body && error.body.statusCode === 403) { this.setState({ currentPasswordError: true }); } else { toastNotifications.addDanger( diff --git a/x-pack/legacy/plugins/security/public/hacks/on_session_timeout.js b/x-pack/legacy/plugins/security/public/hacks/on_session_timeout.js index 0f1787820a2f2..81b14ee7d8bf4 100644 --- a/x-pack/legacy/plugins/security/public/hacks/on_session_timeout.js +++ b/x-pack/legacy/plugins/security/public/hacks/on_session_timeout.js @@ -4,15 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; import _ from 'lodash'; -import { i18n } from '@kbn/i18n'; import { uiModules } from 'ui/modules'; import { isSystemApiRequest } from 'ui/system_api'; import { Path } from 'plugins/xpack_main/services/path'; -import { toastNotifications } from 'ui/notify'; -import 'plugins/security/services/auto_logout'; -import { SessionExpirationWarning } from '../components/session_expiration_warning'; +import { npSetup } from 'ui/new_platform'; /** * Client session timeout is decreased by this number so that Kibana server @@ -20,65 +16,19 @@ import { SessionExpirationWarning } from '../components/session_expiration_warni * user session up (invalidate access tokens, redirect to logout portal etc.). * @type {number} */ -const SESSION_TIMEOUT_GRACE_PERIOD_MS = 5000; const module = uiModules.get('security', []); module.config(($httpProvider) => { $httpProvider.interceptors.push(( - $timeout, $q, - $injector, - sessionTimeout, - Private, - autoLogout ) => { - function refreshSession() { - // Make a simple request to keep the session alive - $injector.get('es').ping(); - clearNotifications(); - } - const isUnauthenticated = Path.isUnauthenticated(); - const notificationLifetime = 60 * 1000; - const notificationOptions = { - color: 'warning', - text: ( - - ), - title: i18n.translate('xpack.security.hacks.warningTitle', { - defaultMessage: 'Warning' - }), - toastLifeTimeMs: Math.min( - (sessionTimeout - SESSION_TIMEOUT_GRACE_PERIOD_MS), - notificationLifetime - ), - }; - - let pendingNotification; - let activeNotification; - let pendingSessionExpiration; - - function clearNotifications() { - if (pendingNotification) $timeout.cancel(pendingNotification); - if (pendingSessionExpiration) clearTimeout(pendingSessionExpiration); - if (activeNotification) toastNotifications.remove(activeNotification); - } - - function scheduleNotification() { - pendingNotification = $timeout(showNotification, Math.max(sessionTimeout - notificationLifetime, 0)); - } - - function showNotification() { - activeNotification = toastNotifications.add(notificationOptions); - pendingSessionExpiration = setTimeout(() => autoLogout(), notificationOptions.toastLifeTimeMs); - } function interceptorFactory(responseHandler) { return function interceptor(response) { - if (!isUnauthenticated && !isSystemApiRequest(response.config) && sessionTimeout !== null) { - clearNotifications(); - scheduleNotification(); + if (!isUnauthenticated && !isSystemApiRequest(response.config)) { + npSetup.plugins.security.sessionTimeout.extend(); } return responseHandler(response); }; diff --git a/x-pack/legacy/plugins/security/server/routes/api/v1/__tests__/users.js b/x-pack/legacy/plugins/security/server/routes/api/v1/__tests__/users.js index 8444efe8790e7..83dfa778f1b50 100644 --- a/x-pack/legacy/plugins/security/server/routes/api/v1/__tests__/users.js +++ b/x-pack/legacy/plugins/security/server/routes/api/v1/__tests__/users.js @@ -81,7 +81,7 @@ describe('User routes', () => { .resolves(AuthenticationResult.succeeded({})); }); - it('returns 401 if old password is wrong.', async () => { + it('returns 403 if old password is wrong.', async () => { loginStub.resolves(AuthenticationResult.failed(new Error('Something went wrong.'))); const response = await changePasswordRoute.handler(request); @@ -89,13 +89,13 @@ describe('User routes', () => { sinon.assert.notCalled(clusterStub.callWithRequest); expect(response.isBoom).to.be(true); expect(response.output.payload).to.eql({ - statusCode: 401, + statusCode: 403, error: 'Unauthorized', message: 'Something went wrong.' }); }); - it('returns 401 if user can authenticate with new password.', async () => { + it(`returns 401 if user can't authenticate with new password.`, async () => { loginStub .withArgs( sinon.match.instanceOf(KibanaRequest), diff --git a/x-pack/legacy/plugins/security/server/routes/api/v1/users.js b/x-pack/legacy/plugins/security/server/routes/api/v1/users.js index 9cb2ad799a211..1d47dc8875348 100644 --- a/x-pack/legacy/plugins/security/server/routes/api/v1/users.js +++ b/x-pack/legacy/plugins/security/server/routes/api/v1/users.js @@ -108,7 +108,7 @@ export function initUsersApi({ authc: { login }, config }, server) { return Boom.unauthorized(authenticationResult.error); } } catch(err) { - return Boom.unauthorized(err); + throw Boom.forbidden(err); } } diff --git a/x-pack/package.json b/x-pack/package.json index c8f7345450aa6..fa439a2087547 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -182,6 +182,7 @@ "ts-loader": "^6.0.4", "typescript": "3.5.3", "vinyl-fs": "^3.0.3", + "whatwg-fetch": "^3.0.0", "xml-crypto": "^1.4.0", "yargs": "4.8.1" }, diff --git a/x-pack/plugins/security/kibana.json b/x-pack/plugins/security/kibana.json index 7ac9d654eb07e..9f243a7dfb2fc 100644 --- a/x-pack/plugins/security/kibana.json +++ b/x-pack/plugins/security/kibana.json @@ -4,5 +4,5 @@ "kibanaVersion": "kibana", "configPath": ["xpack", "security"], "server": true, - "ui": false + "ui": true } diff --git a/x-pack/plugins/security/public/index.ts b/x-pack/plugins/security/public/index.ts new file mode 100644 index 0000000000000..12a3092039d0d --- /dev/null +++ b/x-pack/plugins/security/public/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { PluginInitializer } from 'src/core/public'; +import { SecurityPlugin, SecurityPluginSetup, SecurityPluginStart } from './plugin'; + +export const plugin: PluginInitializer = () => + new SecurityPlugin(); diff --git a/x-pack/plugins/security/public/plugin.ts b/x-pack/plugins/security/public/plugin.ts new file mode 100644 index 0000000000000..55d125bf993ec --- /dev/null +++ b/x-pack/plugins/security/public/plugin.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Plugin, CoreSetup } from 'src/core/public'; +import { + SessionExpired, + SessionTimeout, + SessionTimeoutHttpInterceptor, + UnauthorizedResponseHttpInterceptor, +} from './session'; + +export class SecurityPlugin implements Plugin { + public setup(core: CoreSetup) { + const { http, notifications, injectedMetadata } = core; + const { basePath, anonymousPaths } = http; + anonymousPaths.register('/login'); + anonymousPaths.register('/logout'); + anonymousPaths.register('/logged_out'); + + const sessionExpired = new SessionExpired(basePath); + http.intercept(new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths)); + const sessionTimeout = new SessionTimeout( + injectedMetadata.getInjectedVar('sessionTimeout', null) as number | null, + notifications, + sessionExpired, + http + ); + http.intercept(new SessionTimeoutHttpInterceptor(sessionTimeout, anonymousPaths)); + + return { + anonymousPaths, + sessionTimeout, + }; + } + + public start() {} +} + +export type SecurityPluginSetup = ReturnType; +export type SecurityPluginStart = ReturnType; diff --git a/x-pack/plugins/security/public/session/index.ts b/x-pack/plugins/security/public/session/index.ts new file mode 100644 index 0000000000000..253207dc1b717 --- /dev/null +++ b/x-pack/plugins/security/public/session/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { SessionExpired } from './session_expired'; +export { SessionTimeout } from './session_timeout'; +export { SessionTimeoutHttpInterceptor } from './session_timeout_http_interceptor'; +export { UnauthorizedResponseHttpInterceptor } from './unauthorized_response_http_interceptor'; diff --git a/x-pack/legacy/plugins/security/public/components/session_expiration_warning/index.ts b/x-pack/plugins/security/public/session/session_expired.mock.ts similarity index 58% rename from x-pack/legacy/plugins/security/public/components/session_expiration_warning/index.ts rename to x-pack/plugins/security/public/session/session_expired.mock.ts index 0aa0c1f9fb079..e894caafd9594 100644 --- a/x-pack/legacy/plugins/security/public/components/session_expiration_warning/index.ts +++ b/x-pack/plugins/security/public/session/session_expired.mock.ts @@ -4,4 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -export { SessionExpirationWarning } from './session_expiration_warning'; +import { ISessionExpired } from './session_expired'; + +export function createSessionExpiredMock() { + return { + logout: jest.fn(), + } as jest.Mocked; +} diff --git a/x-pack/plugins/security/public/session/session_expired.test.ts b/x-pack/plugins/security/public/session/session_expired.test.ts new file mode 100644 index 0000000000000..9c0e4cd8036cc --- /dev/null +++ b/x-pack/plugins/security/public/session/session_expired.test.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { coreMock } from 'src/core/public/mocks'; +import { SessionExpired } from './session_expired'; + +const mockCurrentUrl = (url: string) => window.history.pushState({}, '', url); + +it('redirects user to "/logout" when there is no basePath', async () => { + const { basePath } = coreMock.createSetup().http; + mockCurrentUrl('/foo/bar?baz=quz#quuz'); + const sessionExpired = new SessionExpired(basePath); + const newUrlPromise = new Promise(resolve => { + jest.spyOn(window.location, 'assign').mockImplementation(url => { + resolve(url); + }); + }); + + sessionExpired.logout(); + + const url = await newUrlPromise; + expect(url).toBe( + `/logout?next=${encodeURIComponent('/foo/bar?baz=quz#quuz')}&msg=SESSION_EXPIRED` + ); +}); + +it('redirects user to "/${basePath}/logout" and removes basePath from next parameter when there is a basePath', async () => { + const { basePath } = coreMock.createSetup({ basePath: '/foo' }).http; + mockCurrentUrl('/foo/bar?baz=quz#quuz'); + const sessionExpired = new SessionExpired(basePath); + const newUrlPromise = new Promise(resolve => { + jest.spyOn(window.location, 'assign').mockImplementation(url => { + resolve(url); + }); + }); + + sessionExpired.logout(); + + const url = await newUrlPromise; + expect(url).toBe( + `/foo/logout?next=${encodeURIComponent('/bar?baz=quz#quuz')}&msg=SESSION_EXPIRED` + ); +}); diff --git a/x-pack/plugins/security/public/session/session_expired.ts b/x-pack/plugins/security/public/session/session_expired.ts new file mode 100644 index 0000000000000..3ef15088bb288 --- /dev/null +++ b/x-pack/plugins/security/public/session/session_expired.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpSetup } from 'src/core/public'; + +export interface ISessionExpired { + logout(): void; +} + +export class SessionExpired { + constructor(private basePath: HttpSetup['basePath']) {} + + logout() { + const next = this.basePath.remove( + `${window.location.pathname}${window.location.search}${window.location.hash}` + ); + window.location.assign( + this.basePath.prepend(`/logout?next=${encodeURIComponent(next)}&msg=SESSION_EXPIRED`) + ); + } +} diff --git a/x-pack/plugins/security/public/session/session_timeout.mock.ts b/x-pack/plugins/security/public/session/session_timeout.mock.ts new file mode 100644 index 0000000000000..9917a50279083 --- /dev/null +++ b/x-pack/plugins/security/public/session/session_timeout.mock.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ISessionTimeout } from './session_timeout'; + +export function createSessionTimeoutMock() { + return { + extend: jest.fn(), + } as jest.Mocked; +} diff --git a/x-pack/plugins/security/public/session/session_timeout.test.tsx b/x-pack/plugins/security/public/session/session_timeout.test.tsx new file mode 100644 index 0000000000000..776247dda94e6 --- /dev/null +++ b/x-pack/plugins/security/public/session/session_timeout.test.tsx @@ -0,0 +1,171 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { coreMock } from 'src/core/public/mocks'; +import { SessionTimeout } from './session_timeout'; +import { createSessionExpiredMock } from './session_expired.mock'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; + +jest.useFakeTimers(); + +const expectNoWarningToast = ( + notifications: ReturnType['notifications'] +) => { + expect(notifications.toasts.add).not.toHaveBeenCalled(); +}; + +const expectWarningToast = ( + notifications: ReturnType['notifications'], + toastLifeTimeMS: number = 60000 +) => { + expect(notifications.toasts.add).toHaveBeenCalledTimes(1); + expect(notifications.toasts.add.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "color": "warning", + "text": , + "title": "Warning", + "toastLifeTimeMs": ${toastLifeTimeMS}, + }, + ] + `); +}; + +const expectWarningToastHidden = ( + notifications: ReturnType['notifications'], + toast: symbol +) => { + expect(notifications.toasts.remove).toHaveBeenCalledTimes(1); + expect(notifications.toasts.remove).toHaveBeenCalledWith(toast); +}; + +describe('warning toast', () => { + test(`shows session expiration warning toast`, () => { + const { notifications, http } = coreMock.createSetup(); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(2 * 60 * 1000, notifications, sessionExpired, http); + + sessionTimeout.extend(); + // we display the warning a minute before we expire the the session, which is 5 seconds before it actually expires + jest.advanceTimersByTime(55 * 1000); + expectWarningToast(notifications); + }); + + test(`extend delays the warning toast`, () => { + const { notifications, http } = coreMock.createSetup(); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(2 * 60 * 1000, notifications, sessionExpired, http); + + sessionTimeout.extend(); + jest.advanceTimersByTime(54 * 1000); + expectNoWarningToast(notifications); + + sessionTimeout.extend(); + jest.advanceTimersByTime(54 * 1000); + expectNoWarningToast(notifications); + + jest.advanceTimersByTime(1 * 1000); + + expectWarningToast(notifications); + }); + + test(`extend hides displayed warning toast`, () => { + const { notifications, http } = coreMock.createSetup(); + const toast = Symbol(); + notifications.toasts.add.mockReturnValue(toast as any); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(2 * 60 * 1000, notifications, sessionExpired, http); + + sessionTimeout.extend(); + // we display the warning a minute before we expire the the session, which is 5 seconds before it actually expires + jest.advanceTimersByTime(55 * 1000); + expectWarningToast(notifications); + + sessionTimeout.extend(); + expectWarningToastHidden(notifications, toast); + }); + + test('clicking "extend" causes a new HTTP request (which implicitly extends the session)', () => { + const { notifications, http } = coreMock.createSetup(); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(2 * 60 * 1000, notifications, sessionExpired, http); + + sessionTimeout.extend(); + // we display the warning a minute before we expire the the session, which is 5 seconds before it actually expires + jest.advanceTimersByTime(55 * 1000); + expectWarningToast(notifications); + + expect(http.get).not.toHaveBeenCalled(); + const toastInput = notifications.toasts.add.mock.calls[0][0]; + expect(toastInput).toHaveProperty('text'); + const reactComponent = (toastInput as any).text; + const wrapper = mountWithIntl(reactComponent); + wrapper.find('EuiButton[data-test-subj="refreshSessionButton"]').simulate('click'); + expect(http.get).toHaveBeenCalled(); + }); + + test('when the session timeout is shorter than 65 seconds, display the warning immediately and for a shorter duration', () => { + const { notifications, http } = coreMock.createSetup(); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(64 * 1000, notifications, sessionExpired, http); + + sessionTimeout.extend(); + jest.advanceTimersByTime(0); + expectWarningToast(notifications, 59 * 1000); + }); +}); + +describe('session expiration', () => { + test(`expires the session 5 seconds before it really expires`, () => { + const { notifications, http } = coreMock.createSetup(); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(2 * 60 * 1000, notifications, sessionExpired, http); + + sessionTimeout.extend(); + jest.advanceTimersByTime(114 * 1000); + expect(sessionExpired.logout).not.toHaveBeenCalled(); + + jest.advanceTimersByTime(1 * 1000); + expect(sessionExpired.logout).toHaveBeenCalled(); + }); + + test(`extend delays the expiration`, () => { + const { notifications, http } = coreMock.createSetup(); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(2 * 60 * 1000, notifications, sessionExpired, http); + + sessionTimeout.extend(); + jest.advanceTimersByTime(114 * 1000); + + sessionTimeout.extend(); + jest.advanceTimersByTime(114 * 1000); + expect(sessionExpired.logout).not.toHaveBeenCalled(); + + jest.advanceTimersByTime(1 * 1000); + expect(sessionExpired.logout).toHaveBeenCalled(); + }); + + test(`if the session timeout is shorter than 5 seconds, expire session immediately`, () => { + const { notifications, http } = coreMock.createSetup(); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(4 * 1000, notifications, sessionExpired, http); + + sessionTimeout.extend(); + jest.advanceTimersByTime(0); + expect(sessionExpired.logout).toHaveBeenCalled(); + }); + + test(`'null' sessionTimeout never logs you out`, () => { + const { notifications, http } = coreMock.createSetup(); + const sessionExpired = createSessionExpiredMock(); + const sessionTimeout = new SessionTimeout(null, notifications, sessionExpired, http); + sessionTimeout.extend(); + jest.advanceTimersByTime(Number.MAX_VALUE); + expect(sessionExpired.logout).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/security/public/session/session_timeout.tsx b/x-pack/plugins/security/public/session/session_timeout.tsx new file mode 100644 index 0000000000000..db4926e7f04ea --- /dev/null +++ b/x-pack/plugins/security/public/session/session_timeout.tsx @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { NotificationsSetup, Toast, HttpSetup } from 'src/core/public'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { SessionTimeoutWarning } from './session_timeout_warning'; +import { ISessionExpired } from './session_expired'; + +/** + * Client session timeout is decreased by this number so that Kibana server + * can still access session content during logout request to properly clean + * user session up (invalidate access tokens, redirect to logout portal etc.). + */ +const GRACE_PERIOD_MS = 5 * 1000; + +/** + * Duration we'll normally display the warning toast + */ +const WARNING_MS = 60 * 1000; + +export interface ISessionTimeout { + extend(): void; +} + +export class SessionTimeout { + private warningTimeoutMilliseconds?: number; + private expirationTimeoutMilliseconds?: number; + private warningToast?: Toast; + + constructor( + private sessionTimeoutMilliseconds: number | null, + private notifications: NotificationsSetup, + private sessionExpired: ISessionExpired, + private http: HttpSetup + ) {} + + extend() { + if (this.sessionTimeoutMilliseconds == null) { + return; + } + + if (this.warningTimeoutMilliseconds) { + window.clearTimeout(this.warningTimeoutMilliseconds); + } + if (this.expirationTimeoutMilliseconds) { + window.clearTimeout(this.expirationTimeoutMilliseconds); + } + if (this.warningToast) { + this.notifications.toasts.remove(this.warningToast); + } + this.warningTimeoutMilliseconds = window.setTimeout( + () => this.showWarning(), + Math.max(this.sessionTimeoutMilliseconds - WARNING_MS - GRACE_PERIOD_MS, 0) + ); + this.expirationTimeoutMilliseconds = window.setTimeout( + () => this.sessionExpired.logout(), + Math.max(this.sessionTimeoutMilliseconds - GRACE_PERIOD_MS, 0) + ); + } + + private showWarning = () => { + this.warningToast = this.notifications.toasts.add({ + color: 'warning', + text: , + title: i18n.translate('xpack.security.components.sessionTimeoutWarning.title', { + defaultMessage: 'Warning', + }), + toastLifeTimeMs: Math.min(this.sessionTimeoutMilliseconds! - GRACE_PERIOD_MS, WARNING_MS), + }); + }; + + private refreshSession = () => { + this.http.get('/api/security/v1/me'); + }; +} diff --git a/x-pack/plugins/security/public/session/session_timeout_http_interceptor.test.ts b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.test.ts new file mode 100644 index 0000000000000..ffbd625590b15 --- /dev/null +++ b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.test.ts @@ -0,0 +1,120 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// @ts-ignore +import fetchMock from 'fetch-mock/es5/client'; +import { SessionTimeoutHttpInterceptor } from './session_timeout_http_interceptor'; +import { setup } from '../../../../../src/test_utils/public/http_test_setup'; +import { createSessionTimeoutMock } from './session_timeout.mock'; + +const mockCurrentUrl = (url: string) => window.history.pushState({}, '', url); + +const setupHttp = (basePath: string) => { + const { http } = setup(injectedMetadata => { + injectedMetadata.getBasePath.mockReturnValue(basePath); + }); + return http; +}; + +afterEach(() => { + fetchMock.restore(); +}); + +describe('response', () => { + test('extends session timeouts', async () => { + const http = setupHttp('/foo'); + const sessionTimeoutMock = createSessionTimeoutMock(); + const interceptor = new SessionTimeoutHttpInterceptor(sessionTimeoutMock, http.anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 200); + + await http.fetch('/foo-api'); + + expect(sessionTimeoutMock.extend).toHaveBeenCalled(); + }); + + test(`doesn't extend session timeouts for anonymous paths`, async () => { + mockCurrentUrl('/foo/bar'); + const http = setupHttp('/foo'); + const sessionTimeoutMock = createSessionTimeoutMock(); + const { anonymousPaths } = http; + anonymousPaths.register('/bar'); + const interceptor = new SessionTimeoutHttpInterceptor(sessionTimeoutMock, anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 200); + + await http.fetch('/foo-api'); + + expect(sessionTimeoutMock.extend).not.toHaveBeenCalled(); + }); + + test(`doesn't extend session timeouts for system api requests`, async () => { + const http = setupHttp('/foo'); + const sessionTimeoutMock = createSessionTimeoutMock(); + const interceptor = new SessionTimeoutHttpInterceptor(sessionTimeoutMock, http.anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 200); + + await http.fetch('/foo-api', { headers: { 'kbn-system-api': 'true' } }); + + expect(sessionTimeoutMock.extend).not.toHaveBeenCalled(); + }); +}); + +describe('responseError', () => { + test('extends session timeouts', async () => { + const http = setupHttp('/foo'); + const sessionTimeoutMock = createSessionTimeoutMock(); + const interceptor = new SessionTimeoutHttpInterceptor(sessionTimeoutMock, http.anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 401); + + await expect(http.fetch('/foo-api')).rejects.toMatchInlineSnapshot(`[Error: Unauthorized]`); + + expect(sessionTimeoutMock.extend).toHaveBeenCalled(); + }); + + test(`doesn't extend session timeouts for anonymous paths`, async () => { + mockCurrentUrl('/foo/bar'); + const http = setupHttp('/foo'); + const sessionTimeoutMock = createSessionTimeoutMock(); + const { anonymousPaths } = http; + anonymousPaths.register('/bar'); + const interceptor = new SessionTimeoutHttpInterceptor(sessionTimeoutMock, anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 401); + + await expect(http.fetch('/foo-api')).rejects.toMatchInlineSnapshot(`[Error: Unauthorized]`); + + expect(sessionTimeoutMock.extend).not.toHaveBeenCalled(); + }); + + test(`doesn't extend session timeouts for system api requests`, async () => { + const http = setupHttp('/foo'); + const sessionTimeoutMock = createSessionTimeoutMock(); + const interceptor = new SessionTimeoutHttpInterceptor(sessionTimeoutMock, http.anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 401); + + await expect( + http.fetch('/foo-api', { headers: { 'kbn-system-api': 'true' } }) + ).rejects.toMatchInlineSnapshot(`[Error: Unauthorized]`); + + expect(sessionTimeoutMock.extend).not.toHaveBeenCalled(); + }); + + test(`doesn't extend session timeouts when there is no response`, async () => { + const http = setupHttp('/foo'); + const sessionTimeoutMock = createSessionTimeoutMock(); + const interceptor = new SessionTimeoutHttpInterceptor(sessionTimeoutMock, http.anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', new Promise((resolve, reject) => reject(new Error('Network is down')))); + + await expect(http.fetch('/foo-api')).rejects.toMatchInlineSnapshot(`[Error: Network is down]`); + + expect(sessionTimeoutMock.extend).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts new file mode 100644 index 0000000000000..98516cb4a613b --- /dev/null +++ b/x-pack/plugins/security/public/session/session_timeout_http_interceptor.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { HttpInterceptor, HttpErrorResponse, HttpResponse, IAnonymousPaths } from 'src/core/public'; + +import { ISessionTimeout } from './session_timeout'; + +const isSystemAPIRequest = (request: Request) => { + return request.headers.has('kbn-system-api'); +}; + +export class SessionTimeoutHttpInterceptor implements HttpInterceptor { + constructor(private sessionTimeout: ISessionTimeout, private anonymousPaths: IAnonymousPaths) {} + + response(httpResponse: HttpResponse) { + if (this.anonymousPaths.isAnonymous(window.location.pathname)) { + return; + } + + if (isSystemAPIRequest(httpResponse.request)) { + return; + } + + this.sessionTimeout.extend(); + } + + responseError(httpErrorResponse: HttpErrorResponse) { + if (this.anonymousPaths.isAnonymous(window.location.pathname)) { + return; + } + + if (isSystemAPIRequest(httpErrorResponse.request)) { + return; + } + + // if we happen to not have a response, for example if there is no + // network connectivity, we won't extend the session because there + // won't be a response with a set-cookie header, which is required + // to extend the session + const { response } = httpErrorResponse; + if (!response) { + return; + } + + this.sessionTimeout.extend(); + } +} diff --git a/x-pack/legacy/plugins/security/public/components/session_expiration_warning/session_expiration_warning.test.tsx b/x-pack/plugins/security/public/session/session_timeout_warning.test.tsx similarity index 74% rename from x-pack/legacy/plugins/security/public/components/session_expiration_warning/session_expiration_warning.test.tsx rename to x-pack/plugins/security/public/session/session_timeout_warning.test.tsx index abc5a970eec9a..a52e7ce4e94b5 100644 --- a/x-pack/legacy/plugins/security/public/components/session_expiration_warning/session_expiration_warning.test.tsx +++ b/x-pack/plugins/security/public/session/session_timeout_warning.test.tsx @@ -5,12 +5,12 @@ */ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { SessionExpirationWarning } from './session_expiration_warning'; +import { SessionTimeoutWarning } from './session_timeout_warning'; -describe('SessionExpirationWarning', () => { +describe('SessionTimeoutWarning', () => { it('fires its callback when the OK button is clicked', () => { const handler = jest.fn(); - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); expect(handler).toBeCalledTimes(0); wrapper.find('EuiButton[data-test-subj="refreshSessionButton"]').simulate('click'); diff --git a/x-pack/legacy/plugins/security/public/components/session_expiration_warning/session_expiration_warning.tsx b/x-pack/plugins/security/public/session/session_timeout_warning.tsx similarity index 81% rename from x-pack/legacy/plugins/security/public/components/session_expiration_warning/session_expiration_warning.tsx rename to x-pack/plugins/security/public/session/session_timeout_warning.tsx index 2b957e9b251a7..e1b4542031ed1 100644 --- a/x-pack/legacy/plugins/security/public/components/session_expiration_warning/session_expiration_warning.tsx +++ b/x-pack/plugins/security/public/session/session_timeout_warning.tsx @@ -12,12 +12,12 @@ interface Props { onRefreshSession: () => void; } -export const SessionExpirationWarning = (props: Props) => { +export const SessionTimeoutWarning = (props: Props) => { return ( <>

@@ -29,7 +29,7 @@ export const SessionExpirationWarning = (props: Props) => { data-test-subj="refreshSessionButton" > diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts new file mode 100644 index 0000000000000..60f032652221b --- /dev/null +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// @ts-ignore +import fetchMock from 'fetch-mock/es5/client'; +import { SessionExpired } from './session_expired'; +import { setup } from '../../../../../src/test_utils/public/http_test_setup'; +import { UnauthorizedResponseHttpInterceptor } from './unauthorized_response_http_interceptor'; +jest.mock('./session_expired'); + +const drainPromiseQueue = () => { + return new Promise(resolve => { + setImmediate(resolve); + }); +}; + +const mockCurrentUrl = (url: string) => window.history.pushState({}, '', url); + +const setupHttp = (basePath: string) => { + const { http } = setup(injectedMetadata => { + injectedMetadata.getBasePath.mockReturnValue(basePath); + }); + return http; +}; + +afterEach(() => { + fetchMock.restore(); +}); + +it(`logs out 401 responses`, async () => { + const http = setupHttp('/foo'); + const sessionExpired = new SessionExpired(http.basePath); + const logoutPromise = new Promise(resolve => { + jest.spyOn(sessionExpired, 'logout').mockImplementation(() => resolve()); + }); + const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, http.anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 401); + + let fetchResolved = false; + let fetchRejected = false; + http.fetch('/foo-api').then(() => (fetchResolved = true), () => (fetchRejected = true)); + + await logoutPromise; + await drainPromiseQueue(); + expect(fetchResolved).toBe(false); + expect(fetchRejected).toBe(false); +}); + +it(`ignores anonymous paths`, async () => { + mockCurrentUrl('/foo/bar'); + const http = setupHttp('/foo'); + const { anonymousPaths } = http; + anonymousPaths.register('/bar'); + const sessionExpired = new SessionExpired(http.basePath); + const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 401); + + await expect(http.fetch('/foo-api')).rejects.toMatchInlineSnapshot(`[Error: Unauthorized]`); + expect(sessionExpired.logout).not.toHaveBeenCalled(); +}); + +it(`ignores errors which don't have a response, for example network connectivity issues`, async () => { + const http = setupHttp('/foo'); + const sessionExpired = new SessionExpired(http.basePath); + const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, http.anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', new Promise((resolve, reject) => reject(new Error('Network is down')))); + + await expect(http.fetch('/foo-api')).rejects.toMatchInlineSnapshot(`[Error: Network is down]`); + expect(sessionExpired.logout).not.toHaveBeenCalled(); +}); + +it(`ignores requests which omit credentials`, async () => { + const http = setupHttp('/foo'); + const sessionExpired = new SessionExpired(http.basePath); + const interceptor = new UnauthorizedResponseHttpInterceptor(sessionExpired, http.anonymousPaths); + http.intercept(interceptor); + fetchMock.mock('*', 401); + + await expect(http.fetch('/foo-api', { credentials: 'omit' })).rejects.toMatchInlineSnapshot( + `[Error: Unauthorized]` + ); + expect(sessionExpired.logout).not.toHaveBeenCalled(); +}); diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts new file mode 100644 index 0000000000000..a0ef2fdb86b47 --- /dev/null +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + HttpInterceptor, + HttpErrorResponse, + IHttpInterceptController, + IAnonymousPaths, +} from 'src/core/public'; + +import { SessionExpired } from './session_expired'; + +export class UnauthorizedResponseHttpInterceptor implements HttpInterceptor { + constructor(private sessionExpired: SessionExpired, private anonymousPaths: IAnonymousPaths) {} + + responseError(httpErrorResponse: HttpErrorResponse, controller: IHttpInterceptController) { + if (this.anonymousPaths.isAnonymous(window.location.pathname)) { + return; + } + + // if the request was omitting credentials it's to an anonymous endpoint + // (for example to login) and we don't wish to ever redirect + if (httpErrorResponse.request.credentials === 'omit') { + return; + } + + // if we happen to not have a response, for example if there is no + // network connectivity, we don't do anything + const { response } = httpErrorResponse; + if (!response) { + return; + } + + if (response.status === 401) { + this.sessionExpired.logout(); + controller.halt(); + } + } +} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 4ff1459637889..0d8d4d908231f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8549,9 +8549,9 @@ "xpack.security.account.passwordsDoNotMatch": "パスワードが一致していません。", "xpack.security.account.usernameGroupDescription": "この情報は変更できません。", "xpack.security.account.usernameGroupTitle": "ユーザー名とメールアドレス", - "xpack.security.components.sessionExpiration.logoutNotification": "操作がないため間もなくログアウトします。再開するには [OK] をクリックしてくださ。", - "xpack.security.components.sessionExpiration.okButtonText": "OK", - "xpack.security.hacks.warningTitle": "警告", + "xpack.security.components.sessionTimeoutWarning.message": "操作がないため間もなくログアウトします。再開するには [OK] をクリックしてくださ。", + "xpack.security.components.sessionTimeoutWarning.okButtonText": "OK", + "xpack.security.components.sessionTimeoutWarning.title": "警告", "xpack.security.loggedOut.login": "ログイン", "xpack.security.loggedOut.title": "ログアウト完了", "xpack.security.login.basicLoginForm.invalidUsernameOrPasswordErrorMessage": "無効なユーザー名またはパスワード再試行してください。", @@ -10470,4 +10470,4 @@ "xpack.fileUpload.fileParser.errorReadingFile": "ファイルの読み込み中にエラーが発生しました", "xpack.fileUpload.fileParser.noFileProvided": "エラー、ファイルが提供されていません" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 116a1f15a139b..2e99d6d49a8e5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8706,9 +8706,9 @@ "xpack.security.account.passwordsDoNotMatch": "密码不匹配。", "xpack.security.account.usernameGroupDescription": "不能更改此信息。", "xpack.security.account.usernameGroupTitle": "用户名和电子邮件", - "xpack.security.components.sessionExpiration.logoutNotification": "由于处于不活动状态,您即将退出。单击“确定”可以恢复。", - "xpack.security.components.sessionExpiration.okButtonText": "确定", - "xpack.security.hacks.warningTitle": "警告", + "xpack.security.components.sessionTimeoutWarning.message": "由于处于不活动状态,您即将退出。单击“确定”可以恢复。", + "xpack.security.components.sessionTimeoutWarning.okButtonText": "确定", + "xpack.security.components.sessionTimeoutWarning.title": "警告", "xpack.security.loggedOut.login": "登录", "xpack.security.loggedOut.title": "已成功退出", "xpack.security.login.basicLoginForm.invalidUsernameOrPasswordErrorMessage": "用户名或密码无效。请重试。", @@ -10627,4 +10627,4 @@ "xpack.fileUpload.fileParser.errorReadingFile": "读取文件时出错", "xpack.fileUpload.fileParser.noFileProvided": "错误,未提供任何文件" } -} \ No newline at end of file +} From 88f0eba57e67656d11d3ce72ec1e8a7865fdbe2f Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 24 Oct 2019 09:14:47 -0700 Subject: [PATCH 123/191] [ML] Fix tooltip positioning. (#49160) - Moves all DOM manipulation to a ref callback for the ChartTooltip react component. The service mlChartTooltipService no longer touches the DOM, it just passed around data and triggers the chartTooltip$ observable which the ChartTooltip is subscribed to. The code infers positioning now from the tooltips parent element and we no longer rely on hard-coded Kibana classnames. Besides that the code to determine the position remains the same (with some offset tweaking). - The mocha tests for mlChartTooltipService have been migrated to jest. --- .../chart_tooltip/chart_tooltip.tsx | 60 ++++++++++--- .../chart_tooltip/chart_tooltip_service.d.ts | 11 ++- .../chart_tooltip/chart_tooltip_service.js | 86 +++++-------------- ...oltip.js => chart_tooltip_service.test.ts} | 15 ++-- .../plugins/ml/public/explorer/explorer.js | 3 +- .../explorer_chart_distribution.js | 4 +- .../explorer_chart_single_metric.js | 4 +- .../ml/public/explorer/explorer_swimlane.js | 8 +- .../timeseriesexplorer/timeseriesexplorer.js | 1 + 9 files changed, 96 insertions(+), 96 deletions(-) rename x-pack/legacy/plugins/ml/public/components/chart_tooltip/{__tests__/chart_tooltip.js => chart_tooltip_service.test.ts} (50%) diff --git a/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip.tsx b/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip.tsx index 784deb260902b..ea9bc4f0f92ee 100644 --- a/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip.tsx +++ b/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip.tsx @@ -12,7 +12,53 @@ import { TooltipValueFormatter } from '@elastic/charts'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { useObservable } from '../../../../../../../src/plugins/kibana_react/public/util/use_observable'; -import { chartTooltip$, mlChartTooltipService, ChartTooltipValue } from './chart_tooltip_service'; +import { chartTooltip$, ChartTooltipValue } from './chart_tooltip_service'; + +type RefValue = HTMLElement | null; + +function useRefWithCallback() { + const chartTooltipState = useObservable(chartTooltip$); + const ref = useRef(null); + + return (node: RefValue) => { + ref.current = node; + + if ( + node !== null && + node.parentElement !== null && + chartTooltipState !== undefined && + chartTooltipState.isTooltipVisible + ) { + const parentBounding = node.parentElement.getBoundingClientRect(); + + const { targetPosition, offset } = chartTooltipState; + + const contentWidth = document.body.clientWidth - parentBounding.left; + const tooltipWidth = node.clientWidth; + + let left = targetPosition.left + offset.x - parentBounding.left; + if (left + tooltipWidth > contentWidth) { + // the tooltip is hanging off the side of the page, + // so move it to the other side of the target + const markerWidthAdjustment = 25; + left = left - (tooltipWidth + offset.x + markerWidthAdjustment); + } + + const top = targetPosition.top + offset.y - parentBounding.top; + + if ( + chartTooltipState.tooltipPosition.left !== left || + chartTooltipState.tooltipPosition.top !== top + ) { + // render the tooltip with adjusted position. + chartTooltip$.next({ + ...chartTooltipState, + tooltipPosition: { left, top }, + }); + } + } + }; +} const renderHeader = (headerData?: ChartTooltipValue, formatter?: TooltipValueFormatter) => { if (!headerData) { @@ -23,24 +69,18 @@ const renderHeader = (headerData?: ChartTooltipValue, formatter?: TooltipValueFo }; export const ChartTooltip: FC = () => { - const chartTooltipElement = useRef(null); - - mlChartTooltipService.element = chartTooltipElement.current; - const chartTooltipState = useObservable(chartTooltip$); + const chartTooltipElement = useRefWithCallback(); if (chartTooltipState === undefined || !chartTooltipState.isTooltipVisible) { return
; } const { tooltipData, tooltipHeaderFormatter, tooltipPosition } = chartTooltipState; + const transform = `translate(${tooltipPosition.left}px, ${tooltipPosition.top}px)`; return ( -
+
{tooltipData.length > 0 && tooltipData[0].skipHeader === undefined && (
{renderHeader(tooltipData[0], tooltipHeaderFormatter)} diff --git a/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.d.ts b/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.d.ts index 2e80d577adeb6..e6b0b6b4270bd 100644 --- a/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.d.ts +++ b/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.d.ts @@ -8,15 +8,19 @@ import { BehaviorSubject } from 'rxjs'; import { TooltipValue, TooltipValueFormatter } from '@elastic/charts'; +export declare const getChartTooltipDefaultState: () => ChartTooltipState; + export interface ChartTooltipValue extends TooltipValue { skipHeader?: boolean; } interface ChartTooltipState { isTooltipVisible: boolean; + offset: ToolTipOffset; + targetPosition: ClientRect; tooltipData: ChartTooltipValue[]; tooltipHeaderFormatter?: TooltipValueFormatter; - tooltipPosition: { transform: string }; + tooltipPosition: { left: number; top: number }; } export declare const chartTooltip$: BehaviorSubject; @@ -27,11 +31,10 @@ interface ToolTipOffset { } interface MlChartTooltipService { - element: HTMLElement | null; show: ( tooltipData: ChartTooltipValue[], - target: HTMLElement | null, - offset: ToolTipOffset + target?: HTMLElement | null, + offset?: ToolTipOffset ) => void; hide: () => void; } diff --git a/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.js b/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.js index 2177ed9fa2288..8fe1e795df53a 100644 --- a/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.js +++ b/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.js @@ -6,74 +6,32 @@ import { BehaviorSubject } from 'rxjs'; -const doc = document.documentElement; - -const chartTooltipDefaultState = { +export const getChartTooltipDefaultState = () => ({ isTooltipVisible: false, tooltipData: [], - tooltipPosition: { transform: 'translate(0px, 0px)' } -}; + offset: { x: 0, y: 0 }, + targetPosition: { left: 0, top: 0 }, + tooltipPosition: { left: 0, top: 0 } +}); -export const chartTooltip$ = new BehaviorSubject(chartTooltipDefaultState); +export const chartTooltip$ = new BehaviorSubject(getChartTooltipDefaultState()); export const mlChartTooltipService = { - element: null, -}; - -mlChartTooltipService.show = function (tooltipData, target, offset = { x: 0, y: 0 }) { - if (this.element === null || typeof target === 'undefined') { - return; - } - - // side bar width - const euiNavDrawer = document.getElementsByClassName('euiNavDrawer'); - - if (euiNavDrawer.length === 0) { - return; - } - - // enable the tooltip to render it in the DOM - // so the correct `tooltipWidth` gets returned. - const tooltipState = { - ...chartTooltipDefaultState, - isTooltipVisible: true, - tooltipData, - }; - chartTooltip$.next(tooltipState); - - const navOffset = euiNavDrawer[0].clientWidth; // Offset by width of side navbar - const contentWidth = document.body.clientWidth - navOffset; - const tooltipWidth = this.element.clientWidth; - - const pos = target.getBoundingClientRect(); - let left = pos.left + offset.x + 4 - navOffset; - if (left + tooltipWidth > contentWidth) { - // the tooltip is hanging off the side of the page, - // so move it to the other side of the target - const markerWidthAdjustment = 10; - left = left - (tooltipWidth + offset.x + markerWidthAdjustment); + show: (tooltipData, target, offset = { x: 0, y: 0 }) => { + if (typeof target !== 'undefined' && target !== null) { + chartTooltip$.next({ + ...chartTooltip$.getValue(), + isTooltipVisible: true, + offset, + targetPosition: target.getBoundingClientRect(), + tooltipData, + }); + } + }, + hide: () => { + chartTooltip$.next({ + ...getChartTooltipDefaultState(), + isTooltipVisible: false + }); } - - // Calculate top offset - const scrollTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); - const topNavHeightAdjustment = 190; - const top = pos.top + offset.y + scrollTop - topNavHeightAdjustment; - - // render the tooltip with adjusted position. - chartTooltip$.next({ - ...tooltipState, - tooltipPosition: { transform: `translate(${left}px, ${top}px)` } - }); - -}; - -// When selecting multiple cells using dragSelect, we need to quickly -// hide the tooltip with `noTransition`, otherwise, if the mouse pointer -// enters the tooltip while dragging, it will cancel selecting multiple -// swimlane cells which we'd like to avoid of course. -mlChartTooltipService.hide = function () { - chartTooltip$.next({ - ...chartTooltipDefaultState, - isTooltipVisible: false - }); }; diff --git a/x-pack/legacy/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js b/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.test.ts similarity index 50% rename from x-pack/legacy/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js rename to x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.test.ts index a542b5284b70b..aa1dbf92b0677 100644 --- a/x-pack/legacy/plugins/ml/public/components/chart_tooltip/__tests__/chart_tooltip.js +++ b/x-pack/legacy/plugins/ml/public/components/chart_tooltip/chart_tooltip_service.test.ts @@ -4,21 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; - -import { mlChartTooltipService } from '../chart_tooltip_service'; +import { getChartTooltipDefaultState, mlChartTooltipService } from './chart_tooltip_service'; describe('ML - mlChartTooltipService', () => { it('service API duck typing', () => { - expect(mlChartTooltipService).to.be.an('object'); - expect(mlChartTooltipService.show).to.be.a('function'); - expect(mlChartTooltipService.hide).to.be.a('function'); + expect(typeof mlChartTooltipService).toBe('object'); + expect(typeof mlChartTooltipService.show).toBe('function'); + expect(typeof mlChartTooltipService.hide).toBe('function'); }); it('should fail silently when target is not defined', () => { - mlChartTooltipService.element = {}; expect(() => { - mlChartTooltipService.show('', undefined); - }).to.not.throwError('Call to show() should fail silently.'); + mlChartTooltipService.show(getChartTooltipDefaultState().tooltipData, null); + }).not.toThrow('Call to show() should fail silently.'); }); }); diff --git a/x-pack/legacy/plugins/ml/public/explorer/explorer.js b/x-pack/legacy/plugins/ml/public/explorer/explorer.js index 694e61db0583e..1acdd041c4052 100644 --- a/x-pack/legacy/plugins/ml/public/explorer/explorer.js +++ b/x-pack/legacy/plugins/ml/public/explorer/explorer.js @@ -1169,8 +1169,9 @@ export const Explorer = injectI18n(injectObservablesAsProps( return ( -
+ {/* Make sure ChartTooltip is inside this plain wrapping div so positioning can be infered correctly. */} + {noInfluencersConfigured === false && influencers !== undefined && diff --git a/x-pack/legacy/plugins/ml/public/explorer/explorer_charts/explorer_chart_distribution.js b/x-pack/legacy/plugins/ml/public/explorer/explorer_charts/explorer_chart_distribution.js index 82a4744f6aec8..588c3e3d6f1e9 100644 --- a/x-pack/legacy/plugins/ml/public/explorer/explorer_charts/explorer_chart_distribution.js +++ b/x-pack/legacy/plugins/ml/public/explorer/explorer_charts/explorer_chart_distribution.js @@ -498,8 +498,8 @@ export const ExplorerChartDistribution = injectI18n(class ExplorerChartDistribut } mlChartTooltipService.show(tooltipData, circle, { - x: LINE_CHART_ANOMALY_RADIUS * 2, - y: 0 + x: LINE_CHART_ANOMALY_RADIUS * 3, + y: LINE_CHART_ANOMALY_RADIUS * 2, }); } } diff --git a/x-pack/legacy/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.js b/x-pack/legacy/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.js index 2d991172ed345..be85af5a70c40 100644 --- a/x-pack/legacy/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.js +++ b/x-pack/legacy/plugins/ml/public/explorer/explorer_charts/explorer_chart_single_metric.js @@ -444,8 +444,8 @@ export const ExplorerChartSingleMetric = injectI18n(class ExplorerChartSingleMet } mlChartTooltipService.show(tooltipData, circle, { - x: LINE_CHART_ANOMALY_RADIUS * 2, - y: 0 + x: LINE_CHART_ANOMALY_RADIUS * 3, + y: LINE_CHART_ANOMALY_RADIUS * 2, }); } } diff --git a/x-pack/legacy/plugins/ml/public/explorer/explorer_swimlane.js b/x-pack/legacy/plugins/ml/public/explorer/explorer_swimlane.js index d49a1dc0523c4..2ee725b6fda86 100644 --- a/x-pack/legacy/plugins/ml/public/explorer/explorer_swimlane.js +++ b/x-pack/legacy/plugins/ml/public/explorer/explorer_swimlane.js @@ -325,10 +325,10 @@ export const ExplorerSwimlane = injectI18n(class ExplorerSwimlane extends React. yAccessor: 'anomaly_score' }); - const offsets = (target.className === 'sl-cell-inner' ? { x: 0, y: 0 } : { x: 2, y: 1 }); + const offsets = (target.className === 'sl-cell-inner' ? { x: 6, y: 0 } : { x: 8, y: 1 }); mlChartTooltipService.show(tooltipData, target, { - x: target.offsetWidth - offsets.x, - y: 10 + offsets.y + x: target.offsetWidth + offsets.x, + y: 6 + offsets.y }); } @@ -364,7 +364,7 @@ export const ExplorerSwimlane = injectI18n(class ExplorerSwimlane extends React. .on('mouseover', label => { mlChartTooltipService.show([{ skipHeader: true }, { name: swimlaneData.fieldName, value: label }], this, { x: laneLabelWidth, - y: 8 + y: 0 }); }) .on('mouseout', () => { diff --git a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js index 164e5e7b5a778..73d1dd2818042 100644 --- a/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/legacy/plugins/ml/public/timeseriesexplorer/timeseriesexplorer.js @@ -1179,6 +1179,7 @@ export class TimeSeriesExplorer extends React.Component { {(arePartitioningFieldsProvided && jobs.length > 0 && (fullRefresh === false || loading === false) && hasResults === true) && ( + {/* Make sure ChartTooltip is inside this plain wrapping element so positioning can be infered correctly. */} From cd8c708d88c5a6b09df4b8bd19620881f3edf15e Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 24 Oct 2019 18:23:51 +0200 Subject: [PATCH 124/191] Kibana app migration: Centralize home dependencies (#48618) --- .../kibana/public/home/components/add_data.js | 5 +- .../public/home/components/add_data.test.js | 27 ++++--- .../kibana/public/home/components/home.js | 7 +- .../public/home/components/home.test.js | 7 ++ .../public/home/components/home.test.mocks.ts | 24 ++---- .../kibana/public/home/components/home_app.js | 35 +++++--- .../home/components/sample_data_set_cards.js | 21 ++--- .../sample_data_view_data_button.js | 7 +- .../sample_data_view_data_button.test.js | 13 ++- .../tutorial/replace_template_strings.js | 31 ++++--- .../home/components/tutorial/tutorial.js | 4 +- .../home/components/tutorial/tutorial.test.js | 8 ++ .../home/components/tutorial_directory.js | 4 +- .../kibana/public/home/components/welcome.tsx | 28 ++++--- .../core_plugins/kibana/public/home/index.js | 29 +++---- .../kibana/public/home/kibana_services.js | 40 --------- .../kibana/public/home/kibana_services.ts | 81 +++++++++++++++++++ .../kibana/public/home/load_tutorials.js | 7 +- .../kibana/public/home/sample_data_client.js | 24 +++--- 19 files changed, 233 insertions(+), 169 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/home/kibana_services.js create mode 100644 src/legacy/core_plugins/kibana/public/home/kibana_services.ts diff --git a/src/legacy/core_plugins/kibana/public/home/components/add_data.js b/src/legacy/core_plugins/kibana/public/home/components/add_data.js index f8c8e0ec8411f..0a3adfa430a45 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/add_data.js +++ b/src/legacy/core_plugins/kibana/public/home/components/add_data.js @@ -21,7 +21,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; -import chrome from 'ui/chrome'; +import { getServices } from '../kibana_services'; import { EuiButton, @@ -38,10 +38,9 @@ import { EuiFlexGrid, } from '@elastic/eui'; -/* istanbul ignore next */ -const basePath = chrome.getBasePath(); const AddDataUi = ({ apmUiEnabled, isNewKibanaInstance, intl, mlEnabled }) => { + const basePath = getServices().getBasePath(); const renderCards = () => { const apmData = { title: intl.formatMessage({ diff --git a/src/legacy/core_plugins/kibana/public/home/components/add_data.test.js b/src/legacy/core_plugins/kibana/public/home/components/add_data.test.js index d7c8e9daa99da..07f415cfcb1c9 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/add_data.test.js +++ b/src/legacy/core_plugins/kibana/public/home/components/add_data.test.js @@ -20,15 +20,20 @@ import React from 'react'; import { AddData } from './add_data'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; -import chrome from 'ui/chrome'; +import { getServices } from '../kibana_services'; -jest.mock( - 'ui/chrome', - () => ({ +jest.mock('../kibana_services', () =>{ + const mock = { getBasePath: jest.fn(() => 'path'), - }), - { virtual: true } -); + }; + return { + getServices: () => mock, + }; +}); + +beforeEach(() => { + jest.clearAllMocks(); +}); test('render', () => { const component = shallowWithIntl( { isNewKibanaInstance={false} />); expect(component).toMatchSnapshot(); // eslint-disable-line - expect(chrome.getBasePath).toHaveBeenCalledTimes(1); + expect(getServices().getBasePath).toHaveBeenCalledTimes(1); }); test('mlEnabled', () => { @@ -47,7 +52,7 @@ test('mlEnabled', () => { isNewKibanaInstance={false} />); expect(component).toMatchSnapshot(); // eslint-disable-line - expect(chrome.getBasePath).toHaveBeenCalledTimes(1); + expect(getServices().getBasePath).toHaveBeenCalledTimes(1); }); test('apmUiEnabled', () => { @@ -57,7 +62,7 @@ test('apmUiEnabled', () => { isNewKibanaInstance={false} />); expect(component).toMatchSnapshot(); // eslint-disable-line - expect(chrome.getBasePath).toHaveBeenCalledTimes(1); + expect(getServices().getBasePath).toHaveBeenCalledTimes(1); }); test('isNewKibanaInstance', () => { @@ -67,5 +72,5 @@ test('isNewKibanaInstance', () => { isNewKibanaInstance={true} />); expect(component).toMatchSnapshot(); // eslint-disable-line - expect(chrome.getBasePath).toHaveBeenCalledTimes(1); + expect(getServices().getBasePath).toHaveBeenCalledTimes(1); }); diff --git a/src/legacy/core_plugins/kibana/public/home/components/home.js b/src/legacy/core_plugins/kibana/public/home/components/home.js index 6a8dff2ad4fa7..e4c7de9b495a0 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/home.js +++ b/src/legacy/core_plugins/kibana/public/home/components/home.js @@ -22,7 +22,6 @@ import PropTypes from 'prop-types'; import { Synopsis } from './synopsis'; import { AddData } from './add_data'; import { FormattedMessage } from '@kbn/i18n/react'; -import chrome from 'ui/chrome'; import { EuiButton, @@ -40,6 +39,7 @@ import { import { Welcome } from './welcome'; import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; +import { getServices } from '../kibana_services'; const KEY_ENABLE_WELCOME = 'home:welcome:show'; @@ -47,7 +47,10 @@ export class Home extends Component { constructor(props) { super(props); - const isWelcomeEnabled = !(chrome.getInjected('disableWelcomeScreen') || props.localStorage.getItem(KEY_ENABLE_WELCOME) === 'false'); + const isWelcomeEnabled = !( + getServices().getInjected('disableWelcomeScreen') || + props.localStorage.getItem(KEY_ENABLE_WELCOME) === 'false' + ); this.state = { // If welcome is enabled, we wait for loading to complete diff --git a/src/legacy/core_plugins/kibana/public/home/components/home.test.js b/src/legacy/core_plugins/kibana/public/home/components/home.test.js index aa520ba2ed5f9..c21c6fa3d98a5 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/home.test.js +++ b/src/legacy/core_plugins/kibana/public/home/components/home.test.js @@ -25,6 +25,13 @@ import { shallow } from 'enzyme'; import { Home } from './home'; import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; +jest.mock('../kibana_services', () =>({ + getServices: () => ({ + getBasePath: () => 'path', + getInjected: () => '' + }) +})); + describe('home', () => { let defaultProps; diff --git a/src/legacy/core_plugins/kibana/public/home/components/home.test.mocks.ts b/src/legacy/core_plugins/kibana/public/home/components/home.test.mocks.ts index 621c058c803db..cd7bc82fe3345 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/home.test.mocks.ts +++ b/src/legacy/core_plugins/kibana/public/home/components/home.test.mocks.ts @@ -17,7 +17,12 @@ * under the License. */ -import { notificationServiceMock, overlayServiceMock } from '../../../../../../core/public/mocks'; +import { + notificationServiceMock, + overlayServiceMock, + httpServiceMock, + injectedMetadataServiceMock, +} from '../../../../../../core/public/mocks'; jest.doMock('ui/new_platform', () => { return { @@ -29,22 +34,9 @@ jest.doMock('ui/new_platform', () => { npStart: { core: { overlays: overlayServiceMock.createStartContract(), + http: httpServiceMock.createStartContract({ basePath: 'path' }), + injectedMetadata: injectedMetadataServiceMock.createStartContract(), }, }, }; }); - -jest.doMock( - 'ui/chrome', - () => ({ - getBasePath: jest.fn(() => 'path'), - getInjected: jest.fn(() => ''), - }), - { virtual: true } -); - -jest.doMock('ui/capabilities', () => ({ - catalogue: {}, - management: {}, - navLinks: {}, -})); diff --git a/src/legacy/core_plugins/kibana/public/home/components/home_app.js b/src/legacy/core_plugins/kibana/public/home/components/home_app.js index 9aa44863f6d70..005d4bdb0a99e 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/home_app.js +++ b/src/legacy/core_plugins/kibana/public/home/components/home_app.js @@ -26,23 +26,32 @@ import { Tutorial } from './tutorial/tutorial'; import { HashRouter as Router, Switch, - Route + Route, } from 'react-router-dom'; import { getTutorial } from '../load_tutorials'; import { replaceTemplateStrings } from './tutorial/replace_template_strings'; -import { telemetryOptInProvider, shouldShowTelemetryOptIn } from '../kibana_services'; -import chrome from 'ui/chrome'; +import { + getServices +} from '../kibana_services'; export function HomeApp({ directories }) { - const isCloudEnabled = chrome.getInjected('isCloudEnabled', false); - const apmUiEnabled = chrome.getInjected('apmUiEnabled', true); - const mlEnabled = chrome.getInjected('mlEnabled', false); - const savedObjectsClient = chrome.getSavedObjectsClient(); + const { + telemetryOptInProvider, + shouldShowTelemetryOptIn, + getInjected, + savedObjectsClient, + getBasePath, + addBasePath, + } = getServices(); + + const isCloudEnabled = getInjected('isCloudEnabled', false); + const apmUiEnabled = getInjected('apmUiEnabled', true); + const mlEnabled = getInjected('mlEnabled', false); const renderTutorialDirectory = (props) => { return ( @@ -52,7 +61,7 @@ export function HomeApp({ directories }) { const renderTutorial = (props) => { return ( @@ -85,13 +94,13 @@ export function HomeApp({ directories }) { path="/home" > { - return IS_DARK_THEME && sampleDataSet.darkPreviewImagePath ? sampleDataSet.darkPreviewImagePath : sampleDataSet.previewImagePath; + return getServices().uiSettings.get('theme:darkMode') && sampleDataSet.darkPreviewImagePath + ? sampleDataSet.darkPreviewImagePath + : sampleDataSet.previewImagePath; } render() { diff --git a/src/legacy/core_plugins/kibana/public/home/components/sample_data_view_data_button.js b/src/legacy/core_plugins/kibana/public/home/components/sample_data_view_data_button.js index 1df99e9b03d11..89d4909b0c66f 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/sample_data_view_data_button.js +++ b/src/legacy/core_plugins/kibana/public/home/components/sample_data_view_data_button.js @@ -27,9 +27,10 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import chrome from 'ui/chrome'; +import { getServices } from '../kibana_services'; export class SampleDataViewDataButton extends React.Component { + addBasePath = getServices().addBasePath; state = { isPopoverOpen: false @@ -56,7 +57,7 @@ export class SampleDataViewDataButton extends React.Component { datasetName: this.props.name, }, }); - const dashboardPath = chrome.addBasePath(`/app/kibana#/dashboard/${this.props.overviewDashboard}`); + const dashboardPath = this.addBasePath(`/app/kibana#/dashboard/${this.props.overviewDashboard}`); if (this.props.appLinks.length === 0) { return ( @@ -79,7 +80,7 @@ export class SampleDataViewDataButton extends React.Component { size="m" /> ), - href: chrome.addBasePath(path) + href: this.addBasePath(path) }; }); const panels = [ diff --git a/src/legacy/core_plugins/kibana/public/home/components/sample_data_view_data_button.test.js b/src/legacy/core_plugins/kibana/public/home/components/sample_data_view_data_button.test.js index b0551341965fa..cc515993ac061 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/sample_data_view_data_button.test.js +++ b/src/legacy/core_plugins/kibana/public/home/components/sample_data_view_data_button.test.js @@ -17,19 +17,18 @@ * under the License. */ -jest.mock('ui/chrome', () => { - return { - addBasePath: (path) => { - return `root${path}`; - }, - }; -}); import React from 'react'; import { shallow } from 'enzyme'; import { SampleDataViewDataButton } from './sample_data_view_data_button'; +jest.mock('../kibana_services', () =>({ + getServices: () =>({ + addBasePath: path => `root${path}` + }) +})); + test('should render simple button when appLinks is empty', () => { const component = shallow(({ + getServices: () =>({ + getBasePath: jest.fn(() => 'path'), + chrome: { + setBreadcrumbs: () => {} + } + }) +})); jest.mock('../../../../../kibana_react/public', () => { return { Markdown: () =>
, diff --git a/src/legacy/core_plugins/kibana/public/home/components/tutorial_directory.js b/src/legacy/core_plugins/kibana/public/home/components/tutorial_directory.js index eae549f8a6ac0..0c537c8e9ae8a 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/tutorial_directory.js +++ b/src/legacy/core_plugins/kibana/public/home/components/tutorial_directory.js @@ -22,7 +22,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Synopsis } from './synopsis'; import { SampleDataSetCards } from './sample_data_set_cards'; -import chrome from 'ui/chrome'; +import { getServices } from '../kibana_services'; import { EuiPage, @@ -112,7 +112,7 @@ class TutorialDirectoryUi extends React.Component { async componentDidMount() { this._isMounted = true; - chrome.breadcrumbs.set([ + getServices().chrome.setBreadcrumbs([ { text: homeTitle, href: '#/home', diff --git a/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx b/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx index 8869819290263..afe43a23e18cb 100644 --- a/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx +++ b/src/legacy/core_plugins/kibana/public/home/components/welcome.tsx @@ -33,15 +33,11 @@ import { EuiIcon, EuiPortal, } from '@elastic/eui'; -// @ts-ignore -import { banners } from 'ui/notify'; - import { FormattedMessage } from '@kbn/i18n/react'; -import chrome from 'ui/chrome'; +import { getServices } from '../kibana_services'; + import { SampleDataCard } from './sample_data'; import { TelemetryOptInCard } from './telemetry_opt_in'; -// @ts-ignore -import { trackUiMetric, METRIC_TYPE } from '../kibana_services'; interface Props { urlBasePath: string; @@ -51,6 +47,7 @@ interface Props { getTelemetryBannerId: () => string; shouldShowTelemetryOptIn: boolean; } + interface State { step: number; } @@ -59,6 +56,7 @@ interface State { * Shows a full-screen welcome page that gives helpful quick links to beginners. */ export class Welcome extends React.PureComponent { + private services = getServices(); public readonly state: State = { step: 0, }; @@ -70,31 +68,35 @@ export class Welcome extends React.PureComponent { }; private redirecToSampleData() { - const path = chrome.addBasePath('#/home/tutorial_directory/sampleData'); + const path = this.services.addBasePath('#/home/tutorial_directory/sampleData'); window.location.href = path; } + private async handleTelemetrySelection(confirm: boolean) { const metricName = `telemetryOptIn${confirm ? 'Confirm' : 'Decline'}`; - trackUiMetric(METRIC_TYPE.CLICK, metricName); + this.services.trackUiMetric(this.services.METRIC_TYPE.CLICK, metricName); await this.props.setOptIn(confirm); const bannerId = this.props.getTelemetryBannerId(); - banners.remove(bannerId); + this.services.banners.remove(bannerId); this.setState(() => ({ step: 1 })); } private onSampleDataDecline = () => { - trackUiMetric(METRIC_TYPE.CLICK, 'sampleDataDecline'); + this.services.trackUiMetric(this.services.METRIC_TYPE.CLICK, 'sampleDataDecline'); this.props.onSkip(); }; private onSampleDataConfirm = () => { - trackUiMetric(METRIC_TYPE.CLICK, 'sampleDataConfirm'); + this.services.trackUiMetric(this.services.METRIC_TYPE.CLICK, 'sampleDataConfirm'); this.redirecToSampleData(); }; componentDidMount() { - trackUiMetric(METRIC_TYPE.LOADED, 'welcomeScreenMount'); + this.services.trackUiMetric(this.services.METRIC_TYPE.LOADED, 'welcomeScreenMount'); if (this.props.shouldShowTelemetryOptIn) { - trackUiMetric(METRIC_TYPE.COUNT, 'welcomeScreenWithTelemetryOptIn'); + this.services.trackUiMetric( + this.services.METRIC_TYPE.COUNT, + 'welcomeScreenWithTelemetryOptIn' + ); } document.addEventListener('keydown', this.hideOnEsc); } diff --git a/src/legacy/core_plugins/kibana/public/home/index.js b/src/legacy/core_plugins/kibana/public/home/index.js index 8233df680edfd..829d1ef8f0ba4 100644 --- a/src/legacy/core_plugins/kibana/public/home/index.js +++ b/src/legacy/core_plugins/kibana/public/home/index.js @@ -17,17 +17,14 @@ * under the License. */ -import chrome from 'ui/chrome'; -import routes from 'ui/routes'; +import { getServices } from './kibana_services'; import template from './home_ng_wrapper.html'; -import { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue'; -import { wrapInI18nContext } from 'ui/i18n'; -import { uiModules } from 'ui/modules'; import { HomeApp } from './components/home_app'; import { i18n } from '@kbn/i18n'; -import { npStart } from 'ui/new_platform'; + +const { wrapInI18nContext, uiRoutes, uiModules } = getServices(); const app = uiModules.get('apps/home', []); app.directive('homeApp', function (reactDirective) { @@ -39,10 +36,14 @@ const homeTitle = i18n.translate('kbn.home.breadcrumbs.homeTitle', { defaultMess function getRoute() { return { template, - controller($scope, Private) { - $scope.directories = Private(FeatureCatalogueRegistryProvider).inTitleOrder; - $scope.recentlyAccessed = npStart.core.chrome.recentlyAccessed.get().map(item => { - item.link = chrome.addBasePath(item.link); + controller($scope) { + const { chrome, addBasePath, getFeatureCatalogueRegistryProvider } = getServices(); + getFeatureCatalogueRegistryProvider().then(catalogue => { + $scope.directories = catalogue.inTitleOrder; + $scope.$digest(); + }); + $scope.recentlyAccessed = chrome.recentlyAccessed.get().map(item => { + item.link = addBasePath(item.link); return item; }); }, @@ -54,7 +55,7 @@ function getRoute() { // All routing will be handled inside HomeApp via react, we just need to make sure angular doesn't // redirect us to the default page by encountering a url it isn't marked as being able to handle. -routes.when('/home', getRoute()); -routes.when('/home/feature_directory', getRoute()); -routes.when('/home/tutorial_directory/:tab?', getRoute()); -routes.when('/home/tutorial/:id', getRoute()); +uiRoutes.when('/home', getRoute()); +uiRoutes.when('/home/feature_directory', getRoute()); +uiRoutes.when('/home/tutorial_directory/:tab?', getRoute()); +uiRoutes.when('/home/tutorial/:id', getRoute()); diff --git a/src/legacy/core_plugins/kibana/public/home/kibana_services.js b/src/legacy/core_plugins/kibana/public/home/kibana_services.js deleted file mode 100644 index 792c5e09435a4..0000000000000 --- a/src/legacy/core_plugins/kibana/public/home/kibana_services.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { uiModules } from 'ui/modules'; -import { npStart } from 'ui/new_platform'; -import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public'; -import { TelemetryOptInProvider } from '../../../telemetry/public/services'; - -export let indexPatternService; -export let shouldShowTelemetryOptIn; -export let telemetryOptInProvider; - -export const trackUiMetric = createUiStatsReporter('Kibana_home'); -export { METRIC_TYPE }; - -uiModules.get('kibana').run(($injector) => { - const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled'); - const telemetryBanner = npStart.core.injectedMetadata.getInjectedVar('telemetryBanner'); - const Private = $injector.get('Private'); - - telemetryOptInProvider = Private(TelemetryOptInProvider); - shouldShowTelemetryOptIn = telemetryEnabled && telemetryBanner && !telemetryOptInProvider.getOptIn(); - indexPatternService = $injector.get('indexPatterns'); -}); diff --git a/src/legacy/core_plugins/kibana/public/home/kibana_services.ts b/src/legacy/core_plugins/kibana/public/home/kibana_services.ts new file mode 100644 index 0000000000000..39067e2271f28 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/kibana_services.ts @@ -0,0 +1,81 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @ts-ignore +import { toastNotifications, banners } from 'ui/notify'; +import { kfetch } from 'ui/kfetch'; +import chrome from 'ui/chrome'; + +import { wrapInI18nContext } from 'ui/i18n'; + +// @ts-ignore +import { uiModules as modules } from 'ui/modules'; +import routes from 'ui/routes'; +import { npStart } from 'ui/new_platform'; +import { IPrivate } from 'ui/private'; +import { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue'; +import { createUiStatsReporter, METRIC_TYPE } from '../../../ui_metric/public'; +import { TelemetryOptInProvider } from '../../../telemetry/public/services'; +import { start as data } from '../../../data/public/legacy'; + +let shouldShowTelemetryOptIn: boolean; +let telemetryOptInProvider: any; + +export function getServices() { + return { + getInjected: npStart.core.injectedMetadata.getInjectedVar, + metadata: npStart.core.injectedMetadata.getLegacyMetadata(), + docLinks: npStart.core.docLinks, + + uiRoutes: routes, + uiModules: modules, + + savedObjectsClient: npStart.core.savedObjects.client, + chrome: npStart.core.chrome, + uiSettings: npStart.core.uiSettings, + addBasePath: npStart.core.http.basePath.prepend, + getBasePath: npStart.core.http.basePath.get, + + indexPatternService: data.indexPatterns.indexPatterns, + shouldShowTelemetryOptIn, + telemetryOptInProvider, + getFeatureCatalogueRegistryProvider: async () => { + const injector = await chrome.dangerouslyGetActiveInjector(); + const Private = injector.get('Private'); + return Private(FeatureCatalogueRegistryProvider as any); + }, + + trackUiMetric: createUiStatsReporter('Kibana_home'), + METRIC_TYPE, + + toastNotifications, + banners, + kfetch, + wrapInI18nContext, + }; +} + +modules.get('kibana').run((Private: IPrivate) => { + const telemetryEnabled = npStart.core.injectedMetadata.getInjectedVar('telemetryEnabled'); + const telemetryBanner = npStart.core.injectedMetadata.getInjectedVar('telemetryBanner'); + + telemetryOptInProvider = Private(TelemetryOptInProvider); + shouldShowTelemetryOptIn = + telemetryEnabled && telemetryBanner && !telemetryOptInProvider.getOptIn(); +}); diff --git a/src/legacy/core_plugins/kibana/public/home/load_tutorials.js b/src/legacy/core_plugins/kibana/public/home/load_tutorials.js index d6b264154d424..a6f19bc166dc7 100644 --- a/src/legacy/core_plugins/kibana/public/home/load_tutorials.js +++ b/src/legacy/core_plugins/kibana/public/home/load_tutorials.js @@ -18,11 +18,10 @@ */ import _ from 'lodash'; -import chrome from 'ui/chrome'; +import { getServices } from './kibana_services'; import { i18n } from '@kbn/i18n'; -import { toastNotifications } from 'ui/notify'; -const baseUrl = chrome.addBasePath('/api/kibana/home/tutorials'); +const baseUrl = getServices().addBasePath('/api/kibana/home/tutorials'); const headers = new Headers(); headers.append('Accept', 'application/json'); headers.append('Content-Type', 'application/json'); @@ -47,7 +46,7 @@ async function loadTutorials() { tutorials = await response.json(); tutorialsLoaded = true; } catch(err) { - toastNotifications.addDanger({ + getServices().toastNotifications.addDanger({ title: i18n.translate('kbn.home.loadTutorials.unableToLoadErrorMessage', { defaultMessage: 'Unable to load tutorials' } ), diff --git a/src/legacy/core_plugins/kibana/public/home/sample_data_client.js b/src/legacy/core_plugins/kibana/public/home/sample_data_client.js index da46b3e16c093..9411373004c25 100644 --- a/src/legacy/core_plugins/kibana/public/home/sample_data_client.js +++ b/src/legacy/core_plugins/kibana/public/home/sample_data_client.js @@ -17,36 +17,36 @@ * under the License. */ -import { kfetch } from 'ui/kfetch'; -import chrome from 'ui/chrome'; -import { indexPatternService } from './kibana_services'; +import { getServices } from './kibana_services'; const sampleDataUrl = '/api/sample_data'; function clearIndexPatternsCache() { - indexPatternService.clearCache(); + getServices().indexPatternService.clearCache(); } export async function listSampleDataSets() { - return await kfetch({ method: 'GET', pathname: sampleDataUrl }); + return await getServices().kfetch({ method: 'GET', pathname: sampleDataUrl }); } export async function installSampleDataSet(id, sampleDataDefaultIndex) { - await kfetch({ method: 'POST', pathname: `${sampleDataUrl}/${id}` }); + await getServices().kfetch({ method: 'POST', pathname: `${sampleDataUrl}/${id}` }); - if (chrome.getUiSettingsClient().isDefault('defaultIndex')) { - chrome.getUiSettingsClient().set('defaultIndex', sampleDataDefaultIndex); + if (getServices().uiSettings.isDefault('defaultIndex')) { + getServices().uiSettings.set('defaultIndex', sampleDataDefaultIndex); } clearIndexPatternsCache(); } export async function uninstallSampleDataSet(id, sampleDataDefaultIndex) { - await kfetch({ method: 'DELETE', pathname: `${sampleDataUrl}/${id}` }); + await getServices().kfetch({ method: 'DELETE', pathname: `${sampleDataUrl}/${id}` }); - if (!chrome.getUiSettingsClient().isDefault('defaultIndex') - && chrome.getUiSettingsClient().get('defaultIndex') === sampleDataDefaultIndex) { - chrome.getUiSettingsClient().set('defaultIndex', null); + const uiSettings = getServices().uiSettings; + + if (!uiSettings.isDefault('defaultIndex') + && uiSettings.get('defaultIndex') === sampleDataDefaultIndex) { + uiSettings.set('defaultIndex', null); } clearIndexPatternsCache(); From f4cf28f2e81e919ef950c8c97df1c5bb1e1accb7 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Thu, 24 Oct 2019 12:31:02 -0400 Subject: [PATCH 125/191] [ML] Overview: ensure proper permissions check for empty prompt 'Create job' buttons (#49067) * disabled overview empty prompt create job button if no permissions * permission check from overviewPage main component. add mlNodes check to resolver * remove period from overview empty prompt title --- .../analytics_panel/analytics_panel.tsx | 15 +++++++-- .../anomaly_detection_panel.tsx | 16 ++++++++-- .../ml/public/overview/components/content.tsx | 14 +++++++-- .../ml/public/overview/components/sidebar.tsx | 31 +++++++++++++------ .../ml/public/overview/overview_page.tsx | 13 ++++++-- .../plugins/ml/public/overview/route.ts | 2 ++ 6 files changed, 71 insertions(+), 20 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/overview/components/analytics_panel/analytics_panel.tsx b/x-pack/legacy/plugins/ml/public/overview/components/analytics_panel/analytics_panel.tsx index ff7c519829b7c..fb08403b391ef 100644 --- a/x-pack/legacy/plugins/ml/public/overview/components/analytics_panel/analytics_panel.tsx +++ b/x-pack/legacy/plugins/ml/public/overview/components/analytics_panel/analytics_panel.tsx @@ -19,7 +19,10 @@ import { AnalyticsTable } from './table'; import { getAnalyticsFactory } from '../../../data_frame_analytics/pages/analytics_management/services/analytics_service'; import { DataFrameAnalyticsListRow } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/common'; -export const AnalyticsPanel: FC = () => { +interface Props { + jobCreationDisabled: boolean; +} +export const AnalyticsPanel: FC = ({ jobCreationDisabled }) => { const [analytics, setAnalytics] = useState([]); const [errorMessage, setErrorMessage] = useState(undefined); const [isInitialized, setIsInitialized] = useState(false); @@ -67,7 +70,7 @@ export const AnalyticsPanel: FC = () => { title={

{i18n.translate('xpack.ml.overview.analyticsList.createFirstJobMessage', { - defaultMessage: 'Create your first analytics job.', + defaultMessage: 'Create your first analytics job', })}

} @@ -81,7 +84,13 @@ export const AnalyticsPanel: FC = () => { } actions={ - + {i18n.translate('xpack.ml.overview.analyticsList.createJobButtonText', { defaultMessage: 'Create job', })} diff --git a/x-pack/legacy/plugins/ml/public/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx b/x-pack/legacy/plugins/ml/public/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx index 72e17c4d090f4..3c89e72ee4943 100644 --- a/x-pack/legacy/plugins/ml/public/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx +++ b/x-pack/legacy/plugins/ml/public/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx @@ -50,7 +50,11 @@ function getDefaultAnomalyScores(groups: Group[]): MaxScoresByGroup { return anomalyScores; } -export const AnomalyDetectionPanel: FC = () => { +interface Props { + jobCreationDisabled: boolean; +} + +export const AnomalyDetectionPanel: FC = ({ jobCreationDisabled }) => { const [isLoading, setIsLoading] = useState(false); const [groups, setGroups] = useState({}); const [groupsCount, setGroupsCount] = useState(0); @@ -156,7 +160,7 @@ export const AnomalyDetectionPanel: FC = () => { title={

{i18n.translate('xpack.ml.overview.anomalyDetection.createFirstJobMessage', { - defaultMessage: 'Create your first anomaly detection job.', + defaultMessage: 'Create your first anomaly detection job', })}

} @@ -170,7 +174,13 @@ export const AnomalyDetectionPanel: FC = () => { } actions={ - + {i18n.translate('xpack.ml.overview.anomalyDetection.createJobButtonText', { defaultMessage: 'Create job', })} diff --git a/x-pack/legacy/plugins/ml/public/overview/components/content.tsx b/x-pack/legacy/plugins/ml/public/overview/components/content.tsx index 98295fe0a1a49..a285d5c91a266 100644 --- a/x-pack/legacy/plugins/ml/public/overview/components/content.tsx +++ b/x-pack/legacy/plugins/ml/public/overview/components/content.tsx @@ -9,15 +9,23 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { AnomalyDetectionPanel } from './anomaly_detection_panel'; import { AnalyticsPanel } from './analytics_panel/'; +interface Props { + createAnomalyDetectionJobDisabled: boolean; + createAnalyticsJobDisabled: boolean; +} + // Fetch jobs and determine what to show -export const OverviewContent: FC = () => ( +export const OverviewContent: FC = ({ + createAnomalyDetectionJobDisabled, + createAnalyticsJobDisabled, +}) => ( - + - + diff --git a/x-pack/legacy/plugins/ml/public/overview/components/sidebar.tsx b/x-pack/legacy/plugins/ml/public/overview/components/sidebar.tsx index 5a25f9ad54aa1..496beb158f698 100644 --- a/x-pack/legacy/plugins/ml/public/overview/components/sidebar.tsx +++ b/x-pack/legacy/plugins/ml/public/overview/components/sidebar.tsx @@ -17,7 +17,27 @@ const feedbackLink = 'https://www.elastic.co/community/'; const transformsLink = `${chrome.getBasePath()}/app/kibana#/management/elasticsearch/transform`; const whatIsMachineLearningLink = 'https://www.elastic.co/what-is/elasticsearch-machine-learning'; -export const OverviewSideBar: FC = () => ( +interface Props { + createAnomalyDetectionJobDisabled: boolean; +} + +function getCreateJobLink(createAnomalyDetectionJobDisabled: boolean) { + return createAnomalyDetectionJobDisabled === true ? ( + + ) : ( + + + + ); +} + +export const OverviewSideBar: FC = ({ createAnomalyDetectionJobDisabled }) => (

@@ -41,14 +61,7 @@ export const OverviewSideBar: FC = () => ( /> ), - createJob: ( - - - - ), + createJob: getCreateJobLink(createAnomalyDetectionJobDisabled), transforms: ( { + const disableCreateAnomalyDetectionJob = !checkPermission('canCreateJob') || !mlNodesAvailable(); + const disableCreateAnalyticsButton = + !checkPermission('canCreateDataFrameAnalytics') || + !checkPermission('canStartStopDataFrameAnalytics'); return ( - - + + diff --git a/x-pack/legacy/plugins/ml/public/overview/route.ts b/x-pack/legacy/plugins/ml/public/overview/route.ts index 4f5ce7e453f9a..c24b537796a00 100644 --- a/x-pack/legacy/plugins/ml/public/overview/route.ts +++ b/x-pack/legacy/plugins/ml/public/overview/route.ts @@ -5,6 +5,7 @@ */ import uiRoutes from 'ui/routes'; +import { getMlNodeCount } from '../ml_nodes_check/check_ml_nodes'; // @ts-ignore no declaration module import { checkFullLicense } from '../license/check_license'; import { checkGetJobsPrivilege } from '../privilege/check_privilege'; @@ -19,5 +20,6 @@ uiRoutes.when('/overview/?', { resolve: { CheckLicense: checkFullLicense, privileges: checkGetJobsPrivilege, + mlNodeCount: getMlNodeCount, }, }); From 213014bb884679884db2003cda4c9589e6003be4 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Thu, 24 Oct 2019 14:14:27 -0400 Subject: [PATCH 126/191] [SIEM] Remove Timezone since we are using epoch (#49199) * We are using epoch time for our query so we should not using timezone with them * update api integration --- .../siem/common/graphql/shared/schema.gql.ts | 2 - .../components/timeline/helpers.test.tsx | 22 +- .../events/events_over_time/index.tsx | 2 - .../siem/public/containers/query_template.tsx | 1 - .../siem/public/graphql/introspection.json | 6 - .../plugins/siem/public/graphql/types.ts | 2 - .../plugins/siem/public/lib/keury/index.ts | 5 +- .../plugins/siem/public/pages/hosts/hosts.tsx | 2 +- .../siem/public/pages/hosts/hosts_body.tsx | 2 - .../plugins/siem/public/pages/hosts/index.tsx | 417 +++++++++--------- .../navigation/events_query_tab_body.tsx | 2 - .../public/pages/hosts/navigation/types.ts | 1 - .../plugins/siem/server/graphql/types.ts | 2 - .../lib/events/query.events_over_time.dsl.ts | 3 +- .../apis/siem/events_over_time.ts | 2 - 15 files changed, 220 insertions(+), 251 deletions(-) diff --git a/x-pack/legacy/plugins/siem/common/graphql/shared/schema.gql.ts b/x-pack/legacy/plugins/siem/common/graphql/shared/schema.gql.ts index 937b8771ac89b..d043c1587d3c3 100644 --- a/x-pack/legacy/plugins/siem/common/graphql/shared/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/common/graphql/shared/schema.gql.ts @@ -14,8 +14,6 @@ export const sharedSchema = gql` to: Float! "The beginning of the timerange" from: Float! - "The default browser set time zone" - timezone: String } type CursorType { diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.test.tsx index 855c951fbcecc..b30771760bad3 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/helpers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/helpers.test.tsx @@ -156,7 +156,7 @@ describe('Combined Queries', () => { }) ).toEqual({ filterQuery: - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}],"should":[],"must_not":[]}}', + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}],"should":[],"must_not":[]}}', }); }); @@ -174,7 +174,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -194,7 +194,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521848183232,"lte":1521848183232,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521848183232,"lte":1521848183232}}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -214,7 +214,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521848183232,"lte":1521848183232,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521848183232,"lte":1521848183232}}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -234,7 +234,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"match":{"event.end":1521848183232}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"match":{"event.end":1521848183232}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -254,7 +254,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"match":{"event.end":1521848183232}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"match":{"event.end":1521848183232}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -271,7 +271,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -289,7 +289,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -307,7 +307,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}]}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}]}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -327,7 +327,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"bool":{"should":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 3"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 4"}}],"minimum_should_match":1}}]}}]}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 2"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 5"}}],"minimum_should_match":1}}]}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"should":[{"bool":{"should":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 3"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 4"}}],"minimum_should_match":1}}]}}]}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 2"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 5"}}],"minimum_should_match":1}}]}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); @@ -347,7 +347,7 @@ describe('Combined Queries', () => { end: endDate, })!; expect(filterQuery).toEqual( - '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"filter":[{"bool":{"should":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 3"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 4"}}],"minimum_should_match":1}}]}}]}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 2"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 5"}}],"minimum_should_match":1}}]}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}]}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132,"time_zone":"America/New_York"}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253,"time_zone":"America/New_York"}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' + '{"bool":{"must":[],"filter":[{"bool":{"filter":[{"bool":{"filter":[{"bool":{"should":[{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 1"}}],"minimum_should_match":1}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 3"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 4"}}],"minimum_should_match":1}}]}}]}},{"bool":{"filter":[{"bool":{"should":[{"match_phrase":{"name":"Provider 2"}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"name":"Provider 5"}}],"minimum_should_match":1}}]}}],"minimum_should_match":1}},{"bool":{"should":[{"match_phrase":{"host.name":"host-1"}}],"minimum_should_match":1}}]}},{"bool":{"filter":[{"bool":{"should":[{"range":{"@timestamp":{"gte":1521830963132}}}],"minimum_should_match":1}},{"bool":{"should":[{"range":{"@timestamp":{"lte":1521862432253}}}],"minimum_should_match":1}}]}}]}}],"should":[],"must_not":[]}}' ); }); }); diff --git a/x-pack/legacy/plugins/siem/public/containers/events/events_over_time/index.tsx b/x-pack/legacy/plugins/siem/public/containers/events/events_over_time/index.tsx index 6fde630c691b4..77ce98e180ab0 100644 --- a/x-pack/legacy/plugins/siem/public/containers/events/events_over_time/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/events/events_over_time/index.tsx @@ -56,7 +56,6 @@ class EventsOverTimeComponentQuery extends QueryTemplate< isInspected, sourceId, startDate, - timezone, } = this.props; return ( @@ -70,7 +69,6 @@ class EventsOverTimeComponentQuery extends QueryTemplate< interval: '12h', from: startDate!, to: endDate!, - timezone, }, defaultIndex: chrome.getUiSettingsClient().get(DEFAULT_INDEX_KEY), inspect: isInspected, diff --git a/x-pack/legacy/plugins/siem/public/containers/query_template.tsx b/x-pack/legacy/plugins/siem/public/containers/query_template.tsx index 035ebba5ae6ba..b51eac492c48a 100644 --- a/x-pack/legacy/plugins/siem/public/containers/query_template.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/query_template.tsx @@ -17,7 +17,6 @@ export interface QueryTemplateProps { skip?: boolean; sourceId: string; startDate?: number; - timezone?: string; } // eslint-disable-next-line @typescript-eslint/no-explicit-any type FetchMoreOptionsArgs = FetchMoreQueryOptions & diff --git a/x-pack/legacy/plugins/siem/public/graphql/introspection.json b/x-pack/legacy/plugins/siem/public/graphql/introspection.json index cc9438d67bd26..0348b283ed318 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/introspection.json +++ b/x-pack/legacy/plugins/siem/public/graphql/introspection.json @@ -2351,12 +2351,6 @@ "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } }, "defaultValue": null - }, - { - "name": "timezone", - "description": "The default browser set time zone", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null } ], "interfaces": null, diff --git a/x-pack/legacy/plugins/siem/public/graphql/types.ts b/x-pack/legacy/plugins/siem/public/graphql/types.ts index 332592a64dfa5..50fb6bd9e8a8a 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/public/graphql/types.ts @@ -27,8 +27,6 @@ export interface TimerangeInput { to: number; /** The beginning of the timerange */ from: number; - /** The default browser set time zone */ - timezone?: Maybe; } export interface PaginationInputPaginated { diff --git a/x-pack/legacy/plugins/siem/public/lib/keury/index.ts b/x-pack/legacy/plugins/siem/public/lib/keury/index.ts index 0c78fb9d6f45f..7bd8560a1770a 100644 --- a/x-pack/legacy/plugins/siem/public/lib/keury/index.ts +++ b/x-pack/legacy/plugins/siem/public/lib/keury/index.ts @@ -87,7 +87,10 @@ export const convertToBuildEsQuery = ({ }) => { try { return JSON.stringify( - buildEsQuery(indexPattern, queries, filters.filter(f => f.meta.disabled === false), config) + buildEsQuery(indexPattern, queries, filters.filter(f => f.meta.disabled === false), { + ...config, + dateFormatTZ: null, + }) ); } catch (exp) { return ''; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx index fc969974609ea..7c54745f872a9 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx @@ -52,7 +52,7 @@ interface HostsComponentDispatchProps { }>; } -export type HostsQueryProps = { timezone?: string } & GlobalTimeArgs; +export type HostsQueryProps = GlobalTimeArgs; export type HostsComponentProps = HostsComponentReduxProps & HostsComponentDispatchProps & diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx index 242c66bb3a9ee..3d7e54b4a19ac 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx @@ -33,7 +33,6 @@ const HostsBodyComponent = memo( query, setAbsoluteRangeDatePicker, setQuery, - timezone, to, }) => { const core = useKibanaCore(); @@ -55,7 +54,6 @@ const HostsBodyComponent = memo( skip: isInitializing, setQuery, startDate: from, - timezone, type: hostsModel.HostsType.page, indexPattern, narrowDateRange: (score: Anomaly, interval: string) => { diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx index 840c65af8229e..6596d4c65c00e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx @@ -20,8 +20,6 @@ import { HostsTableType } from '../../store/hosts/model'; import { GlobalTime } from '../../containers/global_time'; import { SiemPageName } from '../home/types'; import { Hosts } from './hosts'; -import { useKibanaUiSetting } from '../../lib/settings/use_kibana_ui_setting'; -import { DEFAULT_TIMEZONE_BROWSER } from '../../../common/constants'; const hostsPagePath = `/:pageName(${SiemPageName.hosts})`; @@ -42,223 +40,214 @@ const getHostDetailsTabPath = (pagePath: string) => type Props = Partial> & { url: string }; -export const HostsContainer = React.memo(({ url }) => { - const [timezone] = useKibanaUiSetting(DEFAULT_TIMEZONE_BROWSER); - return ( - - {({ to, from, setQuery, deleteQuery, isInitializing }) => ( - - ( +export const HostsContainer = React.memo(({ url }) => ( + + {({ to, from, setQuery, deleteQuery, isInitializing }) => ( + + ( + ( + <> + + + + )} + /> + )} + /> + ( + <> + ( - <> - - - + )} /> - )} - /> - ( - <> - - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - - )} - /> - ( - <> - - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - - )} - /> - ( - ( + + )} + /> + ( + + )} + /> + ( + + )} /> - )} - /> - ( - ( + + )} + /> + + )} + /> + ( + <> + + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} + /> + ( + + )} /> - )} - /> - - )} - - ); -}); + + )} + /> + ( + + )} + /> + ( + + )} + /> + + )} + +)); HostsContainer.displayName = 'HostsContainer'; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx index 53bf73a1b9b7b..808565cadfa46 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx @@ -21,7 +21,6 @@ export const EventsQueryTabBody = ({ filterQuery, setQuery, startDate, - timezone, updateDateRange = () => {}, }: HostsComponentsQueryProps) => { return ( @@ -31,7 +30,6 @@ export const EventsQueryTabBody = ({ filterQuery={filterQuery} sourceId="default" startDate={startDate} - timezone={timezone} type={hostsModel.HostsType.page} > {({ eventsOverTime, loading, id, inspect, refetch, totalCount }) => ( diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/types.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/types.ts index 552426602cdc5..d567038a05bd8 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/types.ts @@ -29,7 +29,6 @@ interface QueryTabBodyProps { type: hostsModel.HostsType; startDate: number; endDate: number; - timezone?: string; filterQuery?: string | ESTermQuery; } diff --git a/x-pack/legacy/plugins/siem/server/graphql/types.ts b/x-pack/legacy/plugins/siem/server/graphql/types.ts index a87d321fc68d2..776efeebd6ddb 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/types.ts @@ -29,8 +29,6 @@ export interface TimerangeInput { to: number; /** The beginning of the timerange */ from: number; - /** The default browser set time zone */ - timezone?: Maybe; } export interface PaginationInputPaginated { diff --git a/x-pack/legacy/plugins/siem/server/lib/events/query.events_over_time.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/events/query.events_over_time.dsl.ts index 357c1c24119bb..e655485638e16 100644 --- a/x-pack/legacy/plugins/siem/server/lib/events/query.events_over_time.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/events/query.events_over_time.dsl.ts @@ -8,7 +8,7 @@ import { RequestBasicOptions } from '../framework'; export const buildEventsOverTimeQuery = ({ filterQuery, - timerange: { from, timezone, to }, + timerange: { from, to }, defaultIndex, sourceConfiguration: { fields: { timestamp }, @@ -21,7 +21,6 @@ export const buildEventsOverTimeQuery = ({ [timestamp]: { gte: from, lte: to, - ...(timezone && { time_zone: timezone }), }, }, }, diff --git a/x-pack/test/api_integration/apis/siem/events_over_time.ts b/x-pack/test/api_integration/apis/siem/events_over_time.ts index 253dbbab77c3c..10b81734b7b79 100644 --- a/x-pack/test/api_integration/apis/siem/events_over_time.ts +++ b/x-pack/test/api_integration/apis/siem/events_over_time.ts @@ -29,7 +29,6 @@ export default function({ getService }: FtrProviderContext) { interval: '12h', to: TO, from: FROM, - timezone: 'America/Denver', }, defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], inspect: false, @@ -70,7 +69,6 @@ export default function({ getService }: FtrProviderContext) { interval: '12h', to: TO, from: FROM, - timezone: 'America/Denver', }, defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], inspect: false, From adc204e7e63ab7f264530a0a455eb8c69f26f546 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 24 Oct 2019 13:06:35 -0700 Subject: [PATCH 127/191] disable flaky suite (#48617) --- x-pack/test/api_integration/apis/code/feature_controls.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/code/feature_controls.ts b/x-pack/test/api_integration/apis/code/feature_controls.ts index a96b3074e4f81..c72ff362a9a9c 100644 --- a/x-pack/test/api_integration/apis/code/feature_controls.ts +++ b/x-pack/test/api_integration/apis/code/feature_controls.ts @@ -121,7 +121,8 @@ export default function featureControlsTests({ getService }: FtrProviderContext) } } - describe('feature controls', () => { + // FLAKY: https://github.com/elastic/kibana/issues/48617 + describe.skip('feature controls', () => { const codeAdminUsername = 'code_admin_user'; const codeAdminRoleName = 'code_admin_role'; const codeAdminUserPassword = `${codeAdminUsername}-password`; From 48313f73f63eae135f68766d8579603b9622f4dd Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 24 Oct 2019 14:57:46 -0600 Subject: [PATCH 128/191] [Maps] add unique count metric aggregation (#48961) * [Maps] add unique count metric aggregation * do not format unique_count aggregation results * do not format value in legend for unique count * update heatmap docs * one more doc change --- docs/maps/heatmap-layer.asciidoc | 4 +-- .../legacy/plugins/maps/common/constants.js | 9 +++++++ .../maps/public/components/metric_editor.js | 13 ++++++---- .../maps/public/components/metric_select.js | 17 +++++++++---- .../maps/public/components/metrics_editor.js | 3 ++- .../resources/metrics_expression.js | 8 +++--- .../es_geo_grid_source/es_geo_grid_source.js | 19 +++++++++----- .../update_source_editor.js | 3 ++- .../es_pew_pew_source/es_pew_pew_source.js | 19 +++++++++----- .../es_search_source/es_search_source.js | 5 ---- .../maps/public/layers/sources/es_source.js | 22 ++++++++-------- .../public/layers/sources/es_term_source.js | 25 ++++++++++++------- .../tooltips/es_aggmetric_tooltip_property.js | 3 ++- 13 files changed, 94 insertions(+), 56 deletions(-) diff --git a/docs/maps/heatmap-layer.asciidoc b/docs/maps/heatmap-layer.asciidoc index 9d456c59b69ef..77b6d929a931c 100644 --- a/docs/maps/heatmap-layer.asciidoc +++ b/docs/maps/heatmap-layer.asciidoc @@ -13,6 +13,6 @@ You can create a heat map layer from the following data source: Set *Show as* to *heat map*. The index must contain at least one field mapped as {ref}/geo-point.html[geo_point]. -NOTE: Only count and sum metric aggregations are available with the grid aggregation source and heat map layers. -Mean, median, min, and max are turned off because the heat map will blend nearby values. +NOTE: Only count, sum, unique count metric aggregations are available with the grid aggregation source and heat map layers. +Average, min, and max are turned off because the heat map will blend nearby values. Blending two average values would make the cluster more prominent, even though it just might literally mean that these nearby areas are average. diff --git a/x-pack/legacy/plugins/maps/common/constants.js b/x-pack/legacy/plugins/maps/common/constants.js index 1fd1f4b43bbda..942d0a21123c2 100644 --- a/x-pack/legacy/plugins/maps/common/constants.js +++ b/x-pack/legacy/plugins/maps/common/constants.js @@ -102,3 +102,12 @@ export const DRAW_TYPE = { BOUNDS: 'BOUNDS', POLYGON: 'POLYGON' }; + +export const METRIC_TYPE = { + AVG: 'avg', + COUNT: 'count', + MAX: 'max', + MIN: 'min', + SUM: 'sum', + UNIQUE_COUNT: 'cardinality', +}; diff --git a/x-pack/legacy/plugins/maps/public/components/metric_editor.js b/x-pack/legacy/plugins/maps/public/components/metric_editor.js index f3123d5645ccd..03d364f3d84a9 100644 --- a/x-pack/legacy/plugins/maps/public/components/metric_editor.js +++ b/x-pack/legacy/plugins/maps/public/components/metric_editor.js @@ -12,6 +12,7 @@ import { EuiFieldText, EuiFormRow } from '@elastic/eui'; import { MetricSelect, METRIC_AGGREGATION_VALUES } from './metric_select'; import { SingleFieldSelect } from './single_field_select'; +import { METRIC_TYPE } from '../../common/constants'; export function MetricEditor({ fields, metricsFilter, metric, onChange, removeButton }) { const onAggChange = metricAggregationType => { @@ -34,10 +35,12 @@ export function MetricEditor({ fields, metricsFilter, metric, onChange, removeBu }; let fieldSelect; - if (metric.type && metric.type !== 'count') { - const filterNumberFields = field => { - return field.type === 'number'; - }; + if (metric.type && metric.type !== METRIC_TYPE.COUNT) { + const filterField = metric.type !== METRIC_TYPE.UNIQUE_COUNT + ? field => { + return field.type === 'number'; + } + : undefined; fieldSelect = ( { - if (type === 'count') { + if (type === METRIC_TYPE.COUNT) { return true; } @@ -69,7 +71,7 @@ export class MetricsExpression extends Component { }) .map(({ type, field }) => { // do not use metric label so field and aggregation are not obscured. - if (type === 'count') { + if (type === METRIC_TYPE.COUNT) { return 'count'; } @@ -127,6 +129,6 @@ MetricsExpression.propTypes = { MetricsExpression.defaultProps = { metrics: [ - { type: 'count' } + { type: METRIC_TYPE.COUNT } ] }; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index 8416ef5709e30..776980e17bb13 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -21,7 +21,7 @@ import { RENDER_AS } from './render_as'; import { CreateSourceEditor } from './create_source_editor'; import { UpdateSourceEditor } from './update_source_editor'; import { GRID_RESOLUTION } from '../../grid_resolution'; -import { SOURCE_DATA_ID_ORIGIN, ES_GEO_GRID } from '../../../../common/constants'; +import { SOURCE_DATA_ID_ORIGIN, ES_GEO_GRID, METRIC_TYPE } from '../../../../common/constants'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; @@ -36,9 +36,16 @@ const aggSchemas = new Schemas([ title: 'Value', min: 1, max: Infinity, - aggFilter: ['avg', 'count', 'max', 'min', 'sum'], + aggFilter: [ + METRIC_TYPE.AVG, + METRIC_TYPE.COUNT, + METRIC_TYPE.MAX, + METRIC_TYPE.MIN, + METRIC_TYPE.SUM, + METRIC_TYPE.UNIQUE_COUNT + ], defaults: [ - { schema: 'metric', type: 'count' } + { schema: 'metric', type: METRIC_TYPE.COUNT } ] }, { @@ -215,11 +222,11 @@ export class ESGeoGridSource extends AbstractESSource { } _formatMetricKey(metric) { - return metric.type !== 'count' ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME; + return metric.type !== METRIC_TYPE.COUNT ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME; } _formatMetricLabel(metric) { - return metric.type !== 'count' ? `${metric.type} of ${metric.field}` : COUNT_PROP_LABEL; + return metric.type !== METRIC_TYPE.COUNT ? `${metric.type} of ${metric.field}` : COUNT_PROP_LABEL; } _makeAggConfigs(precision) { @@ -231,7 +238,7 @@ export class ESGeoGridSource extends AbstractESSource { schema: 'metric', params: {} }; - if (metric.type !== 'count') { + if (metric.type !== METRIC_TYPE.COUNT) { metricAggConfig.params = { field: metric.field }; } return metricAggConfig; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js index bed8236da1be8..9ea5093724ed9 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/update_source_editor.js @@ -8,6 +8,7 @@ import React, { Fragment, Component } from 'react'; import { RENDER_AS } from './render_as'; import { MetricsEditor } from '../../../components/metrics_editor'; +import { METRIC_TYPE } from '../../../../common/constants'; import { indexPatternService } from '../../../kibana_services'; import { ResolutionEditor } from './resolution_editor'; import { i18n } from '@kbn/i18n'; @@ -66,7 +67,7 @@ export class UpdateSourceEditor extends Component { this.props.renderAs === RENDER_AS.HEATMAP ? metric => { //these are countable metrics, where blending heatmap color blobs make sense - return ['count', 'sum'].includes(metric.value); + return [METRIC_TYPE.COUNT, METRIC_TYPE.SUM, METRIC_TYPE.UNIQUE_COUNT].includes(metric.value); } : null; const allowMultipleMetrics = this.props.renderAs !== RENDER_AS.HEATMAP; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js index 4c081d386b3d7..3debfdf1541f7 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js @@ -15,7 +15,7 @@ import { UpdateSourceEditor } from './update_source_editor'; import { VectorStyle } from '../../styles/vector_style'; import { vectorStyles } from '../../styles/vector_style_defaults'; import { i18n } from '@kbn/i18n'; -import { SOURCE_DATA_ID_ORIGIN, ES_PEW_PEW } from '../../../../common/constants'; +import { SOURCE_DATA_ID_ORIGIN, ES_PEW_PEW, METRIC_TYPE } from '../../../../common/constants'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { convertToLines } from './convert_to_lines'; import { Schemas } from 'ui/vis/editors/default/schemas'; @@ -32,9 +32,16 @@ const aggSchemas = new Schemas([ title: 'Value', min: 1, max: Infinity, - aggFilter: ['avg', 'count', 'max', 'min', 'sum'], + aggFilter: [ + METRIC_TYPE.AVG, + METRIC_TYPE.COUNT, + METRIC_TYPE.MAX, + METRIC_TYPE.MIN, + METRIC_TYPE.SUM, + METRIC_TYPE.UNIQUE_COUNT + ], defaults: [ - { schema: 'metric', type: 'count' } + { schema: 'metric', type: METRIC_TYPE.COUNT } ] } ]); @@ -193,7 +200,7 @@ export class ESPewPewSource extends AbstractESSource { schema: 'metric', params: {} }; - if (metric.type !== 'count') { + if (metric.type !== METRIC_TYPE.COUNT) { metricAggConfig.params = { field: metric.field }; } return metricAggConfig; @@ -252,11 +259,11 @@ export class ESPewPewSource extends AbstractESSource { } _formatMetricKey(metric) { - return metric.type !== 'count' ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME; + return metric.type !== METRIC_TYPE.COUNT ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME; } _formatMetricLabel(metric) { - return metric.type !== 'count' ? `${metric.type} of ${metric.field}` : COUNT_PROP_LABEL; + return metric.type !== METRIC_TYPE.COUNT ? `${metric.type} of ${metric.field}` : COUNT_PROP_LABEL; } async _getGeoField() { diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js index 7c248e332d403..d9c48424bb77d 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js @@ -512,9 +512,4 @@ export class ESSearchSource extends AbstractESSource { path: geoField.name, }; } - - _getRawFieldName(fieldName) { - // fieldName is rawFieldName for documents source since the source uses raw documents instead of aggregated metrics - return fieldName; - } } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js index 0670474df89bb..85c866479a6ba 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js @@ -19,7 +19,7 @@ import { ESAggMetricTooltipProperty } from '../tooltips/es_aggmetric_tooltip_pro import uuid from 'uuid/v4'; import { copyPersistentState } from '../../reducers/util'; -import { ES_GEO_FIELD_TYPE } from '../../../common/constants'; +import { ES_GEO_FIELD_TYPE, METRIC_TYPE } from '../../../common/constants'; import { DataRequestAbortError } from '../util/data_request'; export class AbstractESSource extends AbstractVectorSource { @@ -59,7 +59,7 @@ export class AbstractESSource extends AbstractVectorSource { _getValidMetrics() { const metrics = _.get(this._descriptor, 'metrics', []).filter(({ type, field }) => { - if (type === 'count') { + if (type === METRIC_TYPE.COUNT) { return true; } @@ -69,7 +69,7 @@ export class AbstractESSource extends AbstractVectorSource { return false; }); if (metrics.length === 0) { - metrics.push({ type: 'count' }); + metrics.push({ type: METRIC_TYPE.COUNT }); } return metrics; } @@ -300,18 +300,13 @@ export class AbstractESSource extends AbstractVectorSource { return this._descriptor.id; } - _getRawFieldName(fieldName) { + async getFieldFormatter(fieldName) { const metricField = this.getMetricFields().find(({ propertyKey }) => { return propertyKey === fieldName; }); - return metricField ? metricField.field : null; - } - - async getFieldFormatter(fieldName) { - // fieldName could be an aggregation so it needs to be unpacked to expose raw field. - const rawFieldName = this._getRawFieldName(fieldName); - if (!rawFieldName) { + // Do not use field formatters for counting metrics + if (metricField && metricField.type === METRIC_TYPE.COUNT || metricField.type === METRIC_TYPE.UNIQUE_COUNT) { return null; } @@ -322,7 +317,10 @@ export class AbstractESSource extends AbstractVectorSource { return null; } - const fieldFromIndexPattern = indexPattern.fields.getByName(rawFieldName); + const realFieldName = metricField + ? metricField.field + : fieldName; + const fieldFromIndexPattern = indexPattern.fields.getByName(realFieldName); if (!fieldFromIndexPattern) { return null; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js index 5d876dbbd011f..1f5adc00cca6f 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js @@ -11,7 +11,7 @@ import { Schemas } from 'ui/vis/editors/default/schemas'; import { AggConfigs } from 'ui/agg_types'; import { i18n } from '@kbn/i18n'; import { ESTooltipProperty } from '../tooltips/es_tooltip_property'; -import { ES_SIZE_LIMIT } from '../../../common/constants'; +import { ES_SIZE_LIMIT, METRIC_TYPE } from '../../../common/constants'; const TERMS_AGG_NAME = 'join'; @@ -22,9 +22,16 @@ const aggSchemas = new Schemas([ title: 'Value', min: 1, max: Infinity, - aggFilter: ['avg', 'count', 'max', 'min', 'sum'], + aggFilter: [ + METRIC_TYPE.AVG, + METRIC_TYPE.COUNT, + METRIC_TYPE.MAX, + METRIC_TYPE.MIN, + METRIC_TYPE.SUM, + METRIC_TYPE.UNIQUE_COUNT + ], defaults: [ - { schema: 'metric', type: 'count' } + { schema: 'metric', type: METRIC_TYPE.COUNT } ] }, { @@ -81,12 +88,12 @@ export class ESTermSource extends AbstractESSource { } _formatMetricKey(metric) { - const metricKey = metric.type !== 'count' ? `${metric.type}_of_${metric.field}` : metric.type; + const metricKey = metric.type !== METRIC_TYPE.COUNT ? `${metric.type}_of_${metric.field}` : metric.type; return `__kbnjoin__${metricKey}_groupby_${this._descriptor.indexPatternTitle}.${this._descriptor.term}`; } _formatMetricLabel(metric) { - const metricLabel = metric.type !== 'count' ? `${metric.type} ${metric.field}` : 'count'; + const metricLabel = metric.type !== METRIC_TYPE.COUNT ? `${metric.type} ${metric.field}` : 'count'; return `${metricLabel} of ${this._descriptor.indexPatternTitle}:${this._descriptor.term}`; } @@ -108,13 +115,13 @@ export class ESTermSource extends AbstractESSource { const metricPropertyNames = configStates .filter(configState => { - return configState.schema === 'metric' && configState.type !== 'count'; + return configState.schema === 'metric' && configState.type !== METRIC_TYPE.COUNT; }) .map(configState => { return configState.id; }); const countConfigState = configStates.find(configState => { - return configState.type === 'count'; + return configState.type === METRIC_TYPE.COUNT; }); const countPropertyName = _.get(countConfigState, 'id'); return { @@ -128,7 +135,7 @@ export class ESTermSource extends AbstractESSource { _getRequestDescription(leftSourceName, leftFieldName) { const metrics = this._getValidMetrics().map(metric => { - return metric.type !== 'count' ? `${metric.type} ${metric.field}` : 'count'; + return metric.type !== METRIC_TYPE.COUNT ? `${metric.type} ${metric.field}` : 'count'; }); const joinStatement = []; joinStatement.push(i18n.translate('xpack.maps.source.esJoin.joinLeftDescription', { @@ -157,7 +164,7 @@ export class ESTermSource extends AbstractESSource { schema: 'metric', params: {} }; - if (metric.type !== 'count') { + if (metric.type !== METRIC_TYPE.COUNT) { metricAggConfig.params = { field: metric.field }; } return metricAggConfig; diff --git a/x-pack/legacy/plugins/maps/public/layers/tooltips/es_aggmetric_tooltip_property.js b/x-pack/legacy/plugins/maps/public/layers/tooltips/es_aggmetric_tooltip_property.js index 11cbb36f49593..42629e192c27d 100644 --- a/x-pack/legacy/plugins/maps/public/layers/tooltips/es_aggmetric_tooltip_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/tooltips/es_aggmetric_tooltip_property.js @@ -6,6 +6,7 @@ import { ESTooltipProperty } from './es_tooltip_property'; +import { METRIC_TYPE } from '../../../common/constants'; export class ESAggMetricTooltipProperty extends ESTooltipProperty { @@ -21,7 +22,7 @@ export class ESAggMetricTooltipProperty extends ESTooltipProperty { if (typeof this._rawValue === 'undefined') { return '-'; } - if (this._metricField.type === 'count') { + if (this._metricField.type === METRIC_TYPE.COUNT || this._metricField.type === METRIC_TYPE.UNIQUE_COUNT) { return this._rawValue; } const indexPatternField = this._indexPattern.fields.getByName(this._metricField.field); From f601ab4c5410a60b3fdb23dde11688fbb91b55d2 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Thu, 24 Oct 2019 17:26:24 -0500 Subject: [PATCH 129/191] [SIEM] Fields browser, auto selects category bugfix (#48999) --- .../fields_browser/category_columns.test.tsx | 4 +- .../fields_browser/category_columns.tsx | 4 +- .../components/fields_browser/index.test.tsx | 55 +++++++++++++++++-- .../components/fields_browser/index.tsx | 11 ++-- 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.test.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.test.tsx index 6406c4609a266..0a8fd9b54f4aa 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.test.tsx @@ -112,7 +112,7 @@ describe('getCategoryColumns', () => { expect( wrapper.find(`.field-browser-category-pane-${selectedCategoryId}-${timelineId}`).first() - ).toHaveStyleRule('font-weight', 'bold'); + ).toHaveStyleRule('font-weight', 'bold', { modifier: '.euiText' }); }); test('it does NOT render an un-selected category with bold text', () => { @@ -135,7 +135,7 @@ describe('getCategoryColumns', () => { expect( wrapper.find(`.field-browser-category-pane-${notTheSelectedCategoryId}-${timelineId}`).first() - ).toHaveStyleRule('font-weight', 'normal'); + ).toHaveStyleRule('font-weight', 'normal', { modifier: '.euiText' }); }); test('it invokes onCategorySelected when a user clicks a category', () => { diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.tsx index 2581fba75da1e..1845a0bae88d5 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/category_columns.tsx @@ -26,7 +26,9 @@ import { LoadingSpinner, getCategoryPaneCategoryClassName, getFieldCount } from import * as i18n from './translations'; const CategoryName = styled.span<{ bold: boolean }>` - font-weight: ${({ bold }) => (bold ? 'bold' : 'normal')}; + .euiText { + font-weight: ${({ bold }) => (bold ? 'bold' : 'normal')}; + } `; CategoryName.displayName = 'CategoryName'; diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx index 4c9c1fc4147ab..2a13d1549d90a 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx @@ -13,9 +13,18 @@ import { TestProviders } from '../../mock'; import { FIELD_BROWSER_HEIGHT, FIELD_BROWSER_WIDTH } from './helpers'; -import { StatefulFieldsBrowser } from '.'; - +import { INPUT_TIMEOUT, StatefulFieldsBrowser } from '.'; +// Suppress warnings about "act" until async/await syntax is supported: https://github.com/facebook/react/issues/14769 +/* eslint-disable no-console */ +const originalError = console.error; describe('StatefulFieldsBrowser', () => { + beforeAll(() => { + console.error = jest.fn(); + }); + + afterAll(() => { + console.error = originalError; + }); const timelineId = 'test'; test('it renders the Fields button, which displays the fields browser on click', () => { @@ -85,6 +94,9 @@ describe('StatefulFieldsBrowser', () => { }); describe('updateSelectedCategoryId', () => { + beforeEach(() => { + jest.setTimeout(10000); + }); test('it updates the selectedCategoryId state, which makes the category bold, when the user clicks a category name in the left hand side of the field browser', () => { const wrapper = mount( @@ -111,10 +123,45 @@ describe('StatefulFieldsBrowser', () => { .simulate('click'); wrapper.update(); - expect( wrapper.find(`.field-browser-category-pane-auditd-${timelineId}`).first() - ).toHaveStyleRule('font-weight', 'bold'); + ).toHaveStyleRule('font-weight', 'bold', { modifier: '.euiText' }); + }); + test('it updates the selectedCategoryId state according to most fields returned', done => { + const wrapper = mount( + + + + ); + + wrapper + .find('[data-test-subj="show-field-browser"]') + .first() + .simulate('click'); + expect( + wrapper.find(`.field-browser-category-pane-cloud-${timelineId}`).first() + ).toHaveStyleRule('font-weight', 'normal', { modifier: '.euiText' }); + wrapper + .find('[data-test-subj="field-search"]') + .last() + .simulate('change', { target: { value: 'cloud' } }); + + setTimeout(() => { + wrapper.update(); + expect( + wrapper.find(`.field-browser-category-pane-cloud-${timelineId}`).first() + ).toHaveStyleRule('font-weight', 'bold', { modifier: '.euiText' }); + wrapper.unmount(); + done(); + }, INPUT_TIMEOUT); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx index 7d21e1f44d04b..a58721eb5a87f 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx @@ -23,7 +23,7 @@ import { FieldBrowserProps } from './types'; const fieldsButtonClassName = 'fields-button'; /** wait this many ms after the user completes typing before applying the filter input */ -const INPUT_TIMEOUT = 250; +export const INPUT_TIMEOUT = 250; const FieldsBrowserButtonContainer = styled.div` position: relative; @@ -94,19 +94,18 @@ export const StatefulFieldsBrowserComponent = React.memo { const newFilteredBrowserFields = filterBrowserFieldsByFieldName({ browserFields: mergeBrowserFieldsWithDefaultCategory(browserFields), - substring: filterInput, + substring: newFilterInput, }); setFilteredBrowserFields(newFilteredBrowserFields); setIsSearching(false); const newSelectedCategoryId = - filterInput === '' || Object.keys(newFilteredBrowserFields).length === 0 + newFilterInput === '' || Object.keys(newFilteredBrowserFields).length === 0 ? DEFAULT_CATEGORY_NAME : Object.keys(newFilteredBrowserFields) .sort() @@ -114,8 +113,8 @@ export const StatefulFieldsBrowserComponent = React.memo newFilteredBrowserFields[category].fields != null && newFilteredBrowserFields[selected].fields != null && - newFilteredBrowserFields[category].fields!.length > - newFilteredBrowserFields[selected].fields!.length + Object.keys(newFilteredBrowserFields[category].fields!).length > + Object.keys(newFilteredBrowserFields[selected].fields!).length ? category : selected, Object.keys(newFilteredBrowserFields)[0] From 39aa43992973a713241110d6c431d208ffe0beed Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Thu, 24 Oct 2019 17:27:00 -0500 Subject: [PATCH 130/191] [SIEM] Table columns, number related design tweaks (#48969) --- .../field_renderers.test.tsx.snap | 3 +- .../field_renderers/field_renderers.test.tsx | 6 +-- .../field_renderers/field_renderers.tsx | 14 ++---- .../components/formatted_date/index.test.tsx | 45 ++++++++++++++++++- .../components/formatted_date/index.tsx | 34 ++++++++++++++ .../components/last_event_time/index.test.tsx | 3 +- .../components/last_event_time/index.tsx | 21 ++++----- .../get_anomalies_host_table_columns.tsx | 10 +---- .../get_anomalies_network_table_columns.tsx | 11 ++--- .../timelines_table/common_columns.tsx | 4 +- .../hosts/authentications_table/index.tsx | 15 +++---- .../page/hosts/first_last_seen_host/index.tsx | 9 ++-- .../page/hosts/hosts_table/columns.tsx | 10 +---- .../hosts/uncommon_process_table/index.tsx | 4 ++ .../page/network/ip_overview/index.tsx | 10 ++++- .../network/network_dns_table/columns.tsx | 4 ++ .../page/network/users_table/columns.tsx | 1 + .../containers/events/last_event_time/mock.ts | 8 ++-- 18 files changed, 135 insertions(+), 77 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap index 928f62cffd720..6ae9268966480 100644 --- a/x-pack/legacy/plugins/siem/public/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap @@ -35,8 +35,7 @@ exports[`Field Renderers #autonomousSystemRenderer it renders correctly against exports[`Field Renderers #dateRenderer it renders correctly against snapshot 1`] = ` - diff --git a/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.test.tsx b/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.test.tsx index 6306dc0d288cf..0fd63bc3f2bf2 100644 --- a/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.test.tsx @@ -60,16 +60,14 @@ describe('Field Renderers', () => { describe('#dateRenderer', () => { test('it renders correctly against snapshot', () => { const wrapper = shallow( - {dateRenderer('firstSeen', mockData.complete.source!)} + {dateRenderer(mockData.complete.source!.firstSeen)} ); expect(toJson(wrapper)).toMatchSnapshot(); }); test('it renders emptyTagValue when invalid field provided', () => { - const wrapper = mount( - {dateRenderer('geo.spark_plug', mockData.complete.source!)} - ); + const wrapper = mount({dateRenderer(null)}); expect(wrapper.text()).toEqual(getEmptyValue()); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx b/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx index 1045f9c52e5e1..ffad36c7f9396 100644 --- a/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx +++ b/x-pack/legacy/plugins/siem/public/components/field_renderers/field_renderers.tsx @@ -11,17 +11,11 @@ import React, { Fragment, useState } from 'react'; import { pure } from 'recompose'; import styled from 'styled-components'; -import { - AutonomousSystem, - FlowTarget, - HostEcsFields, - IpOverviewData, - Overview, -} from '../../graphql/types'; +import { AutonomousSystem, FlowTarget, HostEcsFields, IpOverviewData } from '../../graphql/types'; import { escapeDataProviderId } from '../drag_and_drop/helpers'; import { DefaultDraggable } from '../draggables'; import { getEmptyTagValue } from '../empty_value'; -import { FormattedDate } from '../formatted_date'; +import { FormattedRelativePreferenceDate } from '../formatted_date'; import { HostDetailsLink, ReputationLink, VirusTotalLink, WhoIsLink } from '../links'; import { Spacer } from '../page'; import * as i18n from '../page/network/ip_overview/translations'; @@ -58,8 +52,8 @@ export const locationRenderer = (fieldNames: string[], data: IpOverviewData): Re getEmptyTagValue() ); -export const dateRenderer = (fieldName: string, data: Overview): React.ReactElement => ( - +export const dateRenderer = (timestamp?: string | null): React.ReactElement => ( + ); export const autonomousSystemRenderer = ( diff --git a/x-pack/legacy/plugins/siem/public/components/formatted_date/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/formatted_date/index.test.tsx index a66ec399a838d..bb0b947f149f4 100644 --- a/x-pack/legacy/plugins/siem/public/components/formatted_date/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/formatted_date/index.test.tsx @@ -13,8 +13,8 @@ import { useKibanaUiSetting } from '../../lib/settings/use_kibana_ui_setting'; import { mockFrameworks, TestProviders, MockFrameworks, getMockKibanaUiSetting } from '../../mock'; -import { PreferenceFormattedDate, FormattedDate } from '.'; -import { getEmptyValue } from '../empty_value'; +import { PreferenceFormattedDate, FormattedDate, FormattedRelativePreferenceDate } from '.'; +import { getEmptyString, getEmptyValue } from '../empty_value'; const mockUseKibanaUiSetting: jest.Mock = useKibanaUiSetting as jest.Mock; jest.mock('../../lib/settings/use_kibana_ui_setting', () => ({ @@ -162,4 +162,45 @@ describe('formatted_date', () => { }); }); }); + + describe('FormattedRelativePreferenceDate', () => { + describe('rendering', () => { + test('renders time over an hour correctly against snapshot', () => { + const isoDateString = '2019-02-25T22:27:05.000Z'; + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="preference-time"]').exists()).toBe(true); + }); + test('renders time under an hour correctly against snapshot', () => { + const timeTwelveMinutesAgo = new Date(new Date().getTime() - 12 * 60 * 1000).toISOString(); + const wrapper = shallow(); + expect(wrapper.find('[data-test-subj="relative-time"]').exists()).toBe(true); + }); + test('renders empty string value correctly', () => { + const wrapper = mount( + + + + ); + expect(wrapper.text()).toBe(getEmptyString()); + }); + + test('renders undefined value correctly', () => { + const wrapper = mount( + + + + ); + expect(wrapper.text()).toBe(getEmptyValue()); + }); + + test('renders null value correctly', () => { + const wrapper = mount( + + + + ); + expect(wrapper.text()).toBe(getEmptyValue()); + }); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/formatted_date/index.tsx b/x-pack/legacy/plugins/siem/public/components/formatted_date/index.tsx index 22a3893cf0f98..32c064096fcf9 100644 --- a/x-pack/legacy/plugins/siem/public/components/formatted_date/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/formatted_date/index.tsx @@ -6,6 +6,7 @@ import moment from 'moment-timezone'; import * as React from 'react'; +import { FormattedRelative } from '@kbn/i18n/react'; import { pure } from 'recompose'; import { @@ -62,3 +63,36 @@ export const FormattedDate = pure<{ ); FormattedDate.displayName = 'FormattedDate'; + +/** + * Renders the specified date value according to under/over one hour + * Under an hour = relative format + * Over an hour = in a format determined by the user's preferences, + * with a tooltip that renders: + * - the name of the field + * - a humanized relative date (e.g. 16 minutes ago) + * - a long representation of the date that includes the day of the week (e.g. Thursday, March 21, 2019 6:47pm) + * - the raw date value (e.g. 2019-03-22T00:47:46Z) + */ + +export const FormattedRelativePreferenceDate = ({ value }: { value?: string | number | null }) => { + if (value == null) { + return getOrEmptyTagFromValue(value); + } + const maybeDate = getMaybeDate(value); + if (!maybeDate.isValid()) { + return getOrEmptyTagFromValue(value); + } + const date = maybeDate.toDate(); + return ( + + {moment(date) + .add(1, 'hours') + .isBefore(new Date()) ? ( + + ) : ( + + )} + + ); +}; diff --git a/x-pack/legacy/plugins/siem/public/components/last_event_time/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/last_event_time/index.test.tsx index bcf5e3c1de408..c23a757647a42 100644 --- a/x-pack/legacy/plugins/siem/public/components/last_event_time/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/last_event_time/index.test.tsx @@ -53,8 +53,7 @@ describe('Last Event Time Stat', () => { ); - - expect(wrapper.html()).toBe('Last event: 12 days ago'); + expect(wrapper.html()).toBe('Last event: 12 minutes ago'); }); test('Bad date time string', async () => { mockUseLastEventTimeQuery.mockImplementation(() => ({ diff --git a/x-pack/legacy/plugins/siem/public/components/last_event_time/index.tsx b/x-pack/legacy/plugins/siem/public/components/last_event_time/index.tsx index cb9895bebcf09..2493a1378e944 100644 --- a/x-pack/legacy/plugins/siem/public/components/last_event_time/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/last_event_time/index.tsx @@ -5,18 +5,20 @@ */ import { EuiIcon, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; -import { FormattedMessage, FormattedRelative } from '@kbn/i18n/react'; +import { FormattedMessage } from '@kbn/i18n/react'; import React, { memo } from 'react'; import { LastEventIndexKey } from '../../graphql/types'; import { useLastEventTimeQuery } from '../../containers/events/last_event_time'; import { getEmptyTagValue } from '../empty_value'; +import { FormattedRelativePreferenceDate } from '../formatted_date'; export interface LastEventTimeProps { hostName?: string; indexKey: LastEventIndexKey; ip?: string; } + export const LastEventTime = memo(({ hostName, indexKey, ip }) => { const { loading, lastSeen, errorMessage } = useLastEventTimeQuery( indexKey, @@ -37,6 +39,7 @@ export const LastEventTime = memo(({ hostName, indexKey, ip ); } + return ( <> {loading && } @@ -44,15 +47,13 @@ export const LastEventTime = memo(({ hostName, indexKey, ip ? lastSeen : !loading && lastSeen != null && ( - - , - }} - /> - + , + }} + /> )} {!loading && lastSeen == null && getEmptyTagValue()} diff --git a/x-pack/legacy/plugins/siem/public/components/ml/tables/get_anomalies_host_table_columns.tsx b/x-pack/legacy/plugins/siem/public/components/ml/tables/get_anomalies_host_table_columns.tsx index 6650449dd8200..daac4835adb28 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/tables/get_anomalies_host_table_columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml/tables/get_anomalies_host_table_columns.tsx @@ -6,7 +6,6 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; -import moment from 'moment'; import { Columns } from '../../paginated_table'; import { AnomaliesByHost, Anomaly, NarrowDateRange } from '../types'; import { getRowItemDraggable } from '../../tables/helpers'; @@ -18,10 +17,9 @@ import * as i18n from './translations'; import { getEntries } from '../get_entries'; import { DraggableScore } from '../score/draggable_score'; import { createExplorerLink } from '../links/create_explorer_link'; -import { LocalizedDateTooltip } from '../../localized_date_tooltip'; -import { PreferenceFormattedDate } from '../../formatted_date'; import { HostsType } from '../../../store/hosts/model'; import { escapeDataProviderId } from '../../drag_and_drop/helpers'; +import { FormattedRelativePreferenceDate } from '../../formatted_date'; export const getAnomaliesHostTableColumns = ( startDate: number, @@ -126,11 +124,7 @@ export const getAnomaliesHostTableColumns = ( name: i18n.TIME_STAMP, field: 'anomaly.time', sortable: true, - render: time => ( - - - - ), + render: time => , }, ]; diff --git a/x-pack/legacy/plugins/siem/public/components/ml/tables/get_anomalies_network_table_columns.tsx b/x-pack/legacy/plugins/siem/public/components/ml/tables/get_anomalies_network_table_columns.tsx index 1e1628fb077dd..2113d3b82f52e 100644 --- a/x-pack/legacy/plugins/siem/public/components/ml/tables/get_anomalies_network_table_columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/ml/tables/get_anomalies_network_table_columns.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; -import moment from 'moment'; + import { Columns } from '../../paginated_table'; import { Anomaly, NarrowDateRange, AnomaliesByNetwork } from '../types'; import { getRowItemDraggable } from '../../tables/helpers'; @@ -18,8 +18,7 @@ import * as i18n from './translations'; import { getEntries } from '../get_entries'; import { DraggableScore } from '../score/draggable_score'; import { createExplorerLink } from '../links/create_explorer_link'; -import { LocalizedDateTooltip } from '../../localized_date_tooltip'; -import { PreferenceFormattedDate } from '../../formatted_date'; +import { FormattedRelativePreferenceDate } from '../../formatted_date'; import { NetworkType } from '../../../store/network/model'; import { escapeDataProviderId } from '../../drag_and_drop/helpers'; @@ -120,11 +119,7 @@ export const getAnomaliesNetworkTableColumns = ( name: i18n.TIME_STAMP, field: 'anomaly.time', sortable: true, - render: time => ( - - - - ), + render: time => , }, ]; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/common_columns.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/common_columns.tsx index 9818a33385286..8eeb29794f5a6 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/common_columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/timelines_table/common_columns.tsx @@ -14,7 +14,7 @@ import { NotePreviews } from '../note_previews'; import * as i18n from '../translations'; import { OnOpenTimeline, OnToggleShowNotes, OpenTimelineResult } from '../types'; import { getEmptyTagValue } from '../../empty_value'; -import { FormattedDate } from '../../formatted_date'; +import { FormattedRelativePreferenceDate } from '../../formatted_date'; /** * Returns the column definitions (passed as the `columns` prop to @@ -96,7 +96,7 @@ export const getCommonColumns = ({ render: (date: number, timelineResult: OpenTimelineResult) => (
{timelineResult.updated != null ? ( - + ) : ( getEmptyTagValue() )} diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx index fe280c2899327..b9b132b4f50a4 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiToolTip } from '@elastic/eui'; -import { FormattedRelative } from '@kbn/i18n/react'; import { has } from 'lodash/fp'; import React from 'react'; import { connect } from 'react-redux'; @@ -18,6 +16,7 @@ import { hostsModel, hostsSelectors, State } from '../../../../store'; import { DragEffects, DraggableWrapper } from '../../../drag_and_drop/draggable_wrapper'; import { escapeDataProviderId } from '../../../drag_and_drop/helpers'; import { getEmptyTagValue } from '../../../empty_value'; +import { FormattedRelativePreferenceDate } from '../../../formatted_date'; import { HostDetailsLink, IPDetailsLink } from '../../../links'; import { Columns, ItemsPerRow, PaginatedTable } from '../../../paginated_table'; import { IS_OPERATOR } from '../../../timeline/data_providers/data_provider'; @@ -200,6 +199,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ /> ); }, + width: '8%', }, { name: i18n.FAILURES, @@ -237,16 +237,15 @@ const getAuthenticationColumns = (): AuthTableColumns => [ /> ); }, + width: '8%', }, { name: i18n.LAST_SUCCESSFUL_TIME, truncateText: false, hideForMobile: false, render: ({ node }) => - has('lastSuccess.timestamp', node) ? ( - - - + has('lastSuccess.timestamp', node) && node.lastSuccess!.timestamp != null ? ( + ) : ( getEmptyTagValue() ), @@ -291,9 +290,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ hideForMobile: false, render: ({ node }) => has('lastFailure.timestamp', node) && node.lastFailure!.timestamp != null ? ( - - - + ) : ( getEmptyTagValue() ), diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/first_last_seen_host/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/first_last_seen_host/index.tsx index 665f1f46bc7c1..553615e950b8d 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/first_last_seen_host/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/first_last_seen_host/index.tsx @@ -5,15 +5,14 @@ */ import { EuiIcon, EuiLoadingSpinner, EuiText, EuiToolTip } from '@elastic/eui'; -import moment from 'moment'; + import React from 'react'; import { ApolloConsumer } from 'react-apollo'; import { pure } from 'recompose'; import { useFirstLastSeenHostQuery } from '../../../../containers/hosts/first_last_seen'; import { getEmptyTagValue } from '../../../empty_value'; -import { PreferenceFormattedDate } from '../../../formatted_date'; -import { LocalizedDateTooltip } from '../../../localized_date_tooltip'; +import { FormattedRelativePreferenceDate } from '../../../formatted_date'; export enum FirstLastSeenHostType { FIRST_SEEN = 'first-seen', @@ -52,9 +51,7 @@ export const FirstLastSeenHost = pure<{ hostname: string; type: FirstLastSeenHos : !loading && valueSeen != null && ( - - - + )} {!loading && valueSeen == null && getEmptyTagValue()} diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/columns.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/columns.tsx index b626df58b007f..8d490d2c152d9 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/columns.tsx @@ -5,14 +5,12 @@ */ import { EuiIcon, EuiToolTip } from '@elastic/eui'; -import moment from 'moment'; import React from 'react'; import { DragEffects, DraggableWrapper } from '../../../drag_and_drop/draggable_wrapper'; import { escapeDataProviderId } from '../../../drag_and_drop/helpers'; import { getEmptyTagValue } from '../../../empty_value'; -import { PreferenceFormattedDate } from '../../../formatted_date'; import { HostDetailsLink } from '../../../links'; -import { LocalizedDateTooltip } from '../../../localized_date_tooltip'; +import { FormattedRelativePreferenceDate } from '../../../formatted_date'; import { IS_OPERATOR } from '../../../timeline/data_providers/data_provider'; import { Provider } from '../../../timeline/data_providers/provider'; import { AddFilterToGlobalSearchBar, createFilter } from '../../add_filter_to_global_search_bar'; @@ -75,11 +73,7 @@ export const getHostsColumns = (): HostsTableColumns => [ sortable: true, render: lastSeen => { if (lastSeen != null) { - return ( - - - - ); + return ; } return getEmptyTagValue(); }, diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx index 6fd2cab90efea..2f2d84306e25e 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx @@ -161,16 +161,20 @@ const getUncommonColumns = (): UncommonProcessTableColumns => [ width: '20%', }, { + align: 'right', name: i18n.NUMBER_OF_HOSTS, truncateText: false, hideForMobile: false, render: ({ node }) => <>{node.hosts != null ? node.hosts.length : getEmptyValue()}, + width: '8%', }, { + align: 'right', name: i18n.NUMBER_OF_INSTANCES, truncateText: false, hideForMobile: false, render: ({ node }) => defaultToEmptyTag(node.instances), + width: '8%', }, { name: i18n.HOSTS, diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/ip_overview/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/ip_overview/index.tsx index 7c695e37386ef..b71d786e643eb 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/ip_overview/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/ip_overview/index.tsx @@ -114,8 +114,14 @@ export const IpOverview = pure( const descriptionLists: Readonly = [ firstColumn, [ - { title: i18n.FIRST_SEEN, description: dateRenderer('firstSeen', typeData) }, - { title: i18n.LAST_SEEN, description: dateRenderer('lastSeen', typeData) }, + { + title: i18n.FIRST_SEEN, + description: typeData ? dateRenderer(typeData.firstSeen) : getEmptyTagValue(), + }, + { + title: i18n.LAST_SEEN, + description: typeData ? dateRenderer(typeData.lastSeen) : getEmptyTagValue(), + }, ], [ { diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/columns.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/columns.tsx index 353699c5158bc..b1c1b26cd498d 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/columns.tsx @@ -69,6 +69,7 @@ export const getNetworkDnsColumns = (type: networkModel.NetworkType): NetworkDns }, }, { + align: 'right', field: `node.${NetworkDnsFields.queryCount}`, name: i18n.TOTAL_QUERIES, sortable: true, @@ -83,6 +84,7 @@ export const getNetworkDnsColumns = (type: networkModel.NetworkType): NetworkDns }, }, { + align: 'right', field: `node.${NetworkDnsFields.uniqueDomains}`, name: i18n.UNIQUE_DOMAINS, sortable: true, @@ -97,6 +99,7 @@ export const getNetworkDnsColumns = (type: networkModel.NetworkType): NetworkDns }, }, { + align: 'right', field: `node.${NetworkDnsFields.dnsBytesIn}`, name: i18n.DNS_BYTES_IN, sortable: true, @@ -111,6 +114,7 @@ export const getNetworkDnsColumns = (type: networkModel.NetworkType): NetworkDns }, }, { + align: 'right', field: `node.${NetworkDnsFields.dnsBytesOut}`, name: i18n.DNS_BYTES_OUT, sortable: true, diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/users_table/columns.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/users_table/columns.tsx index 2c51fb8f94561..b732ac5bfd5fa 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/users_table/columns.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/users_table/columns.tsx @@ -73,6 +73,7 @@ export const getUsersColumns = (flowTarget: FlowTarget, tableId: string): UsersC }), }, { + align: 'right', field: 'node.user.count', name: i18n.DOCUMENT_COUNT, truncateText: false, diff --git a/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/mock.ts b/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/mock.ts index 09cdfbd07bffd..ca8786077851f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/mock.ts +++ b/x-pack/legacy/plugins/siem/public/containers/events/last_event_time/mock.ts @@ -28,11 +28,11 @@ interface MockLastEventTimeQuery { }; } -const getTimeTwelveDaysAgo = () => { +const getTimeTwelveMinutesAgo = () => { const d = new Date(); const ts = d.getTime(); - const twelveDays = ts - 12 * 24 * 60 * 60 * 1000; - return new Date(twelveDays).toISOString(); + const twelveMinutes = ts - 12 * 60 * 1000; + return new Date(twelveMinutes).toISOString(); }; export const mockLastEventTimeQuery: MockLastEventTimeQuery[] = [ @@ -51,7 +51,7 @@ export const mockLastEventTimeQuery: MockLastEventTimeQuery[] = [ source: { id: 'default', LastEventTime: { - lastSeen: getTimeTwelveDaysAgo(), + lastSeen: getTimeTwelveMinutesAgo(), errorMessage: null, }, }, From ccd01a3af0528d0217c626a99643ff19ba5274fb Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Thu, 24 Oct 2019 16:21:46 -0700 Subject: [PATCH 131/191] Migrate ui/doc_title to New platform (#48121) * create NP docTitle service and bridge LP to it Signed-off-by: pgayvallet * properly prefix the docTitle public types Signed-off-by: pgayvallet * update documentation Signed-off-by: pgayvallet * replace direct NP access with closure to avoid error when importing module in tests with no usages Signed-off-by: pgayvallet * remove arrow functions for doc generation Signed-off-by: pgayvallet * remove get$ from the api Signed-off-by: pgayvallet * remove apply param and excludeBase option Signed-off-by: pgayvallet * remove removed export Signed-off-by: pgayvallet * adapt legacy service to new api Signed-off-by: pgayvallet * add entry about docTitle in the migration guide Signed-off-by: pgayvallet * add link in migration guide Signed-off-by: pgayvallet * update generated doc Signed-off-by: pgayvallet * update chrome mock Signed-off-by: pgayvallet * update snapshots due to api change Signed-off-by: pgayvallet * remove ChromeDocTitleChange in favor of inline type Signed-off-by: pgayvallet --- ...ana-plugin-public.chromedoctitle.change.md | 34 ++++++ .../kibana-plugin-public.chromedoctitle.md | 39 +++++++ ...bana-plugin-public.chromedoctitle.reset.md | 17 +++ ...bana-plugin-public.chromestart.doctitle.md | 13 +++ .../kibana-plugin-public.chromestart.md | 1 + .../core/public/kibana-plugin-public.md | 1 + src/core/MIGRATION.md | 1 + src/core/public/chrome/chrome_service.mock.ts | 7 ++ src/core/public/chrome/chrome_service.tsx | 8 +- .../doc_title/doc_title_service.test.ts | 80 +++++++++++++ .../chrome/doc_title/doc_title_service.ts | 105 ++++++++++++++++++ src/core/public/chrome/doc_title/index.ts | 20 ++++ src/core/public/chrome/index.ts | 1 + src/core/public/index.ts | 2 + src/core/public/public.api.md | 11 ++ .../query_bar_input.test.tsx.snap | 42 +++++++ .../public/doc_title/__tests__/doc_title.js | 34 +++--- src/legacy/ui/public/doc_title/doc_title.js | 37 +----- 18 files changed, 402 insertions(+), 51 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromedoctitle.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md create mode 100644 docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md create mode 100644 src/core/public/chrome/doc_title/doc_title_service.test.ts create mode 100644 src/core/public/chrome/doc_title/doc_title_service.ts create mode 100644 src/core/public/chrome/doc_title/index.ts diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md new file mode 100644 index 0000000000000..eba149bf93a4c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.change.md @@ -0,0 +1,34 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [change](./kibana-plugin-public.chromedoctitle.change.md) + +## ChromeDocTitle.change() method + +Changes the current document title. + +Signature: + +```typescript +change(newTitle: string | string[]): void; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| newTitle | string | string[] | | + +Returns: + +`void` + +## Example + +How to change the title of the document + +```ts +chrome.docTitle.change('My application title') +chrome.docTitle.change(['My application', 'My section']) + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.md new file mode 100644 index 0000000000000..3c6cfab486288 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.md @@ -0,0 +1,39 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) + +## ChromeDocTitle interface + +APIs for accessing and updating the document title. + +Signature: + +```typescript +export interface ChromeDocTitle +``` + +## Methods + +| Method | Description | +| --- | --- | +| [change(newTitle)](./kibana-plugin-public.chromedoctitle.change.md) | Changes the current document title. | +| [reset()](./kibana-plugin-public.chromedoctitle.reset.md) | Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) | + +## Example 1 + +How to change the title of the document + +```ts +chrome.docTitle.change('My application') + +``` + +## Example 2 + +How to reset the title of the document to it's initial value + +```ts +chrome.docTitle.reset() + +``` + diff --git a/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md b/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md new file mode 100644 index 0000000000000..4b4c6f573e006 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromedoctitle.reset.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) > [reset](./kibana-plugin-public.chromedoctitle.reset.md) + +## ChromeDocTitle.reset() method + +Resets the document title to it's initial value. (meaning the one present in the title meta at application load.) + +Signature: + +```typescript +reset(): void; +``` +Returns: + +`void` + diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md b/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md new file mode 100644 index 0000000000000..71eda64c24646 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromestart.doctitle.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeStart](./kibana-plugin-public.chromestart.md) > [docTitle](./kibana-plugin-public.chromestart.doctitle.md) + +## ChromeStart.docTitle property + +APIs for accessing and updating the document title. + +Signature: + +```typescript +docTitle: ChromeDocTitle; +``` diff --git a/docs/development/core/public/kibana-plugin-public.chromestart.md b/docs/development/core/public/kibana-plugin-public.chromestart.md index bc41aa10cce8f..153e06d591404 100644 --- a/docs/development/core/public/kibana-plugin-public.chromestart.md +++ b/docs/development/core/public/kibana-plugin-public.chromestart.md @@ -16,6 +16,7 @@ export interface ChromeStart | Property | Type | Description | | --- | --- | --- | +| [docTitle](./kibana-plugin-public.chromestart.doctitle.md) | ChromeDocTitle | APIs for accessing and updating the document title. | | [navControls](./kibana-plugin-public.chromestart.navcontrols.md) | ChromeNavControls | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | | [navLinks](./kibana-plugin-public.chromestart.navlinks.md) | ChromeNavLinks | [APIs](./kibana-plugin-public.chromenavlinks.md) for manipulating nav links. | | [recentlyAccessed](./kibana-plugin-public.chromestart.recentlyaccessed.md) | ChromeRecentlyAccessed | [APIs](./kibana-plugin-public.chromerecentlyaccessed.md) for recently accessed history. | diff --git a/docs/development/core/public/kibana-plugin-public.md b/docs/development/core/public/kibana-plugin-public.md index 57ab8bedde95e..253e50f0f2c2e 100644 --- a/docs/development/core/public/kibana-plugin-public.md +++ b/docs/development/core/public/kibana-plugin-public.md @@ -32,6 +32,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. | | [ChromeBadge](./kibana-plugin-public.chromebadge.md) | | | [ChromeBrand](./kibana-plugin-public.chromebrand.md) | | +| [ChromeDocTitle](./kibana-plugin-public.chromedoctitle.md) | APIs for accessing and updating the document title. | | [ChromeNavControl](./kibana-plugin-public.chromenavcontrol.md) | | | [ChromeNavControls](./kibana-plugin-public.chromenavcontrols.md) | [APIs](./kibana-plugin-public.chromenavcontrols.md) for registering new controls to be displayed in the navigation bar. | | [ChromeNavLink](./kibana-plugin-public.chromenavlink.md) | | diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index 6a12b587085e1..b5942cc82941f 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1111,6 +1111,7 @@ import { npStart: { core } } from 'ui/new_platform'; | `ui/notify` | [`core.notifications`](/docs/development/core/public/kibana-plugin-public.notificationsstart.md) and [`core.overlays`](/docs/development/core/public/kibana-plugin-public.overlaystart.md) | Toast messages are in `notifications`, banners are in `overlays`. May be combined later. | | `ui/routes` | -- | There is no global routing mechanism. Each app [configures its own routing](/rfcs/text/0004_application_service_mounting.md#complete-example). | | `ui/saved_objects` | [`core.savedObjects`](/docs/development/core/public/kibana-plugin-public.savedobjectsstart.md) | Client API is the same | +| `ui/doc_title` | [`core.chrome.docTitle`](/docs/development/core/public/kibana-plugin-public.chromedoctitle.md) | | _See also: [Public's CoreStart API Docs](/docs/development/core/public/kibana-plugin-public.corestart.md)_ diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 3775989c5126b..6f61ee9dc21ba 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -43,6 +43,13 @@ const createStartContractMock = () => { get: jest.fn(), get$: jest.fn(), }, + docTitle: { + change: jest.fn(), + reset: jest.fn(), + __legacy: { + setBaseTitle: jest.fn(), + }, + }, navControls: { registerLeft: jest.fn(), registerRight: jest.fn(), diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 71279ad6fed03..87389d2c10f03 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -33,10 +33,11 @@ import { HttpStart } from '../http'; import { ChromeNavLinks, NavLinksService } from './nav_links'; import { ChromeRecentlyAccessed, RecentlyAccessedService } from './recently_accessed'; import { NavControlsService, ChromeNavControls } from './nav_controls'; +import { DocTitleService, ChromeDocTitle } from './doc_title'; import { LoadingIndicator, HeaderWrapper as Header } from './ui'; import { DocLinksStart } from '../doc_links'; -export { ChromeNavControls, ChromeRecentlyAccessed }; +export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; const IS_COLLAPSED_KEY = 'core.chrome.isCollapsed'; @@ -82,6 +83,7 @@ export class ChromeService { private readonly navControls = new NavControlsService(); private readonly navLinks = new NavLinksService(); private readonly recentlyAccessed = new RecentlyAccessedService(); + private readonly docTitle = new DocTitleService(); constructor(private readonly params: ConstructorParams) {} @@ -106,6 +108,7 @@ export class ChromeService { const navControls = this.navControls.start(); const navLinks = this.navLinks.start({ application, http }); const recentlyAccessed = await this.recentlyAccessed.start({ http }); + const docTitle = this.docTitle.start({ document: window.document }); if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) { notifications.toasts.addWarning( @@ -119,6 +122,7 @@ export class ChromeService { navControls, navLinks, recentlyAccessed, + docTitle, getHeaderComponent: () => ( @@ -259,6 +263,8 @@ export interface ChromeStart { navControls: ChromeNavControls; /** {@inheritdoc ChromeRecentlyAccessed} */ recentlyAccessed: ChromeRecentlyAccessed; + /** {@inheritdoc ChromeDocTitle} */ + docTitle: ChromeDocTitle; /** * Sets the current app's title diff --git a/src/core/public/chrome/doc_title/doc_title_service.test.ts b/src/core/public/chrome/doc_title/doc_title_service.test.ts new file mode 100644 index 0000000000000..763e8c9ebd74a --- /dev/null +++ b/src/core/public/chrome/doc_title/doc_title_service.test.ts @@ -0,0 +1,80 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { DocTitleService } from './doc_title_service'; + +describe('DocTitleService', () => { + const defaultTitle = 'KibanaTest'; + const document = { title: '' }; + + const getStart = (title: string = defaultTitle) => { + document.title = title; + return new DocTitleService().start({ document }); + }; + + beforeEach(() => { + document.title = defaultTitle; + }); + + describe('#change()', () => { + it('changes the title of the document', async () => { + getStart().change('TitleA'); + expect(document.title).toEqual('TitleA - KibanaTest'); + }); + + it('appends the baseTitle to the title', async () => { + const start = getStart('BaseTitle'); + start.change('TitleA'); + expect(document.title).toEqual('TitleA - BaseTitle'); + start.change('TitleB'); + expect(document.title).toEqual('TitleB - BaseTitle'); + }); + + it('accepts string arrays as input', async () => { + const start = getStart(); + start.change(['partA', 'partB']); + expect(document.title).toEqual(`partA - partB - ${defaultTitle}`); + start.change(['partA', 'partB', 'partC']); + expect(document.title).toEqual(`partA - partB - partC - ${defaultTitle}`); + }); + }); + + describe('#reset()', () => { + it('resets the title to the initial value', async () => { + const start = getStart('InitialTitle'); + start.change('TitleA'); + expect(document.title).toEqual('TitleA - InitialTitle'); + start.reset(); + expect(document.title).toEqual('InitialTitle'); + }); + }); + + describe('#__legacy.setBaseTitle()', () => { + it('allows to change the baseTitle after startup', async () => { + const start = getStart('InitialTitle'); + start.change('WithInitial'); + expect(document.title).toEqual('WithInitial - InitialTitle'); + start.__legacy.setBaseTitle('NewBaseTitle'); + start.change('WithNew'); + expect(document.title).toEqual('WithNew - NewBaseTitle'); + start.reset(); + expect(document.title).toEqual('NewBaseTitle'); + }); + }); +}); diff --git a/src/core/public/chrome/doc_title/doc_title_service.ts b/src/core/public/chrome/doc_title/doc_title_service.ts new file mode 100644 index 0000000000000..9453abe54de66 --- /dev/null +++ b/src/core/public/chrome/doc_title/doc_title_service.ts @@ -0,0 +1,105 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { compact, flattenDeep, isString } from 'lodash'; + +interface StartDeps { + document: { title: string }; +} + +/** + * APIs for accessing and updating the document title. + * + * @example + * How to change the title of the document + * ```ts + * chrome.docTitle.change('My application') + * ``` + * + * @example + * How to reset the title of the document to it's initial value + * ```ts + * chrome.docTitle.reset() + * ``` + * + * @public + * */ +export interface ChromeDocTitle { + /** + * Changes the current document title. + * + * @example + * How to change the title of the document + * ```ts + * chrome.docTitle.change('My application title') + * chrome.docTitle.change(['My application', 'My section']) + * ``` + * + * @param newTitle The new title to set, either a string or string array + */ + change(newTitle: string | string[]): void; + /** + * Resets the document title to it's initial value. + * (meaning the one present in the title meta at application load.) + */ + reset(): void; + + /** @internal */ + __legacy: { + setBaseTitle(baseTitle: string): void; + }; +} + +const defaultTitle: string[] = []; +const titleSeparator = ' - '; + +/** @internal */ +export class DocTitleService { + private document = { title: '' }; + private baseTitle = ''; + + public start({ document }: StartDeps): ChromeDocTitle { + this.document = document; + this.baseTitle = document.title; + + return { + change: (title: string | string[]) => { + this.applyTitle(title); + }, + reset: () => { + this.applyTitle(defaultTitle); + }, + __legacy: { + setBaseTitle: baseTitle => { + this.baseTitle = baseTitle; + }, + }, + }; + } + + private applyTitle(title: string | string[]) { + this.document.title = this.render(title); + } + + private render(title: string | string[]) { + const parts = [...(isString(title) ? [title] : title), this.baseTitle]; + // ensuring compat with legacy that might be passing nested arrays + return compact(flattenDeep(parts)).join(titleSeparator); + } +} diff --git a/src/core/public/chrome/doc_title/index.ts b/src/core/public/chrome/doc_title/index.ts new file mode 100644 index 0000000000000..b070d01953f7a --- /dev/null +++ b/src/core/public/chrome/doc_title/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './doc_title_service'; diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts index 6e03f9e023983..b220a81f775f8 100644 --- a/src/core/public/chrome/index.ts +++ b/src/core/public/chrome/index.ts @@ -29,3 +29,4 @@ export { export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './nav_links'; export { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem } from './recently_accessed'; export { ChromeNavControl, ChromeNavControls } from './nav_controls'; +export { ChromeDocTitle } from './doc_title'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 24201ff0253cb..7391cf7f9454c 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -45,6 +45,7 @@ import { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields, + ChromeDocTitle, ChromeStart, ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, @@ -250,6 +251,7 @@ export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields, + ChromeDocTitle, ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, ChromeStart, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 11a1b5c0d1d9b..416fb13cbb73e 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -105,6 +105,16 @@ export interface ChromeBrand { // @public (undocumented) export type ChromeBreadcrumb = Breadcrumb; +// @public +export interface ChromeDocTitle { + // @internal (undocumented) + __legacy: { + setBaseTitle(baseTitle: string): void; + }; + change(newTitle: string | string[]): void; + reset(): void; +} + // @public (undocumented) export type ChromeHelpExtension = (element: HTMLDivElement) => () => void; @@ -186,6 +196,7 @@ export interface ChromeRecentlyAccessedHistoryItem { // @public export interface ChromeStart { addApplicationClass(className: string): void; + docTitle: ChromeDocTitle; getApplicationClasses$(): Observable; getBadge$(): Observable; getBrand$(): Observable; diff --git a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap index f59afc7165bab..286e60cca9712 100644 --- a/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap +++ b/src/legacy/core_plugins/data/public/query/query_bar/components/__snapshots__/query_bar_input.test.tsx.snap @@ -103,6 +103,13 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -659,6 +666,13 @@ exports[`QueryBarInput Should disable autoFocus on EuiFieldText when disableAuto }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -1203,6 +1217,13 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1 }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -1756,6 +1777,13 @@ exports[`QueryBarInput Should pass the query language to the language switcher 1 }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -2300,6 +2328,13 @@ exports[`QueryBarInput Should render the given query 1`] = ` }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], @@ -2853,6 +2888,13 @@ exports[`QueryBarInput Should render the given query 1`] = ` }, "chrome": Object { "addApplicationClass": [MockFunction], + "docTitle": Object { + "__legacy": Object { + "setBaseTitle": [MockFunction], + }, + "change": [MockFunction], + "reset": [MockFunction], + }, "getApplicationClasses$": [MockFunction], "getBadge$": [MockFunction], "getBrand$": [MockFunction], diff --git a/src/legacy/ui/public/doc_title/__tests__/doc_title.js b/src/legacy/ui/public/doc_title/__tests__/doc_title.js index b4c3700e36f68..fa8b83f755957 100644 --- a/src/legacy/ui/public/doc_title/__tests__/doc_title.js +++ b/src/legacy/ui/public/doc_title/__tests__/doc_title.js @@ -20,7 +20,8 @@ import sinon from 'sinon'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { setBaseTitle, docTitle } from '../doc_title'; +import { docTitle } from '../doc_title'; +import { npStart } from '../../new_platform'; describe('docTitle Service', function () { let initialDocTitle; @@ -30,20 +31,24 @@ describe('docTitle Service', function () { beforeEach(function () { initialDocTitle = document.title; document.title = MAIN_TITLE; - setBaseTitle(MAIN_TITLE); + npStart.core.chrome.docTitle.__legacy.setBaseTitle(MAIN_TITLE); }); afterEach(function () { document.title = initialDocTitle; - setBaseTitle(initialDocTitle); + npStart.core.chrome.docTitle.__legacy.setBaseTitle(initialDocTitle); }); - beforeEach(ngMock.module('kibana', function ($provide) { - $provide.decorator('$rootScope', decorateWithSpy('$on')); - })); + beforeEach( + ngMock.module('kibana', function ($provide) { + $provide.decorator('$rootScope', decorateWithSpy('$on')); + }) + ); - beforeEach(ngMock.inject(function ($injector) { - $rootScope = $injector.get('$rootScope'); - })); + beforeEach( + ngMock.inject(function ($injector) { + $rootScope = $injector.get('$rootScope'); + }) + ); describe('setup', function () { it('resets the title when a route change begins', function () { @@ -60,13 +65,11 @@ describe('docTitle Service', function () { }); describe('#reset', function () { - it('clears the internal state, next update() will write the default', function () { + it('clears the internal state', function () { docTitle.change('some title'); - docTitle.update(); expect(document.title).to.be('some title - ' + MAIN_TITLE); docTitle.reset(); - docTitle.update(); expect(document.title).to.be(MAIN_TITLE); }); }); @@ -77,12 +80,6 @@ describe('docTitle Service', function () { docTitle.change('some secondary title'); expect(document.title).to.be('some secondary title - ' + MAIN_TITLE); }); - - it('will write just the first param if the second param is true', function () { - expect(document.title).to.be(MAIN_TITLE); - docTitle.change('entire name', true); - expect(document.title).to.be('entire name'); - }); }); function decorateWithSpy(prop) { @@ -91,5 +88,4 @@ describe('docTitle Service', function () { return $delegate; }; } - }); diff --git a/src/legacy/ui/public/doc_title/doc_title.js b/src/legacy/ui/public/doc_title/doc_title.js index 3692fd71f06cc..0edc55a0ac366 100644 --- a/src/legacy/ui/public/doc_title/doc_title.js +++ b/src/legacy/ui/public/doc_title/doc_title.js @@ -17,53 +17,28 @@ * under the License. */ -import _ from 'lodash'; +import { isArray } from 'lodash'; import { uiModules } from '../modules'; +import { npStart } from '../new_platform'; -let baseTitle = document.title; +const npDocTitle = () => npStart.core.chrome.docTitle; -// for karma test -export function setBaseTitle(str) { - baseTitle = str; -} - -let lastChange; - -function render() { - lastChange = lastChange || []; - - const parts = [lastChange[0]]; - - if (!lastChange[1]) parts.push(baseTitle); - - return _(parts).flattenDeep().compact().join(' - '); -} - -function change(title, complete) { - lastChange = [title, complete]; - update(); +function change(title) { + npDocTitle().change(isArray(title) ? title : [title]); } function reset() { - lastChange = null; -} - -function update() { - document.title = render(); + npDocTitle().reset(); } export const docTitle = { - render, change, reset, - update, }; uiModules.get('kibana') .run(function ($rootScope) { // always bind to the route events $rootScope.$on('$routeChangeStart', docTitle.reset); - $rootScope.$on('$routeChangeError', docTitle.update); - $rootScope.$on('$routeChangeSuccess', docTitle.update); }); From 296fa8e7229c2027ee7180e8c6612cba18bb351a Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 24 Oct 2019 17:02:21 -0700 Subject: [PATCH 132/191] increase type check memory for x-pack to 4GB (#49255) --- src/dev/typescript/run_type_check_cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev/typescript/run_type_check_cli.ts b/src/dev/typescript/run_type_check_cli.ts index bf6e8711fa81e..3deebcc0c18f9 100644 --- a/src/dev/typescript/run_type_check_cli.ts +++ b/src/dev/typescript/run_type_check_cli.ts @@ -88,7 +88,7 @@ export function runTypeCheckCli() { } execInProjects(log, projects, process.execPath, project => [ - ...(project.name === 'x-pack' ? ['--max-old-space-size=2048'] : []), + ...(project.name === 'x-pack' ? ['--max-old-space-size=4096'] : []), require.resolve('typescript/bin/tsc'), ...['--project', project.tsConfigPath], ...tscArgs, From 2ac82dec61f3fbf4b821fd72cf37b06afcc8a1ff Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Fri, 25 Oct 2019 08:28:55 +0100 Subject: [PATCH 133/191] [Saved Objects] Adds support for custom Refresh settings on mutating operations (#48932) Adds the ability to override the Refresh setting of mutating operations (Update, Delete, Bulk, Index) of Saved Objects. --- .../core/server/kibana-plugin-server.md | 3 + ...-server.mutatingoperationrefreshsetting.md | 13 ++ ...in-server.savedobjectsbulkupdateoptions.md | 19 ++ ...r.savedobjectsbulkupdateoptions.refresh.md | 13 ++ ...in-server.savedobjectsclient.bulkupdate.md | 4 +- ...plugin-server.savedobjectsclient.delete.md | 4 +- ...plugin-server.savedobjectscreateoptions.md | 1 + ...erver.savedobjectscreateoptions.refresh.md | 13 ++ ...plugin-server.savedobjectsdeleteoptions.md | 19 ++ ...erver.savedobjectsdeleteoptions.refresh.md | 13 ++ ...plugin-server.savedobjectsupdateoptions.md | 1 + ...erver.savedobjectsupdateoptions.refresh.md | 13 ++ src/core/server/index.ts | 3 + .../service/lib/repository.test.js | 218 ++++++++++++++++++ .../saved_objects/service/lib/repository.ts | 51 ++-- .../service/saved_objects_client.ts | 36 ++- src/core/server/saved_objects/types.ts | 6 + src/core/server/server.api.md | 19 +- 18 files changed, 426 insertions(+), 23 deletions(-) create mode 100644 docs/development/core/server/kibana-plugin-server.mutatingoperationrefreshsetting.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.refresh.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.refresh.md create mode 100644 docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.refresh.md diff --git a/docs/development/core/server/kibana-plugin-server.md b/docs/development/core/server/kibana-plugin-server.md index 2f81afacf4bb4..5a8b702e0ec99 100644 --- a/docs/development/core/server/kibana-plugin-server.md +++ b/docs/development/core/server/kibana-plugin-server.md @@ -90,10 +90,12 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsBulkGetObject](./kibana-plugin-server.savedobjectsbulkgetobject.md) | | | [SavedObjectsBulkResponse](./kibana-plugin-server.savedobjectsbulkresponse.md) | | | [SavedObjectsBulkUpdateObject](./kibana-plugin-server.savedobjectsbulkupdateobject.md) | | +| [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) | | | [SavedObjectsBulkUpdateResponse](./kibana-plugin-server.savedobjectsbulkupdateresponse.md) | | | [SavedObjectsClientProviderOptions](./kibana-plugin-server.savedobjectsclientprovideroptions.md) | Options to control the creation of the Saved Objects Client. | | [SavedObjectsClientWrapperOptions](./kibana-plugin-server.savedobjectsclientwrapperoptions.md) | Options passed to each SavedObjectsClientWrapperFactory to aid in creating the wrapper instance. | | [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) | | +| [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) | | | [SavedObjectsExportOptions](./kibana-plugin-server.savedobjectsexportoptions.md) | Options controlling the export operation. | | [SavedObjectsExportResultDetails](./kibana-plugin-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | | [SavedObjectsFindOptions](./kibana-plugin-server.savedobjectsfindoptions.md) | | @@ -149,6 +151,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [LifecycleResponseFactory](./kibana-plugin-server.lifecycleresponsefactory.md) | Creates an object containing redirection or error response with error details, HTTP headers, and other data transmitted to the client. | | [MIGRATION\_ASSISTANCE\_INDEX\_ACTION](./kibana-plugin-server.migration_assistance_index_action.md) | | | [MIGRATION\_DEPRECATION\_LEVEL](./kibana-plugin-server.migration_deprecation_level.md) | | +| [MutatingOperationRefreshSetting](./kibana-plugin-server.mutatingoperationrefreshsetting.md) | Elasticsearch Refresh setting for mutating operation | | [OnPostAuthHandler](./kibana-plugin-server.onpostauthhandler.md) | See [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md). | | [OnPreAuthHandler](./kibana-plugin-server.onpreauthhandler.md) | See [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md). | | [PluginInitializer](./kibana-plugin-server.plugininitializer.md) | The plugin export at the root of a plugin's server directory should conform to this interface. | diff --git a/docs/development/core/server/kibana-plugin-server.mutatingoperationrefreshsetting.md b/docs/development/core/server/kibana-plugin-server.mutatingoperationrefreshsetting.md new file mode 100644 index 0000000000000..94c8fa8c22ef6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.mutatingoperationrefreshsetting.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [MutatingOperationRefreshSetting](./kibana-plugin-server.mutatingoperationrefreshsetting.md) + +## MutatingOperationRefreshSetting type + +Elasticsearch Refresh setting for mutating operation + +Signature: + +```typescript +export declare type MutatingOperationRefreshSetting = boolean | 'wait_for'; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.md new file mode 100644 index 0000000000000..920a6ca224df4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) + +## SavedObjectsBulkUpdateOptions interface + + +Signature: + +```typescript +export interface SavedObjectsBulkUpdateOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [refresh](./kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md new file mode 100644 index 0000000000000..35e9e6483da10 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsBulkUpdateOptions](./kibana-plugin-server.savedobjectsbulkupdateoptions.md) > [refresh](./kibana-plugin-server.savedobjectsbulkupdateoptions.refresh.md) + +## SavedObjectsBulkUpdateOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkupdate.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkupdate.md index 107e71959f706..30db524ffa02c 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkupdate.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.bulkupdate.md @@ -9,7 +9,7 @@ Bulk Updates multiple SavedObject at once Signature: ```typescript -bulkUpdate(objects: Array>, options?: SavedObjectsBaseOptions): Promise>; +bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; ``` ## Parameters @@ -17,7 +17,7 @@ bulkUpdate(objects: ArrayArray<SavedObjectsBulkUpdateObject<T>> | | -| options | SavedObjectsBaseOptions | | +| options | SavedObjectsBulkUpdateOptions | | Returns: diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.delete.md b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.delete.md index 657f56d591e77..c20c7e886490a 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsclient.delete.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsclient.delete.md @@ -9,7 +9,7 @@ Deletes a SavedObject Signature: ```typescript -delete(type: string, id: string, options?: SavedObjectsBaseOptions): Promise<{}>; +delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; ``` ## Parameters @@ -18,7 +18,7 @@ delete(type: string, id: string, options?: SavedObjectsBaseOptions): Promise<{}> | --- | --- | --- | | type | string | | | id | string | | -| options | SavedObjectsBaseOptions | | +| options | SavedObjectsDeleteOptions | | Returns: diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.md index 16549e420ac01..e4ad636056915 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.md @@ -19,4 +19,5 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions | [migrationVersion](./kibana-plugin-server.savedobjectscreateoptions.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | | [overwrite](./kibana-plugin-server.savedobjectscreateoptions.overwrite.md) | boolean | Overwrite existing documents (defaults to false) | | [references](./kibana-plugin-server.savedobjectscreateoptions.references.md) | SavedObjectReference[] | | +| [refresh](./kibana-plugin-server.savedobjectscreateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.refresh.md new file mode 100644 index 0000000000000..785874a12c8c4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectscreateoptions.refresh.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-server.savedobjectscreateoptions.md) > [refresh](./kibana-plugin-server.savedobjectscreateoptions.refresh.md) + +## SavedObjectsCreateOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.md new file mode 100644 index 0000000000000..2c641ba5cc8d8 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) + +## SavedObjectsDeleteOptions interface + + +Signature: + +```typescript +export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [refresh](./kibana-plugin-server.savedobjectsdeleteoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | + diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.refresh.md new file mode 100644 index 0000000000000..782c52956f297 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsdeleteoptions.refresh.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsDeleteOptions](./kibana-plugin-server.savedobjectsdeleteoptions.md) > [refresh](./kibana-plugin-server.savedobjectsdeleteoptions.refresh.md) + +## SavedObjectsDeleteOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.md index 7fcd362e937a0..49e8946ad2826 100644 --- a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.md +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.md @@ -16,5 +16,6 @@ export interface SavedObjectsUpdateOptions extends SavedObjectsBaseOptions | Property | Type | Description | | --- | --- | --- | | [references](./kibana-plugin-server.savedobjectsupdateoptions.references.md) | SavedObjectReference[] | A reference to another saved object. | +| [refresh](./kibana-plugin-server.savedobjectsupdateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | | [version](./kibana-plugin-server.savedobjectsupdateoptions.version.md) | string | An opaque version number which changes on each successful write operation. Can be used for implementing optimistic concurrency control. | diff --git a/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.refresh.md b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.refresh.md new file mode 100644 index 0000000000000..bb1142c242012 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-server.savedobjectsupdateoptions.refresh.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [SavedObjectsUpdateOptions](./kibana-plugin-server.savedobjectsupdateoptions.md) > [refresh](./kibana-plugin-server.savedobjectsupdateoptions.refresh.md) + +## SavedObjectsUpdateOptions.refresh property + +The Elasticsearch Refresh setting for this operation + +Signature: + +```typescript +refresh?: MutatingOperationRefreshSetting; +``` diff --git a/src/core/server/index.ts b/src/core/server/index.ts index e0d230006d587..c3f63c7c26e97 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -139,6 +139,7 @@ export { SavedObjectsBulkCreateObject, SavedObjectsBulkGetObject, SavedObjectsBulkUpdateObject, + SavedObjectsBulkUpdateOptions, SavedObjectsBulkResponse, SavedObjectsBulkUpdateResponse, SavedObjectsClient, @@ -166,6 +167,7 @@ export { SavedObjectsLegacyService, SavedObjectsUpdateOptions, SavedObjectsUpdateResponse, + SavedObjectsDeleteOptions, } from './saved_objects'; export { @@ -184,6 +186,7 @@ export { SavedObjectAttributeSingle, SavedObjectReference, SavedObjectsBaseOptions, + MutatingOperationRefreshSetting, SavedObjectsClientContract, SavedObjectsFindOptions, SavedObjectsMigrationVersion, diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index e514210752f51..9941bbd03f5dc 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -417,6 +417,32 @@ describe('SavedObjectsRepository', () => { }); }); + it('defaults to a refresh setting of `wait_for`', async () => { + await savedObjectsRepository.create('index-pattern', { + id: 'logstash-*', + title: 'Logstash', + }); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: 'wait_for' + }); + }); + + it('accepts custom refresh settings', async () => { + await savedObjectsRepository.create('index-pattern', { + id: 'logstash-*', + title: 'Logstash', + }, { + refresh: true + }); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: true + }); + }); + it('should use create action if ID defined and overwrite=false', async () => { await savedObjectsRepository.create( 'index-pattern', @@ -645,6 +671,61 @@ describe('SavedObjectsRepository', () => { expect(onBeforeWrite).toHaveBeenCalledTimes(1); }); + it('defaults to a refresh setting of `wait_for`', async () => { + callAdminCluster.mockReturnValue({ + items: [ + { create: { type: 'config', id: 'config:one', _primary_term: 1, _seq_no: 1 } }, + ], + }); + + await savedObjectsRepository.bulkCreate([ + { + type: 'config', + id: 'one', + attributes: { title: 'Test One' }, + references: [{ name: 'ref_0', type: 'test', id: '1' }], + } + ]); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: 'wait_for' + }); + }); + + it('accepts a custom refresh setting', async () => { + callAdminCluster.mockReturnValue({ + items: [ + { create: { type: 'config', id: 'config:one', _primary_term: 1, _seq_no: 1 } }, + { create: { type: 'index-pattern', id: 'config:two', _primary_term: 1, _seq_no: 1 } }, + ], + }); + + await savedObjectsRepository.bulkCreate([ + { + type: 'config', + id: 'one', + attributes: { title: 'Test One' }, + references: [{ name: 'ref_0', type: 'test', id: '1' }], + }, + { + type: 'index-pattern', + id: 'two', + attributes: { title: 'Test Two' }, + references: [{ name: 'ref_0', type: 'test', id: '2' }], + }, + ], { + refresh: true + }); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: true + }); + }); + it('migrates the docs', async () => { callAdminCluster.mockReturnValue({ items: [ @@ -1087,6 +1168,28 @@ describe('SavedObjectsRepository', () => { expect(onBeforeWrite).toHaveBeenCalledTimes(1); }); + + it('defaults to a refresh setting of `wait_for`', async () => { + callAdminCluster.mockReturnValue({ result: 'deleted' }); + await savedObjectsRepository.delete('globaltype', 'logstash-*'); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: 'wait_for' + }); + }); + + it(`accepts a custom refresh setting`, async () => { + callAdminCluster.mockReturnValue({ result: 'deleted' }); + await savedObjectsRepository.delete('globaltype', 'logstash-*', { + refresh: false + }); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: false, + }); + }); }); describe('#deleteByNamespace', () => { @@ -1126,6 +1229,26 @@ describe('SavedObjectsRepository', () => { refresh: 'wait_for', }); }); + + it('defaults to a refresh setting of `wait_for`', async () => { + callAdminCluster.mockReturnValue(deleteByQueryResults); + await savedObjectsRepository.deleteByNamespace('my-namespace'); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: 'wait_for', + }); + }); + + it('accepts a custom refresh setting', async () => { + callAdminCluster.mockReturnValue(deleteByQueryResults); + await savedObjectsRepository.deleteByNamespace('my-namespace', { refresh: true }); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: true, + }); + }); }); describe('#find', () => { @@ -1984,6 +2107,40 @@ describe('SavedObjectsRepository', () => { expect(onBeforeWrite).toHaveBeenCalledTimes(1); }); + + it('defaults to a refresh setting of `wait_for`', async () => { + await savedObjectsRepository.update( + 'globaltype', + 'foo', + { + name: 'bar', + } + ); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: 'wait_for' + }); + }); + + it('accepts a custom refresh setting', async () => { + await savedObjectsRepository.update( + 'globaltype', + 'foo', + { + name: 'bar', + }, + { + refresh: true, + namespace: 'foo-namespace', + } + ); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: true + }); + }); }); describe('#bulkUpdate', () => { @@ -2284,6 +2441,44 @@ describe('SavedObjectsRepository', () => { }); }); + it('defaults to a refresh setting of `wait_for`', async () => { + const objects = [ + { + type: 'index-pattern', + id: `logstash-no-ref`, + attributes: { title: `Testing no-ref` }, + references: [] + } + ]; + + mockValidResponse(objects); + + await savedObjectsRepository.bulkUpdate(objects); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ refresh: 'wait_for' }); + }); + + it('accepts a custom refresh setting', async () => { + const objects = [ + { + type: 'index-pattern', + id: `logstash-no-ref`, + attributes: { title: `Testing no-ref` }, + references: [] + } + ]; + + mockValidResponse(objects); + + await savedObjectsRepository.bulkUpdate(objects, { refresh: true }); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ refresh: true }); + }); + it(`prepends namespace to the id but doesn't add namespace to body when providing namespace for namespaced type`, async () => { const objects = [ @@ -2526,6 +2721,29 @@ describe('SavedObjectsRepository', () => { }); }); + it('defaults to a refresh setting of `wait_for`', async () => { + await savedObjectsRepository.incrementCounter('config', 'doesnotexist', 'buildNum', { + namespace: 'foo-namespace' + }); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: 'wait_for' + }); + }); + + it('accepts a custom refresh setting', async () => { + await savedObjectsRepository.incrementCounter('config', 'doesnotexist', 'buildNum', { + namespace: 'foo-namespace', + refresh: true + }); + + expect(callAdminCluster).toHaveBeenCalledTimes(1); + expect(callAdminCluster.mock.calls[0][1]).toMatchObject({ + refresh: true + }); + }); + it(`prepends namespace to the id but doesn't add namespace to body when providing namespace for namespaced type`, async () => { await savedObjectsRepository.incrementCounter('config', '6.0.0-alpha1', 'buildNum', { namespace: 'foo-namespace', diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 179aa6fffc7de..54b9938decb0a 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -40,6 +40,9 @@ import { SavedObjectsUpdateOptions, SavedObjectsUpdateResponse, SavedObjectsBulkUpdateObject, + SavedObjectsBulkUpdateOptions, + SavedObjectsDeleteOptions, + SavedObjectsDeleteByNamespaceOptions, } from '../saved_objects_client'; import { SavedObject, @@ -47,6 +50,7 @@ import { SavedObjectsBaseOptions, SavedObjectsFindOptions, SavedObjectsMigrationVersion, + MutatingOperationRefreshSetting, } from '../../types'; import { validateConvertFilterToKueryNode } from './filter_utils'; @@ -83,8 +87,12 @@ export interface SavedObjectsRepositoryOptions { export interface IncrementCounterOptions extends SavedObjectsBaseOptions { migrationVersion?: SavedObjectsMigrationVersion; + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; } +const DEFAULT_REFRESH_SETTING = 'wait_for'; + export class SavedObjectsRepository { private _migrator: KibanaMigrator; private _index: string; @@ -154,7 +162,14 @@ export class SavedObjectsRepository { attributes: T, options: SavedObjectsCreateOptions = {} ): Promise> { - const { id, migrationVersion, overwrite = false, namespace, references = [] } = options; + const { + id, + migrationVersion, + overwrite = false, + namespace, + references = [], + refresh = DEFAULT_REFRESH_SETTING, + } = options; if (!this._allowedTypes.includes(type)) { throw SavedObjectsErrorHelpers.createUnsupportedTypeError(type); @@ -179,7 +194,7 @@ export class SavedObjectsRepository { const response = await this._writeToCluster(method, { id: raw._id, index: this.getIndexForType(type), - refresh: 'wait_for', + refresh, body: raw._source, }); @@ -210,7 +225,7 @@ export class SavedObjectsRepository { objects: Array>, options: SavedObjectsCreateOptions = {} ): Promise> { - const { namespace, overwrite = false } = options; + const { namespace, overwrite = false, refresh = DEFAULT_REFRESH_SETTING } = options; const time = this._getCurrentTime(); const bulkCreateParams: object[] = []; @@ -256,7 +271,7 @@ export class SavedObjectsRepository { }); const esResponse = await this._writeToCluster('bulk', { - refresh: 'wait_for', + refresh, body: bulkCreateParams, }); @@ -308,17 +323,17 @@ export class SavedObjectsRepository { * @property {string} [options.namespace] * @returns {promise} */ - async delete(type: string, id: string, options: SavedObjectsBaseOptions = {}): Promise<{}> { + async delete(type: string, id: string, options: SavedObjectsDeleteOptions = {}): Promise<{}> { if (!this._allowedTypes.includes(type)) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(); } - const { namespace } = options; + const { namespace, refresh = DEFAULT_REFRESH_SETTING } = options; const response = await this._writeToCluster('delete', { id: this._serializer.generateRawId(namespace, type, id), index: this.getIndexForType(type), - refresh: 'wait_for', + refresh, ignore: [404], }); @@ -345,11 +360,16 @@ export class SavedObjectsRepository { * @param {string} namespace * @returns {promise} - { took, timed_out, total, deleted, batches, version_conflicts, noops, retries, failures } */ - async deleteByNamespace(namespace: string): Promise { + async deleteByNamespace( + namespace: string, + options: SavedObjectsDeleteByNamespaceOptions = {} + ): Promise { if (!namespace || typeof namespace !== 'string') { throw new TypeError(`namespace is required, and must be a string`); } + const { refresh = DEFAULT_REFRESH_SETTING } = options; + const allTypes = Object.keys(getRootPropertiesObjects(this._mappings)); const typesToDelete = allTypes.filter(type => !this._schema.isNamespaceAgnostic(type)); @@ -357,7 +377,7 @@ export class SavedObjectsRepository { const esOptions = { index: this.getIndicesForTypes(typesToDelete), ignore: [404], - refresh: 'wait_for', + refresh, body: { conflicts: 'proceed', ...getSearchDsl(this._mappings, this._schema, { @@ -626,7 +646,7 @@ export class SavedObjectsRepository { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - const { version, namespace, references } = options; + const { version, namespace, references, refresh = DEFAULT_REFRESH_SETTING } = options; const time = this._getCurrentTime(); @@ -643,7 +663,7 @@ export class SavedObjectsRepository { id: this._serializer.generateRawId(namespace, type, id), index: this.getIndexForType(type), ...(version && decodeRequestVersion(version)), - refresh: 'wait_for', + refresh, ignore: [404], body: { doc, @@ -675,7 +695,7 @@ export class SavedObjectsRepository { */ async bulkUpdate( objects: Array>, - options: SavedObjectsBaseOptions = {} + options: SavedObjectsBulkUpdateOptions = {} ): Promise> { const time = this._getCurrentTime(); const bulkUpdateParams: object[] = []; @@ -729,9 +749,10 @@ export class SavedObjectsRepository { return { tag: 'Right' as 'Right', value: expectedResult }; }); + const { refresh = DEFAULT_REFRESH_SETTING } = options; const esResponse = bulkUpdateParams.length ? await this._writeToCluster('bulk', { - refresh: 'wait_for', + refresh, body: bulkUpdateParams, }) : {}; @@ -794,7 +815,7 @@ export class SavedObjectsRepository { throw SavedObjectsErrorHelpers.createUnsupportedTypeError(type); } - const { migrationVersion, namespace } = options; + const { migrationVersion, namespace, refresh = DEFAULT_REFRESH_SETTING } = options; const time = this._getCurrentTime(); @@ -811,7 +832,7 @@ export class SavedObjectsRepository { const response = await this._writeToCluster('update', { id: this._serializer.generateRawId(namespace, type, id), index: this.getIndexForType(type), - refresh: 'wait_for', + refresh, _source: true, body: { script: { diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index 4e04a08bd5212..550e8a1de0d80 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -24,6 +24,7 @@ import { SavedObjectReference, SavedObjectsMigrationVersion, SavedObjectsBaseOptions, + MutatingOperationRefreshSetting, SavedObjectsFindOptions, } from '../types'; import { SavedObjectsErrorHelpers } from './lib/errors'; @@ -40,6 +41,8 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions { /** {@inheritDoc SavedObjectsMigrationVersion} */ migrationVersion?: SavedObjectsMigrationVersion; references?: SavedObjectReference[]; + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; } /** @@ -101,6 +104,35 @@ export interface SavedObjectsUpdateOptions extends SavedObjectsBaseOptions { version?: string; /** {@inheritdoc SavedObjectReference} */ references?: SavedObjectReference[]; + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; +} + +/** + * + * @public + */ +export interface SavedObjectsBulkUpdateOptions extends SavedObjectsBaseOptions { + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; +} + +/** + * + * @public + */ +export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions { + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; +} + +/** + * + * @public + */ +export interface SavedObjectsDeleteByNamespaceOptions extends SavedObjectsBaseOptions { + /** The Elasticsearch Refresh setting for this operation */ + refresh?: MutatingOperationRefreshSetting; } /** @@ -189,7 +221,7 @@ export class SavedObjectsClient { * @param id * @param options */ - async delete(type: string, id: string, options: SavedObjectsBaseOptions = {}) { + async delete(type: string, id: string, options: SavedObjectsDeleteOptions = {}) { return await this._repository.delete(type, id, options); } @@ -260,7 +292,7 @@ export class SavedObjectsClient { */ async bulkUpdate( objects: Array>, - options?: SavedObjectsBaseOptions + options?: SavedObjectsBulkUpdateOptions ): Promise> { return await this._repository.bulkUpdate(objects, options); } diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index a968b6d9392f8..2c6f5e4a520a7 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -142,6 +142,12 @@ export interface SavedObjectsBaseOptions { namespace?: string; } +/** + * Elasticsearch Refresh setting for mutating operation + * @public + */ +export type MutatingOperationRefreshSetting = boolean | 'wait_for'; + /** * Saved Objects is Kibana's data persisentence mechanism allowing plugins to * use Elasticsearch for storing plugin state. diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 9740f1f7032d1..e7a4cdc0174b0 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -942,6 +942,9 @@ export type MIGRATION_ASSISTANCE_INDEX_ACTION = 'upgrade' | 'reindex'; // @public (undocumented) export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; +// @public +export type MutatingOperationRefreshSetting = boolean | 'wait_for'; + // Warning: (ae-forgotten-export) The symbol "OnPostAuthResult" needs to be exported by the entry point index.d.ts // // @public @@ -1196,6 +1199,11 @@ export interface SavedObjectsBulkUpdateObject { // (undocumented) @@ -1208,9 +1216,9 @@ export class SavedObjectsClient { constructor(repository: SavedObjectsRepository); bulkCreate(objects: Array>, options?: SavedObjectsCreateOptions): Promise>; bulkGet(objects?: SavedObjectsBulkGetObject[], options?: SavedObjectsBaseOptions): Promise>; - bulkUpdate(objects: Array>, options?: SavedObjectsBaseOptions): Promise>; + bulkUpdate(objects: Array>, options?: SavedObjectsBulkUpdateOptions): Promise>; create(type: string, attributes: T, options?: SavedObjectsCreateOptions): Promise>; - delete(type: string, id: string, options?: SavedObjectsBaseOptions): Promise<{}>; + delete(type: string, id: string, options?: SavedObjectsDeleteOptions): Promise<{}>; // (undocumented) errors: typeof SavedObjectsErrorHelpers; // (undocumented) @@ -1247,6 +1255,12 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions { overwrite?: boolean; // (undocumented) references?: SavedObjectReference[]; + refresh?: MutatingOperationRefreshSetting; +} + +// @public (undocumented) +export interface SavedObjectsDeleteOptions extends SavedObjectsBaseOptions { + refresh?: MutatingOperationRefreshSetting; } // @public (undocumented) @@ -1554,6 +1568,7 @@ export class SavedObjectsSerializer { // @public (undocumented) export interface SavedObjectsUpdateOptions extends SavedObjectsBaseOptions { references?: SavedObjectReference[]; + refresh?: MutatingOperationRefreshSetting; version?: string; } From 82d544775138bfda0162e165c56be9e4e24be713 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 25 Oct 2019 09:50:52 +0200 Subject: [PATCH 134/191] [Graph] Shim plugin (#47469) --- src/dev/i18n/extractors/code.js | 2 +- .../ui/public/kbn_top_nav/kbn_top_nav.js | 12 +- .../public/legacy_compat/angular_config.tsx | 6 +- src/legacy/ui/public/modals/confirm_modal.js | 24 +- .../new_platform/new_platform.karma_mock.js | 4 + src/legacy/ui/public/private/private.js | 146 +-- src/legacy/ui/public/promises/promises.js | 10 +- .../show_saved_object_save_modal.tsx | 2 +- .../state_management/config_provider.js | 32 +- x-pack/legacy/plugins/graph/index.js | 2 +- .../angular/directives/graph_inspect.js | 17 - .../angular/services/saved_workspace.js | 8 - .../angular/services/saved_workspaces.js | 5 - .../graph/public/angular/templates/index.html | 44 +- .../public/angular/templates/inspect.html | 43 - x-pack/legacy/plugins/graph/public/app.js | 1010 ++++++++--------- .../public/hacks/toggle_app_link_in_nav.js | 22 +- x-pack/legacy/plugins/graph/public/index.ts | 61 + x-pack/legacy/plugins/graph/public/plugin.ts | 79 ++ .../legacy/plugins/graph/public/render_app.ts | 145 +++ .../plugins/graph/public/services/url.ts | 17 +- .../public/state_management/meta_data.test.ts | 12 +- .../graph/public/state_management/mocks.ts | 8 +- .../graph/public/state_management/store.ts | 4 +- 24 files changed, 984 insertions(+), 731 deletions(-) delete mode 100644 x-pack/legacy/plugins/graph/public/angular/directives/graph_inspect.js delete mode 100644 x-pack/legacy/plugins/graph/public/angular/templates/inspect.html create mode 100644 x-pack/legacy/plugins/graph/public/index.ts create mode 100644 x-pack/legacy/plugins/graph/public/plugin.ts create mode 100644 x-pack/legacy/plugins/graph/public/render_app.ts diff --git a/src/dev/i18n/extractors/code.js b/src/dev/i18n/extractors/code.js index 58ca059be5491..fa0d834824e97 100644 --- a/src/dev/i18n/extractors/code.js +++ b/src/dev/i18n/extractors/code.js @@ -67,7 +67,7 @@ export function* extractCodeMessages(buffer, reporter) { try { ast = parse(buffer.toString(), { sourceType: 'module', - plugins: ['jsx', 'typescript', 'objectRestSpread', 'classProperties', 'asyncGenerators'], + plugins: ['jsx', 'typescript', 'objectRestSpread', 'classProperties', 'asyncGenerators', 'dynamicImport'], }); } catch (error) { if (error instanceof SyntaxError) { diff --git a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js index 79365eb5cf1cc..72fa6bc4c1182 100644 --- a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js +++ b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js @@ -24,7 +24,7 @@ import { TopNavMenu } from '../../../core_plugins/kibana_react/public'; const module = uiModules.get('kibana'); -module.directive('kbnTopNav', () => { +export function createTopNavDirective() { return { restrict: 'E', template: '', @@ -71,9 +71,11 @@ module.directive('kbnTopNav', () => { return linkFn; } }; -}); +} -module.directive('kbnTopNavHelper', (reactDirective) => { +module.directive('kbnTopNav', createTopNavDirective); + +export function createTopNavHelper(reactDirective) { return reactDirective( wrapInI18nContext(TopNavMenu), [ @@ -113,4 +115,6 @@ module.directive('kbnTopNavHelper', (reactDirective) => { 'showAutoRefreshOnly', ], ); -}); +} + +module.directive('kbnTopNavHelper', createTopNavHelper); diff --git a/src/legacy/ui/public/legacy_compat/angular_config.tsx b/src/legacy/ui/public/legacy_compat/angular_config.tsx index 8eac31e24530c..785b0345aa999 100644 --- a/src/legacy/ui/public/legacy_compat/angular_config.tsx +++ b/src/legacy/ui/public/legacy_compat/angular_config.tsx @@ -286,14 +286,12 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => ( const $setupUrlOverflowHandling = (newPlatform: CoreStart) => ( $location: ILocationService, - $rootScope: IRootScopeService, - Private: any, - config: any + $rootScope: IRootScopeService ) => { const urlOverflow = new UrlOverflowService(); const check = () => { // disable long url checks when storing state in session storage - if (config.get('state:storeInSessionStorage')) { + if (newPlatform.uiSettings.get('state:storeInSessionStorage')) { return; } diff --git a/src/legacy/ui/public/modals/confirm_modal.js b/src/legacy/ui/public/modals/confirm_modal.js index 6d5abfca64aaf..9c3f46da4e927 100644 --- a/src/legacy/ui/public/modals/confirm_modal.js +++ b/src/legacy/ui/public/modals/confirm_modal.js @@ -36,16 +36,7 @@ export const ConfirmationButtonTypes = { CANCEL: CANCEL_BUTTON }; -/** - * @typedef {Object} ConfirmModalOptions - * @property {String} confirmButtonText - * @property {String=} cancelButtonText - * @property {function} onConfirm - * @property {function=} onCancel - * @property {String=} title - If given, shows a title on the confirm modal. - */ - -module.factory('confirmModal', function ($rootScope, $compile) { +export function confirmModalFactory($rootScope, $compile) { let modalPopover; const confirmQueue = []; @@ -114,4 +105,15 @@ module.factory('confirmModal', function ($rootScope, $compile) { } } }; -}); +} + +/** + * @typedef {Object} ConfirmModalOptions + * @property {String} confirmButtonText + * @property {String=} cancelButtonText + * @property {function} onConfirm + * @property {function=} onCancel + * @property {String=} title - If given, shows a title on the confirm modal. + */ + +module.factory('confirmModal', confirmModalFactory); diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index ae5c0a83bd781..20ea9c9141aca 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -96,6 +96,10 @@ export const npStart = { export function __setup__(coreSetup) { npSetup.core = coreSetup; + + // no-op application register calls (this is overwritten to + // bootstrap an LP plugin outside of tests) + npSetup.core.application.register = () => {}; } export function __start__(coreStart) { diff --git a/src/legacy/ui/public/private/private.js b/src/legacy/ui/public/private/private.js index ef5c59c21dd7a..6257c12ecf696 100644 --- a/src/legacy/ui/public/private/private.js +++ b/src/legacy/ui/public/private/private.js @@ -108,98 +108,100 @@ function name(fn) { return fn.name || fn.toString().split('\n').shift(); } -uiModules.get('kibana/private') - .provider('Private', function () { - const provider = this; - - // one cache/swaps per Provider - const cache = {}; - const swaps = {}; +export function PrivateProvider() { + const provider = this; - // return the uniq id for this function - function identify(fn) { - if (typeof fn !== 'function') { - throw new TypeError('Expected private module "' + fn + '" to be a function'); - } + // one cache/swaps per Provider + const cache = {}; + const swaps = {}; - if (fn.$$id) return fn.$$id; - else return (fn.$$id = nextId()); + // return the uniq id for this function + function identify(fn) { + if (typeof fn !== 'function') { + throw new TypeError('Expected private module "' + fn + '" to be a function'); } - provider.stub = function (fn, instance) { - cache[identify(fn)] = instance; - return instance; - }; + if (fn.$$id) return fn.$$id; + else return (fn.$$id = nextId()); + } - provider.swap = function (fn, prov) { - const id = identify(fn); - swaps[id] = prov; - }; + provider.stub = function (fn, instance) { + cache[identify(fn)] = instance; + return instance; + }; - provider.$get = ['$injector', function PrivateFactory($injector) { + provider.swap = function (fn, prov) { + const id = identify(fn); + swaps[id] = prov; + }; - // prevent circular deps by tracking where we came from - const privPath = []; - const pathToString = function () { - return privPath.map(name).join(' -> '); - }; + provider.$get = ['$injector', function PrivateFactory($injector) { - // call a private provider and return the instance it creates - function instantiate(prov, locals) { - if (~privPath.indexOf(prov)) { - throw new Error( - 'Circular reference to "' + name(prov) + '"' + - ' found while resolving private deps: ' + pathToString() - ); - } + // prevent circular deps by tracking where we came from + const privPath = []; + const pathToString = function () { + return privPath.map(name).join(' -> '); + }; - privPath.push(prov); + // call a private provider and return the instance it creates + function instantiate(prov, locals) { + if (~privPath.indexOf(prov)) { + throw new Error( + 'Circular reference to "' + name(prov) + '"' + + ' found while resolving private deps: ' + pathToString() + ); + } - const context = {}; - let instance = $injector.invoke(prov, context, locals); - if (!_.isObject(instance)) instance = context; + privPath.push(prov); - privPath.pop(); - return instance; - } + const context = {}; + let instance = $injector.invoke(prov, context, locals); + if (!_.isObject(instance)) instance = context; - // retrieve an instance from cache or create and store on - function get(id, prov, $delegateId, $delegateProv) { - if (cache[id]) return cache[id]; + privPath.pop(); + return instance; + } - let instance; + // retrieve an instance from cache or create and store on + function get(id, prov, $delegateId, $delegateProv) { + if (cache[id]) return cache[id]; - if ($delegateId != null && $delegateProv != null) { - instance = instantiate(prov, { - $decorate: _.partial(get, $delegateId, $delegateProv) - }); - } else { - instance = instantiate(prov); - } + let instance; - return (cache[id] = instance); + if ($delegateId != null && $delegateProv != null) { + instance = instantiate(prov, { + $decorate: _.partial(get, $delegateId, $delegateProv) + }); + } else { + instance = instantiate(prov); } - // main api, get the appropriate instance for a provider - function Private(prov) { - let id = identify(prov); - let $delegateId; - let $delegateProv; + return (cache[id] = instance); + } - if (swaps[id]) { - $delegateId = id; - $delegateProv = prov; + // main api, get the appropriate instance for a provider + function Private(prov) { + let id = identify(prov); + let $delegateId; + let $delegateProv; - prov = swaps[$delegateId]; - id = identify(prov); - } + if (swaps[id]) { + $delegateId = id; + $delegateProv = prov; - return get(id, prov, $delegateId, $delegateProv); + prov = swaps[$delegateId]; + id = identify(prov); } - Private.stub = provider.stub; - Private.swap = provider.swap; + return get(id, prov, $delegateId, $delegateProv); + } + + Private.stub = provider.stub; + Private.swap = provider.swap; + + return Private; + }]; +} - return Private; - }]; - }); +uiModules.get('kibana/private') + .provider('Private', PrivateProvider); diff --git a/src/legacy/ui/public/promises/promises.js b/src/legacy/ui/public/promises/promises.js index 99c9a11be7431..af8a5081e0c55 100644 --- a/src/legacy/ui/public/promises/promises.js +++ b/src/legacy/ui/public/promises/promises.js @@ -22,9 +22,7 @@ import { uiModules } from '../modules'; const module = uiModules.get('kibana'); -// Provides a tiny subset of the excellent API from -// bluebird, reimplemented using the $q service -module.service('Promise', function ($q, $timeout) { +export function PromiseServiceCreator($q, $timeout) { function Promise(fn) { if (typeof this === 'undefined') throw new Error('Promise constructor must be called with "new"'); @@ -122,4 +120,8 @@ module.service('Promise', function ($q, $timeout) { }; return Promise; -}); +} + +// Provides a tiny subset of the excellent API from +// bluebird, reimplemented using the $q service +module.service('Promise', PromiseServiceCreator); diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx index 6aea3c72e0c34..3c691c692948a 100644 --- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx @@ -34,7 +34,7 @@ function isSuccess(result: SaveResult): result is { id?: string } { return 'id' in result; } -interface MinimalSaveModalProps { +export interface MinimalSaveModalProps { onSave: (...args: any[]) => Promise; onClose: () => void; } diff --git a/src/legacy/ui/public/state_management/config_provider.js b/src/legacy/ui/public/state_management/config_provider.js index 090210cc8723e..ec770e7fef6ca 100644 --- a/src/legacy/ui/public/state_management/config_provider.js +++ b/src/legacy/ui/public/state_management/config_provider.js @@ -25,21 +25,23 @@ import { uiModules } from '../modules'; -uiModules.get('kibana/state_management') - .provider('stateManagementConfig', class StateManagementConfigProvider { - _enabled = true +export class StateManagementConfigProvider { + _enabled = true + + $get(/* inject stuff */) { + return { + enabled: this._enabled, + }; + } - $get(/* inject stuff */) { - return { - enabled: this._enabled, - }; - } + disable() { + this._enabled = false; + } - disable() { - this._enabled = false; - } + enable() { + this._enabled = true; + } +} - enable() { - this._enabled = true; - } - }); +uiModules.get('kibana/state_management') + .provider('stateManagementConfig', StateManagementConfigProvider); diff --git a/x-pack/legacy/plugins/graph/index.js b/x-pack/legacy/plugins/graph/index.js index 1a61caca7a7c1..9ece9966b7da4 100644 --- a/x-pack/legacy/plugins/graph/index.js +++ b/x-pack/legacy/plugins/graph/index.js @@ -23,7 +23,7 @@ export function graph(kibana) { order: 9000, icon: 'plugins/graph/icon.png', euiIconType: 'graphApp', - main: 'plugins/graph/app', + main: 'plugins/graph/index', }, styleSheetPaths: resolve(__dirname, 'public/index.scss'), hacks: ['plugins/graph/hacks/toggle_app_link_in_nav'], diff --git a/x-pack/legacy/plugins/graph/public/angular/directives/graph_inspect.js b/x-pack/legacy/plugins/graph/public/angular/directives/graph_inspect.js deleted file mode 100644 index 1e6622fd796fb..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/directives/graph_inspect.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { uiModules } from 'ui/modules'; -import template from '../templates/inspect.html'; -const app = uiModules.get('app/graph'); - -app.directive('graphInspect', function () { - return { - replace: true, - restrict: 'E', - template, - }; -}); diff --git a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js index 1d28b4ba5ab30..444e68dd03520 100644 --- a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js +++ b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { uiModules } from 'ui/modules'; import { SavedObjectProvider } from 'ui/saved_objects/saved_object'; import { i18n } from '@kbn/i18n'; import { @@ -12,8 +11,6 @@ import { injectReferences, } from './saved_workspace_references'; -const module = uiModules.get('app/dashboard'); - export function SavedWorkspaceProvider(Private) { // SavedWorkspace constructor. Usually you'd interact with an instance of this. // ID is option, without it one will be generated on save. @@ -68,8 +65,3 @@ export function SavedWorkspaceProvider(Private) { SavedWorkspace.searchsource = false; return SavedWorkspace; } - -// Used only by the savedDashboards service, usually no reason to change this -module.factory('SavedGraphWorkspace', function (Private) { - return Private(SavedWorkspaceProvider); -}); diff --git a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js index 7af0dad3c704c..1fef4b7c38c07 100644 --- a/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js +++ b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js @@ -6,7 +6,6 @@ import _ from 'lodash'; -import { uiModules } from 'ui/modules'; import chrome from 'ui/chrome'; import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; import { SavedObjectsClientProvider } from 'ui/saved_objects'; @@ -87,9 +86,5 @@ export function SavedWorkspacesProvider(kbnUrl, Private, Promise) { }); }; } -// This is the only thing that gets injected into controllers -uiModules.get('app/graph').service('savedGraphWorkspaces', function (Private) { - return Private(SavedWorkspacesProvider); -}); SavedObjectRegistryProvider.register(SavedWorkspacesProvider); diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/index.html b/x-pack/legacy/plugins/graph/public/angular/templates/index.html index a3b025ff9d6df..686f0f590a19c 100644 --- a/x-pack/legacy/plugins/graph/public/angular/templates/index.html +++ b/x-pack/legacy/plugins/graph/public/angular/templates/index.html @@ -4,7 +4,49 @@
- +
+
+ +
+ http://host:port/{{ selectedIndex.name }}/_graph/explore + + +
+
+
+
-
- -
- http://host:port/{{ selectedIndex.name }}/_graph/explore - - -
-
-
-
diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index ba69756e7b070..41e5819bcbf37 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -11,31 +11,10 @@ import React from 'react'; import { Provider } from 'react-redux'; import { isColorDark, hexToRgb } from '@elastic/eui'; -// import the uiExports that we want to "use" -import 'uiExports/fieldFormats'; -import 'uiExports/savedObjectTypes'; - -import 'ui/autoload/all'; -import 'ui/angular-bootstrap'; -import 'ui/kbn_top_nav'; -import 'ui/directives/saved_object_finder'; -import 'ui/directives/input_focus'; -import 'ui/saved_objects/ui/saved_object_save_as_checkbox'; -import 'uiExports/autocompleteProviders'; -import chrome from 'ui/chrome'; -import { uiModules } from 'ui/modules'; -import uiRoutes from 'ui/routes'; -import { addAppRedirectMessageToUrl, toastNotifications } from 'ui/notify'; -import { formatAngularHttpError } from 'ui/notify/lib'; -import { start as data } from '../../../../../src/legacy/core_plugins/data/public/legacy'; -import { SavedObjectsClientProvider } from 'ui/saved_objects'; -import { npStart } from 'ui/new_platform'; -import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; -import { capabilities } from 'ui/capabilities'; +import { KibanaParsedUrl } from 'ui/url/kibana_parsed_url'; import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; -import { Storage } from 'ui/storage'; - -import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; +import { formatAngularHttpError } from 'ui/notify/lib'; +import { addAppRedirectMessageToUrl } from 'ui/notify'; import appTemplate from './angular/templates/index.html'; import listingTemplate from './angular/templates/listing_ng_wrapper.html'; @@ -48,7 +27,6 @@ import { Settings } from './components/settings'; import { GraphVisualization } from './components/graph_visualization'; import gws from './angular/graph_client_workspace.js'; -import { SavedWorkspacesProvider } from './angular/services/saved_workspaces'; import { getEditUrl, getNewPath, getEditPath, setBreadcrumbs } from './services/url'; import { createCachedIndexPatternProvider } from './services/index_pattern_cache'; import { urlTemplateRegex } from './helpers/url_template'; @@ -62,528 +40,528 @@ import { hasFieldsSelector } from './state_management'; -import './angular/directives/graph_inspect'; +export function initGraphApp(angularModule, deps) { + const { + xpackInfo, + chrome, + savedGraphWorkspaces, + toastNotifications, + savedObjectsClient, + indexPatterns, + kbnBaseUrl, + addBasePath, + getBasePath, + npData, + config, + savedObjectRegistry, + capabilities, + coreStart, + $http, + Storage, + canEditDrillDownUrls, + graphSavePolicy, + } = deps; + + const app = angularModule; + + function checkLicense(kbnBaseUrl) { + const licenseAllowsToShowThisPage = xpackInfo.get('features.graph.showAppLink') && + xpackInfo.get('features.graph.enableAppLink'); + if (!licenseAllowsToShowThisPage) { + const message = xpackInfo.get('features.graph.message'); + const newUrl = addAppRedirectMessageToUrl(addBasePath(kbnBaseUrl), message); + window.location.href = newUrl; + throw new Error('Graph license error'); + } + } -const app = uiModules.get('app/graph'); + app.directive('vennDiagram', function (reactDirective) { + return reactDirective(VennDiagram); + }); -function checkLicense(kbnBaseUrl) { - const licenseAllowsToShowThisPage = xpackInfo.get('features.graph.showAppLink') && - xpackInfo.get('features.graph.enableAppLink'); - if (!licenseAllowsToShowThisPage) { - const message = xpackInfo.get('features.graph.message'); - const newUrl = addAppRedirectMessageToUrl(chrome.addBasePath(kbnBaseUrl), message); - window.location.href = newUrl; - throw new Error('Graph license error'); - } -} + app.directive('graphVisualization', function (reactDirective) { + return reactDirective(GraphVisualization); + }); -app.directive('vennDiagram', function (reactDirective) { - return reactDirective(VennDiagram); -}); - -app.directive('graphListing', function (reactDirective) { - return reactDirective(Listing, [ - ['coreStart', { watchDepth: 'reference' }], - ['createItem', { watchDepth: 'reference' }], - ['findItems', { watchDepth: 'reference' }], - ['deleteItems', { watchDepth: 'reference' }], - ['editItem', { watchDepth: 'reference' }], - ['getViewUrl', { watchDepth: 'reference' }], - ['listingLimit', { watchDepth: 'reference' }], - ['hideWriteControls', { watchDepth: 'reference' }], - ['capabilities', { watchDepth: 'reference' }], - ['initialFilter', { watchDepth: 'reference' }], - ]); -}); - -app.directive('graphApp', function (reactDirective) { - return reactDirective(GraphApp, [ - ['store', { watchDepth: 'reference' }], - ['isInitialized', { watchDepth: 'reference' }], - ['currentIndexPattern', { watchDepth: 'reference' }], - ['indexPatternProvider', { watchDepth: 'reference' }], - ['isLoading', { watchDepth: 'reference' }], - ['onQuerySubmit', { watchDepth: 'reference' }], - ['initialQuery', { watchDepth: 'reference' }], - ['confirmWipeWorkspace', { watchDepth: 'reference' }], - ['coreStart', { watchDepth: 'reference' }], - ['noIndexPatterns', { watchDepth: 'reference' }], - ['reduxStore', { watchDepth: 'reference' }], - ['pluginDataStart', { watchDepth: 'reference' }], - ], { restrict: 'A' }); -}); - -app.directive('graphVisualization', function (reactDirective) { - return reactDirective(GraphVisualization, undefined, { restrict: 'A' }); -}); - -if (uiRoutes.enable) { - uiRoutes.enable(); -} + app.directive('graphListing', function (reactDirective) { + return reactDirective(Listing, [ + ['coreStart', { watchDepth: 'reference' }], + ['createItem', { watchDepth: 'reference' }], + ['findItems', { watchDepth: 'reference' }], + ['deleteItems', { watchDepth: 'reference' }], + ['editItem', { watchDepth: 'reference' }], + ['getViewUrl', { watchDepth: 'reference' }], + ['listingLimit', { watchDepth: 'reference' }], + ['hideWriteControls', { watchDepth: 'reference' }], + ['capabilities', { watchDepth: 'reference' }], + ['initialFilter', { watchDepth: 'reference' }], + ]); + }); -uiRoutes - .when('/home', { - template: listingTemplate, - badge: getReadonlyBadge, - controller($injector, $location, $scope, Private, config, kbnBaseUrl) { - checkLicense(kbnBaseUrl); - const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName; - const graphService = services['Graph workspace']; - const kbnUrl = $injector.get('kbnUrl'); + app.directive('graphApp', function (reactDirective) { + return reactDirective(GraphApp, [ + ['store', { watchDepth: 'reference' }], + ['isInitialized', { watchDepth: 'reference' }], + ['currentIndexPattern', { watchDepth: 'reference' }], + ['indexPatternProvider', { watchDepth: 'reference' }], + ['isLoading', { watchDepth: 'reference' }], + ['onQuerySubmit', { watchDepth: 'reference' }], + ['initialQuery', { watchDepth: 'reference' }], + ['confirmWipeWorkspace', { watchDepth: 'reference' }], + ['coreStart', { watchDepth: 'reference' }], + ['noIndexPatterns', { watchDepth: 'reference' }], + ['reduxStore', { watchDepth: 'reference' }], + ['pluginDataStart', { watchDepth: 'reference' }], + ], { restrict: 'A' }); + }); - $scope.listingLimit = config.get('savedObjects:listingLimit'); - $scope.create = () => { - kbnUrl.redirect(getNewPath()); - }; - $scope.find = (search) => { - return graphService.find(search, $scope.listingLimit); - }; - $scope.editItem = (workspace) => { - kbnUrl.redirect(getEditPath(workspace)); - }; - $scope.getViewUrl = (workspace) => getEditUrl(chrome, workspace); - $scope.delete = (workspaces) => { - return graphService.delete(workspaces.map(({ id }) => id)); - }; - $scope.capabilities = capabilities.get().graph; - $scope.initialFilter = ($location.search()).filter || ''; - $scope.coreStart = npStart.core; - setBreadcrumbs({ chrome }); - } - }) - .when('/workspace/:id?', { - template: appTemplate, - badge: getReadonlyBadge, - resolve: { - savedWorkspace: function (savedGraphWorkspaces, $route) { - return $route.current.params.id ? savedGraphWorkspaces.get($route.current.params.id) - .catch( - function () { - toastNotifications.addDanger( - i18n.translate('xpack.graph.missingWorkspaceErrorMessage', { - defaultMessage: 'Missing workspace', - }) - ); - } - ) : savedGraphWorkspaces.get(); - }, - indexPatterns: function (Private) { - const savedObjectsClient = Private(SavedObjectsClientProvider); - - return savedObjectsClient.find({ - type: 'index-pattern', - fields: ['title', 'type'], - perPage: 10000 - }).then(response => response.savedObjects); - }, - GetIndexPatternProvider: function (Private) { - return data.indexPatterns.indexPatterns; - }, - SavedWorkspacesProvider: function (Private) { - return Private(SavedWorkspacesProvider); - } - } - }) - .otherwise({ - redirectTo: '/home' + app.directive('graphVisualization', function (reactDirective) { + return reactDirective(GraphVisualization, undefined, { restrict: 'A' }); }); + app.config(function ($routeProvider) { + $routeProvider.when('/home', { + template: listingTemplate, + badge: getReadonlyBadge, + controller($location, $scope) { + checkLicense(kbnBaseUrl); + const services = savedObjectRegistry.byLoaderPropertiesName; + const graphService = services['Graph workspace']; + + $scope.listingLimit = config.get('savedObjects:listingLimit'); + $scope.create = () => { + $location.url(getNewPath()); + }; + $scope.find = (search) => { + return graphService.find(search, $scope.listingLimit); + }; + $scope.editItem = (workspace) => { + $location.url(getEditPath(workspace)); + }; + $scope.getViewUrl = (workspace) => getEditUrl(addBasePath, workspace); + $scope.delete = (workspaces) => { + return graphService.delete(workspaces.map(({ id }) => id)); + }; + $scope.capabilities = capabilities; + $scope.initialFilter = ($location.search()).filter || ''; + $scope.coreStart = coreStart; + setBreadcrumbs({ chrome }); + } + }) + .when('/workspace/:id?', { + template: appTemplate, + badge: getReadonlyBadge, + resolve: { + savedWorkspace: function ($route) { + return $route.current.params.id ? savedGraphWorkspaces.get($route.current.params.id) + .catch( + function () { + toastNotifications.addDanger( + i18n.translate('xpack.graph.missingWorkspaceErrorMessage', { + defaultMessage: 'Missing workspace', + }) + ); + } + ) : savedGraphWorkspaces.get(); + + }, + //Copied from example found in wizard.js ( Kibana TODO - can't + indexPatterns: function () { + return savedObjectsClient.find({ + type: 'index-pattern', + fields: ['title', 'type'], + perPage: 10000 + }).then(response => response.savedObjects); + }, + GetIndexPatternProvider: function () { + return indexPatterns; + }, + } + }) + .otherwise({ + redirectTo: '/home' + }); + }); -//======== Controller for basic UI ================== -app.controller('graphuiPlugin', function ( - $scope, - $route, - $http, - kbnUrl, - confirmModal, - kbnBaseUrl -) { - checkLicense(kbnBaseUrl); - function handleError(err) { + //======== Controller for basic UI ================== + app.controller('graphuiPlugin', function ($scope, $route, $location, confirmModal) { checkLicense(kbnBaseUrl); - const toastTitle = i18n.translate('xpack.graph.errorToastTitle', { - defaultMessage: 'Graph Error', - description: '"Graph" is a product name and should not be translated.', - }); - if (err instanceof Error) { - toastNotifications.addError(err, { - title: toastTitle, - }); - } else { - toastNotifications.addDanger({ - title: toastTitle, - text: String(err), + + function handleError(err) { + checkLicense(kbnBaseUrl); + const toastTitle = i18n.translate('xpack.graph.errorToastTitle', { + defaultMessage: 'Graph Error', + description: '"Graph" is a product name and should not be translated.', }); + if (err instanceof Error) { + toastNotifications.addError(err, { + title: toastTitle, + }); + } else { + toastNotifications.addDanger({ + title: toastTitle, + text: String(err), + }); + } } - } - async function handleHttpError(error) { - checkLicense(kbnBaseUrl); - toastNotifications.addDanger(formatAngularHttpError(error)); - } + async function handleHttpError(error) { + checkLicense(kbnBaseUrl); + toastNotifications.addDanger(formatAngularHttpError(error)); + } - // Replacement function for graphClientWorkspace's comms so - // that it works with Kibana. - function callNodeProxy(indexName, query, responseHandler) { - const request = { - index: indexName, - query: query - }; - $scope.loading = true; - return $http.post('../api/graph/graphExplore', request) - .then(function (resp) { - if (resp.data.resp.timed_out) { - toastNotifications.addWarning( - i18n.translate('xpack.graph.exploreGraph.timedOutWarningText', { - defaultMessage: 'Exploration timed out', - }) - ); - } - responseHandler(resp.data.resp); - }) - .catch(handleHttpError) - .finally(() => { - $scope.loading = false; - }); - } + // Replacement function for graphClientWorkspace's comms so + // that it works with Kibana. + function callNodeProxy(indexName, query, responseHandler) { + const request = { + index: indexName, + query: query + }; + $scope.loading = true; + return $http.post('../api/graph/graphExplore', request) + .then(function (resp) { + if (resp.data.resp.timed_out) { + toastNotifications.addWarning( + i18n.translate('xpack.graph.exploreGraph.timedOutWarningText', { + defaultMessage: 'Exploration timed out', + }) + ); + } + responseHandler(resp.data.resp); + }) + .catch(handleHttpError) + .finally(() => { + $scope.loading = false; + }); + } - //Helper function for the graphClientWorkspace to perform a query - const callSearchNodeProxy = function (indexName, query, responseHandler) { - const request = { - index: indexName, - body: query - }; - $scope.loading = true; - $http.post('../api/graph/searchProxy', request) - .then(function (resp) { - responseHandler(resp.data.resp); - }) - .catch(handleHttpError) - .finally(() => { - $scope.loading = false; - }); - }; - - $scope.indexPatternProvider = createCachedIndexPatternProvider($route.current.locals.GetIndexPatternProvider.get); - - const store = createGraphStore({ - basePath: chrome.getBasePath(), - indexPatternProvider: $scope.indexPatternProvider, - indexPatterns: $route.current.locals.indexPatterns, - createWorkspace: (indexPattern, exploreControls) => { - const options = { - indexName: indexPattern, - vertex_fields: [], - // Here we have the opportunity to look up labels for nodes... - nodeLabeller: function () { - // console.log(newNodes); - }, - changeHandler: function () { - //Allows DOM to update with graph layout changes. - $scope.$apply(); - }, - graphExploreProxy: callNodeProxy, - searchProxy: callSearchNodeProxy, - exploreControls, + //Helper function for the graphClientWorkspace to perform a query + const callSearchNodeProxy = function (indexName, query, responseHandler) { + const request = { + index: indexName, + body: query }; - $scope.workspace = gws.createWorkspace(options); - }, - setLiveResponseFields: (fields) => { - $scope.liveResponseFields = fields; - }, - setUrlTemplates: (urlTemplates) => { - $scope.urlTemplates = urlTemplates; - }, - getWorkspace: () => { - return $scope.workspace; - }, - getSavedWorkspace: () => { - return $route.current.locals.savedWorkspace; - }, - notifications: npStart.core.notifications, - http: npStart.core.http, - showSaveModal, - setWorkspaceInitialized: () => { - $scope.workspaceInitialized = true; - }, - savePolicy: chrome.getInjected('graphSavePolicy'), - changeUrl: (newUrl) => { - $scope.$evalAsync(() => { - kbnUrl.change(newUrl, {}); - }); - }, - notifyAngular: () => { - $scope.$digest(); - }, - chrome, - }); + $scope.loading = true; + $http.post('../api/graph/searchProxy', request) + .then(function (resp) { + responseHandler(resp.data.resp); + }) + .catch(handleHttpError) + .finally(() => { + $scope.loading = false; + }); + }; - // register things on scope passed down to react components - $scope.pluginDataStart = npStart.plugins.data; - $scope.store = new Storage(window.localStorage); - $scope.coreStart = npStart.core; - $scope.loading = false; - $scope.reduxStore = store; - $scope.savedWorkspace = $route.current.locals.savedWorkspace; - - // register things for legacy angular UI - const allSavingDisabled = chrome.getInjected('graphSavePolicy') === 'none'; - $scope.spymode = 'request'; - $scope.colors = colorChoices; - $scope.isColorDark = (color) => isColorDark(...hexToRgb(color)); - $scope.nodeClick = function (n, $event) { - - //Selection logic - shift key+click helps selects multiple nodes - // Without the shift key we deselect all prior selections (perhaps not - // a great idea for touch devices with no concept of shift key) - if (!$event.shiftKey) { - const prevSelection = n.isSelected; - $scope.workspace.selectNone(); - n.isSelected = prevSelection; - } + $scope.indexPatternProvider = createCachedIndexPatternProvider($route.current.locals.GetIndexPatternProvider.get); + + const store = createGraphStore({ + basePath: getBasePath(), + indexPatternProvider: $scope.indexPatternProvider, + indexPatterns: $route.current.locals.indexPatterns, + createWorkspace: (indexPattern, exploreControls) => { + const options = { + indexName: indexPattern, + vertex_fields: [], + // Here we have the opportunity to look up labels for nodes... + nodeLabeller: function () { + // console.log(newNodes); + }, + changeHandler: function () { + //Allows DOM to update with graph layout changes. + $scope.$apply(); + }, + graphExploreProxy: callNodeProxy, + searchProxy: callSearchNodeProxy, + exploreControls, + }; + $scope.workspace = gws.createWorkspace(options); + }, + setLiveResponseFields: (fields) => { + $scope.liveResponseFields = fields; + }, + setUrlTemplates: (urlTemplates) => { + $scope.urlTemplates = urlTemplates; + }, + getWorkspace: () => { + return $scope.workspace; + }, + getSavedWorkspace: () => { + return $route.current.locals.savedWorkspace; + }, + notifications: coreStart.notifications, + http: coreStart.http, + showSaveModal, + setWorkspaceInitialized: () => { + $scope.workspaceInitialized = true; + }, + savePolicy: graphSavePolicy, + changeUrl: (newUrl) => { + $scope.$evalAsync(() => { + $location.url(newUrl); + }); + }, + notifyAngular: () => { + $scope.$digest(); + }, + chrome, + }); + // register things on scope passed down to react components + $scope.pluginDataStart = npData; + $scope.store = new Storage(window.localStorage); + $scope.coreStart = coreStart; + $scope.loading = false; + $scope.reduxStore = store; + $scope.savedWorkspace = $route.current.locals.savedWorkspace; + + // register things for legacy angular UI + const allSavingDisabled = graphSavePolicy === 'none'; + $scope.spymode = 'request'; + $scope.colors = colorChoices; + $scope.isColorDark = (color) => isColorDark(...hexToRgb(color)); + $scope.nodeClick = function (n, $event) { + + //Selection logic - shift key+click helps selects multiple nodes + // Without the shift key we deselect all prior selections (perhaps not + // a great idea for touch devices with no concept of shift key) + if (!$event.shiftKey) { + const prevSelection = n.isSelected; + $scope.workspace.selectNone(); + n.isSelected = prevSelection; + } - if ($scope.workspace.toggleNodeSelection(n)) { - $scope.selectSelected(n); - } else { - $scope.detail = null; - } - }; - function canWipeWorkspace(callback, text, options) { - if (!hasFieldsSelector(store.getState())) { - callback(); - return; - } - const confirmModalOptions = { - onConfirm: callback, - onCancel: (() => {}), - confirmButtonText: i18n.translate('xpack.graph.leaveWorkspace.confirmButtonLabel', { - defaultMessage: 'Leave anyway', - }), - title: i18n.translate('xpack.graph.leaveWorkspace.modalTitle', { - defaultMessage: 'Unsaved changes', - }), - ...options, + if ($scope.workspace.toggleNodeSelection(n)) { + $scope.selectSelected(n); + } else { + $scope.detail = null; + } }; - confirmModal(text || i18n.translate('xpack.graph.leaveWorkspace.confirmText', { - defaultMessage: 'If you leave now, you will lose unsaved changes.', - }), confirmModalOptions); - } - $scope.confirmWipeWorkspace = canWipeWorkspace; - $scope.clickEdge = function (edge) { - if (edge.inferred) { - $scope.setDetail ({ 'inferredEdge': edge }); - }else { - $scope.workspace.getAllIntersections($scope.handleMergeCandidatesCallback, [edge.topSrc, edge.topTarget]); - } - }; - - $scope.submit = function (searchTerm) { - $scope.workspaceInitialized = true; - const numHops = 2; - if (searchTerm.startsWith('{')) { - try { - const query = JSON.parse(searchTerm); - if (query.vertices) { - // Is a graph explore request - $scope.workspace.callElasticsearch(query); - }else { - // Is a regular query DSL query - $scope.workspace.search(query, $scope.liveResponseFields, numHops); - } + $scope.clickEdge = function (edge) { + if (edge.inferred) { + $scope.setDetail ({ 'inferredEdge': edge }); + }else { + $scope.workspace.getAllIntersections($scope.handleMergeCandidatesCallback, [edge.topSrc, edge.topTarget]); } - catch (err) { - handleError(err); + }; + + $scope.submit = function (searchTerm) { + $scope.workspaceInitialized = true; + const numHops = 2; + if (searchTerm.startsWith('{')) { + try { + const query = JSON.parse(searchTerm); + if (query.vertices) { + // Is a graph explore request + $scope.workspace.callElasticsearch(query); + }else { + // Is a regular query DSL query + $scope.workspace.search(query, $scope.liveResponseFields, numHops); + } + } + catch (err) { + handleError(err); + } + return; } - return; - } - $scope.workspace.simpleSearch(searchTerm, $scope.liveResponseFields, numHops); - }; + $scope.workspace.simpleSearch(searchTerm, $scope.liveResponseFields, numHops); + }; - $scope.selectSelected = function (node) { - $scope.detail = { - latestNodeSelection: node + $scope.selectSelected = function (node) { + $scope.detail = { + latestNodeSelection: node + }; + return $scope.selectedSelectedVertex = node; }; - return $scope.selectedSelectedVertex = node; - }; - - $scope.isSelectedSelected = function (node) { - return $scope.selectedSelectedVertex === node; - }; - - $scope.openUrlTemplate = function (template) { - const url = template.url; - const newUrl = url.replace(urlTemplateRegex, template.encoder.encode($scope.workspace)); - window.open(newUrl, '_blank'); - }; - - $scope.aceLoaded = (editor) => { - editor.$blockScrolling = Infinity; - }; - - $scope.setDetail = function (data) { - $scope.detail = data; - }; - - $scope.performMerge = function (parentId, childId) { - let found = true; - while (found) { - found = false; - for (const i in $scope.detail.mergeCandidates) { - const mc = $scope.detail.mergeCandidates[i]; - if ((mc.id1 === childId) || (mc.id2 === childId)) { - $scope.detail.mergeCandidates.splice(i, 1); - found = true; - break; - } + + $scope.isSelectedSelected = function (node) { + return $scope.selectedSelectedVertex === node; + }; + + $scope.openUrlTemplate = function (template) { + const url = template.url; + const newUrl = url.replace(urlTemplateRegex, template.encoder.encode($scope.workspace)); + window.open(newUrl, '_blank'); + }; + + $scope.aceLoaded = (editor) => { + editor.$blockScrolling = Infinity; + }; + + $scope.setDetail = function (data) { + $scope.detail = data; + }; + + function canWipeWorkspace(callback, text, options) { + if (!hasFieldsSelector(store.getState())) { + callback(); + return; } + const confirmModalOptions = { + onConfirm: callback, + onCancel: (() => {}), + confirmButtonText: i18n.translate('xpack.graph.leaveWorkspace.confirmButtonLabel', { + defaultMessage: 'Leave anyway', + }), + title: i18n.translate('xpack.graph.leaveWorkspace.modalTitle', { + defaultMessage: 'Unsaved changes', + }), + ...options, + }; + confirmModal(text || i18n.translate('xpack.graph.leaveWorkspace.confirmText', { + defaultMessage: 'If you leave now, you will lose unsaved changes.', + }), confirmModalOptions); } - $scope.workspace.mergeIds(parentId, childId); - $scope.detail = null; - }; - - - $scope.handleMergeCandidatesCallback = function (termIntersects) { - const mergeCandidates = []; - for (const i in termIntersects) { - const ti = termIntersects[i]; - mergeCandidates.push({ - 'id1': ti.id1, - 'id2': ti.id2, - 'term1': ti.term1, - 'term2': ti.term2, - 'v1': ti.v1, - 'v2': ti.v2, - 'overlap': ti.overlap - }); + $scope.confirmWipeWorkspace = canWipeWorkspace; + + $scope.performMerge = function (parentId, childId) { + let found = true; + while (found) { + found = false; + for (const i in $scope.detail.mergeCandidates) { + const mc = $scope.detail.mergeCandidates[i]; + if ((mc.id1 === childId) || (mc.id2 === childId)) { + $scope.detail.mergeCandidates.splice(i, 1); + found = true; + break; + } + } + } + $scope.workspace.mergeIds(parentId, childId); + $scope.detail = null; + }; - } - $scope.detail = { mergeCandidates }; - }; - - // ===== Menubar configuration ========= - $scope.topNavMenu = []; - $scope.topNavMenu.push({ - key: 'new', - label: i18n.translate('xpack.graph.topNavMenu.newWorkspaceLabel', { - defaultMessage: 'New', - }), - description: i18n.translate('xpack.graph.topNavMenu.newWorkspaceAriaLabel', { - defaultMessage: 'New Workspace', - }), - tooltip: i18n.translate('xpack.graph.topNavMenu.newWorkspaceTooltip', { - defaultMessage: 'Create a new workspace', - }), - run: function () { - canWipeWorkspace(function () { - kbnUrl.change('/workspace/', {}); - }); }, - testId: 'graphNewButton', - }); + $scope.handleMergeCandidatesCallback = function (termIntersects) { + const mergeCandidates = []; + for (const i in termIntersects) { + const ti = termIntersects[i]; + mergeCandidates.push({ + 'id1': ti.id1, + 'id2': ti.id2, + 'term1': ti.term1, + 'term2': ti.term2, + 'v1': ti.v1, + 'v2': ti.v2, + 'overlap': ti.overlap + }); - // if saving is disabled using uiCapabilities, we don't want to render the save - // button so it's consistent with all of the other applications - if (capabilities.get().graph.save) { - // allSavingDisabled is based on the xpack.graph.savePolicy, we'll maintain this functionality + } + $scope.detail = { mergeCandidates }; + }; + // ===== Menubar configuration ========= + $scope.topNavMenu = []; $scope.topNavMenu.push({ - key: 'save', - label: i18n.translate('xpack.graph.topNavMenu.saveWorkspace.enabledLabel', { - defaultMessage: 'Save', + key: 'new', + label: i18n.translate('xpack.graph.topNavMenu.newWorkspaceLabel', { + defaultMessage: 'New', }), - description: i18n.translate('xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel', { - defaultMessage: 'Save workspace', + description: i18n.translate('xpack.graph.topNavMenu.newWorkspaceAriaLabel', { + defaultMessage: 'New Workspace', }), - tooltip: () => { - if (allSavingDisabled) { - return i18n.translate('xpack.graph.topNavMenu.saveWorkspace.disabledTooltip', { - defaultMessage: 'No changes to saved workspaces are permitted by the current save policy', - }); - } else { - return i18n.translate('xpack.graph.topNavMenu.saveWorkspace.enabledTooltip', { - defaultMessage: 'Save this workspace', + tooltip: i18n.translate('xpack.graph.topNavMenu.newWorkspaceTooltip', { + defaultMessage: 'Create a new workspace', + }), + run: function () { + canWipeWorkspace(function () { + $scope.$evalAsync(() => { + if ($location.url() === '/workspace/') { + $route.reload(); + } else { + $location.url('/workspace/'); + } }); - } - }, - disableButton: function () { - return allSavingDisabled || !hasFieldsSelector(store.getState()); - }, - run: () => { - store.dispatch({ - type: 'x-pack/graph/SAVE_WORKSPACE', - payload: $route.current.locals.savedWorkspace, }); }, - testId: 'graphSaveButton', + testId: 'graphNewButton', }); - } - $scope.topNavMenu.push({ - key: 'inspect', - disableButton: function () { return $scope.workspace === null; }, - label: i18n.translate('xpack.graph.topNavMenu.inspectLabel', { - defaultMessage: 'Inspect', - }), - description: i18n.translate('xpack.graph.topNavMenu.inspectAriaLabel', { - defaultMessage: 'Inspect', - }), - run: () => { - $scope.$evalAsync(() => { - const curState = $scope.menus.showInspect; - $scope.closeMenus(); - $scope.menus.showInspect = !curState; - }); - }, - }); - $scope.topNavMenu.push({ - key: 'settings', - disableButton: function () { return datasourceSelector(store.getState()).type === 'none'; }, - label: i18n.translate('xpack.graph.topNavMenu.settingsLabel', { - defaultMessage: 'Settings', - }), - description: i18n.translate('xpack.graph.topNavMenu.settingsAriaLabel', { - defaultMessage: 'Settings', - }), - run: () => { - const settingsObservable = asAngularSyncedObservable(() => ({ - blacklistedNodes: $scope.workspace ? [...$scope.workspace.blacklistedNodes] : undefined, - unblacklistNode: $scope.workspace ? $scope.workspace.unblacklist : undefined, - canEditDrillDownUrls: chrome.getInjected('canEditDrillDownUrls') - }), $scope.$digest.bind($scope)); - npStart.core.overlays.openFlyout( - - - , { - size: 'm', - closeButtonAriaLabel: i18n.translate('xpack.graph.settings.closeLabel', { defaultMessage: 'Close' }), - 'data-test-subj': 'graphSettingsFlyout', - ownFocus: true, - className: 'gphSettingsFlyout', - maxWidth: 520, + // if saving is disabled using uiCapabilities, we don't want to render the save + // button so it's consistent with all of the other applications + if (capabilities.save) { + // allSavingDisabled is based on the xpack.graph.savePolicy, we'll maintain this functionality + + $scope.topNavMenu.push({ + key: 'save', + label: i18n.translate('xpack.graph.topNavMenu.saveWorkspace.enabledLabel', { + defaultMessage: 'Save', + }), + description: i18n.translate('xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel', { + defaultMessage: 'Save workspace', + }), + tooltip: () => { + if (allSavingDisabled) { + return i18n.translate('xpack.graph.topNavMenu.saveWorkspace.disabledTooltip', { + defaultMessage: 'No changes to saved workspaces are permitted by the current save policy', + }); + } else { + return i18n.translate('xpack.graph.topNavMenu.saveWorkspace.enabledTooltip', { + defaultMessage: 'Save this workspace', + }); + } + }, + disableButton: function () { + return allSavingDisabled || !hasFieldsSelector(store.getState()); + }, + run: () => { + store.dispatch({ + type: 'x-pack/graph/SAVE_WORKSPACE', + payload: $route.current.locals.savedWorkspace, + }); + }, + testId: 'graphSaveButton', + }); + } + $scope.topNavMenu.push({ + key: 'inspect', + disableButton: function () { return $scope.workspace === null; }, + label: i18n.translate('xpack.graph.topNavMenu.inspectLabel', { + defaultMessage: 'Inspect', + }), + description: i18n.translate('xpack.graph.topNavMenu.inspectAriaLabel', { + defaultMessage: 'Inspect', + }), + run: () => { + $scope.$evalAsync(() => { + const curState = $scope.menus.showInspect; + $scope.closeMenus(); + $scope.menus.showInspect = !curState; }); - }, - }); - - $scope.menus = { - showSettings: false, - }; - - $scope.closeMenus = () => { - _.forOwn($scope.menus, function (_, key) { - $scope.menus[key] = false; + }, }); - }; - // Deal with situation of request to open saved workspace - if ($route.current.locals.savedWorkspace.id) { - store.dispatch({ - type: 'x-pack/graph/LOAD_WORKSPACE', - payload: $route.current.locals.savedWorkspace, + $scope.topNavMenu.push({ + key: 'settings', + disableButton: function () { return datasourceSelector(store.getState()).type === 'none'; }, + label: i18n.translate('xpack.graph.topNavMenu.settingsLabel', { + defaultMessage: 'Settings', + }), + description: i18n.translate('xpack.graph.topNavMenu.settingsAriaLabel', { + defaultMessage: 'Settings', + }), + run: () => { + const settingsObservable = asAngularSyncedObservable(() => ({ + blacklistedNodes: $scope.workspace ? [...$scope.workspace.blacklistedNodes] : undefined, + unblacklistNode: $scope.workspace ? $scope.workspace.unblacklist : undefined, + canEditDrillDownUrls: canEditDrillDownUrls + }), $scope.$digest.bind($scope)); + coreStart.overlays.openFlyout( + + + , { + size: 'm', + closeButtonAriaLabel: i18n.translate('xpack.graph.settings.closeLabel', { defaultMessage: 'Close' }), + 'data-test-subj': 'graphSettingsFlyout', + ownFocus: true, + className: 'gphSettingsFlyout', + maxWidth: 520, + }); + }, }); + // Allow URLs to include a user-defined text query if ($route.current.params.query) { $scope.initialQuery = $route.current.params.query; @@ -595,8 +573,26 @@ app.controller('graphuiPlugin', function ( $scope.submit($route.current.params.query); }); } - } else { - $scope.noIndexPatterns = $route.current.locals.indexPatterns.length === 0; - } -}); + $scope.menus = { + showSettings: false, + }; + + $scope.closeMenus = () => { + _.forOwn($scope.menus, function (_, key) { + $scope.menus[key] = false; + }); + }; + + // Deal with situation of request to open saved workspace + if ($route.current.locals.savedWorkspace.id) { + store.dispatch({ + type: 'x-pack/graph/LOAD_WORKSPACE', + payload: $route.current.locals.savedWorkspace, + }); + } else { + $scope.noIndexPatterns = $route.current.locals.indexPatterns.length === 0; + } + }); +//End controller +} diff --git a/x-pack/legacy/plugins/graph/public/hacks/toggle_app_link_in_nav.js b/x-pack/legacy/plugins/graph/public/hacks/toggle_app_link_in_nav.js index 11b02354a97c5..5b1eb6181fd61 100644 --- a/x-pack/legacy/plugins/graph/public/hacks/toggle_app_link_in_nav.js +++ b/x-pack/legacy/plugins/graph/public/hacks/toggle_app_link_in_nav.js @@ -4,20 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { uiModules } from 'ui/modules'; import { npStart } from 'ui/new_platform'; import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; -uiModules.get('xpack/graph') - .run(() => { - const navLinkUpdates = {}; - navLinkUpdates.hidden = true; - const showAppLink = xpackInfo.get('features.graph.showAppLink', false); - navLinkUpdates.hidden = !showAppLink; - if (showAppLink) { - navLinkUpdates.disabled = !xpackInfo.get('features.graph.enableAppLink', false); - navLinkUpdates.tooltip = xpackInfo.get('features.graph.message'); - } +const navLinkUpdates = {}; +navLinkUpdates.hidden = true; +const showAppLink = xpackInfo.get('features.graph.showAppLink', false); +navLinkUpdates.hidden = !showAppLink; +if (showAppLink) { + navLinkUpdates.disabled = !xpackInfo.get('features.graph.enableAppLink', false); + navLinkUpdates.tooltip = xpackInfo.get('features.graph.message'); +} - npStart.core.chrome.navLinks.update('graph', navLinkUpdates); - }); +npStart.core.chrome.navLinks.update('graph', navLinkUpdates); diff --git a/x-pack/legacy/plugins/graph/public/index.ts b/x-pack/legacy/plugins/graph/public/index.ts new file mode 100644 index 0000000000000..0249ca74035d6 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/index.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// legacy imports currently necessary to power Graph +// for a cutover all of these have to be resolved +import 'uiExports/fieldFormats'; +import 'uiExports/savedObjectTypes'; +import 'uiExports/autocompleteProviders'; +import 'ui/autoload/all'; +import chrome from 'ui/chrome'; +import { IPrivate } from 'ui/private'; +// @ts-ignore +import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; +import { Storage } from 'ui/storage'; +// @ts-ignore +import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; + +import { npSetup, npStart } from 'ui/new_platform'; +import { start as data } from '../../../../../src/legacy/core_plugins/data/public/legacy'; +import { GraphPlugin } from './plugin'; + +// @ts-ignore +import { SavedWorkspacesProvider } from './angular/services/saved_workspaces'; +import { LegacyAngularInjectedDependencies } from './render_app'; + +/** + * Get dependencies relying on the global angular context. + * They also have to get resolved together with the legacy imports above + */ +async function getAngularInjectedDependencies(): Promise { + const injector = await chrome.dangerouslyGetActiveInjector(); + + const Private = injector.get('Private'); + + return { + $http: injector.get('$http'), + savedObjectRegistry: Private(SavedObjectRegistryProvider), + kbnBaseUrl: injector.get('kbnBaseUrl'), + savedGraphWorkspaces: Private(SavedWorkspacesProvider), + }; +} + +(async () => { + const instance = new GraphPlugin(); + instance.setup(npSetup.core, { + __LEGACY: { + xpackInfo, + Storage, + }, + }); + instance.start(npStart.core, { + data, + npData: npStart.plugins.data, + __LEGACY: { + angularDependencies: await getAngularInjectedDependencies(), + }, + }); +})(); diff --git a/x-pack/legacy/plugins/graph/public/plugin.ts b/x-pack/legacy/plugins/graph/public/plugin.ts new file mode 100644 index 0000000000000..d01f325dd8b70 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/plugin.ts @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// NP type imports +import { CoreSetup, CoreStart, Plugin, SavedObjectsClientContract } from 'src/core/public'; +import { DataStart } from 'src/legacy/core_plugins/data/public'; +import { Plugin as DataPlugin } from 'src/plugins/data/public'; +import { LegacyAngularInjectedDependencies } from './render_app'; + +export interface GraphPluginStartDependencies { + data: DataStart; + npData: ReturnType; +} + +export interface GraphPluginSetupDependencies { + __LEGACY: { + Storage: any; + xpackInfo: any; + }; +} + +export interface GraphPluginStartDependencies { + __LEGACY: { + angularDependencies: LegacyAngularInjectedDependencies; + }; +} + +export class GraphPlugin implements Plugin { + private dataStart: DataStart | null = null; + private npDataStart: ReturnType | null = null; + private savedObjectsClient: SavedObjectsClientContract | null = null; + private angularDependencies: LegacyAngularInjectedDependencies | null = null; + + setup(core: CoreSetup, { __LEGACY: { xpackInfo, Storage } }: GraphPluginSetupDependencies) { + core.application.register({ + id: 'graph', + title: 'Graph', + mount: async ({ core: contextCore }, params) => { + const { renderApp } = await import('./render_app'); + return renderApp({ + ...params, + npData: this.npDataStart!, + savedObjectsClient: this.savedObjectsClient!, + xpackInfo, + addBasePath: core.http.basePath.prepend, + getBasePath: core.http.basePath.get, + canEditDrillDownUrls: core.injectedMetadata.getInjectedVar( + 'canEditDrillDownUrls' + ) as boolean, + graphSavePolicy: core.injectedMetadata.getInjectedVar('graphSavePolicy') as string, + Storage, + capabilities: contextCore.application.capabilities.graph, + coreStart: contextCore, + chrome: contextCore.chrome, + config: contextCore.uiSettings, + toastNotifications: contextCore.notifications.toasts, + indexPatterns: this.dataStart!.indexPatterns.indexPatterns, + ...this.angularDependencies!, + }); + }, + }); + } + + start( + core: CoreStart, + { data, npData, __LEGACY: { angularDependencies } }: GraphPluginStartDependencies + ) { + // TODO is this really the right way? I though the app context would give us those + this.dataStart = data; + this.npDataStart = npData; + this.angularDependencies = angularDependencies; + this.savedObjectsClient = core.savedObjects.client; + } + + stop() {} +} diff --git a/x-pack/legacy/plugins/graph/public/render_app.ts b/x-pack/legacy/plugins/graph/public/render_app.ts new file mode 100644 index 0000000000000..8625e20ab9c52 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/render_app.ts @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiConfirmModal } from '@elastic/eui'; + +// inner angular imports +// these are necessary to bootstrap the local angular. +// They can stay even after NP cutover +import angular from 'angular'; +import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; +import 'ui/angular-bootstrap'; +import 'ace'; +import 'ui/kbn_top_nav'; +import { configureAppAngularModule } from 'ui/legacy_compat'; +// @ts-ignore +import { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; +// @ts-ignore +import { confirmModalFactory } from 'ui/modals/confirm_modal'; + +// type imports +import { DataStart } from 'src/legacy/core_plugins/data/public'; +import { + AppMountContext, + ChromeStart, + SavedObjectsClientContract, + ToastsStart, + UiSettingsClientContract, +} from 'kibana/public'; +// @ts-ignore +import { initGraphApp } from './app'; +import { Plugin as DataPlugin } from '../../../../../src/plugins/data/public'; + +/** + * These are dependencies of the Graph app besides the base dependencies + * provided by the application service. Some of those still rely on non-shimmed + * plugins in LP-world, but if they are migrated only the import path in the plugin + * itself changes + */ +export interface GraphDependencies extends LegacyAngularInjectedDependencies { + element: HTMLElement; + appBasePath: string; + capabilities: Record>; + coreStart: AppMountContext['core']; + chrome: ChromeStart; + config: UiSettingsClientContract; + toastNotifications: ToastsStart; + indexPatterns: DataStart['indexPatterns']['indexPatterns']; + npData: ReturnType; + savedObjectsClient: SavedObjectsClientContract; + xpackInfo: { get(path: string): unknown }; + addBasePath: (url: string) => string; + getBasePath: () => string; + Storage: any; + canEditDrillDownUrls: boolean; + graphSavePolicy: string; +} + +/** + * Dependencies of the Graph app which rely on the global angular instance. + * These dependencies have to be migrated to their NP counterparts. + */ +export interface LegacyAngularInjectedDependencies { + /** + * angular $http service + */ + $http: any; + /** + * Instance of SavedObjectRegistryProvider + */ + savedObjectRegistry: any; + kbnBaseUrl: any; + /** + * Instance of SavedWorkspacesProvider + */ + savedGraphWorkspaces: any; +} + +export const renderApp = ({ appBasePath, element, ...deps }: GraphDependencies) => { + const graphAngularModule = createLocalAngularModule(deps.coreStart); + configureAppAngularModule(graphAngularModule); + initGraphApp(graphAngularModule, deps); + const $injector = mountGraphApp(appBasePath, element); + return () => $injector.get('$rootScope').$destroy(); +}; + +const mainTemplate = (basePath: string) => `
+ +
+
+`; + +const moduleName = 'app/graph'; + +const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react', 'ui.bootstrap', 'ui.ace']; + +function mountGraphApp(appBasePath: string, element: HTMLElement) { + const mountpoint = document.createElement('div'); + mountpoint.setAttribute('style', 'height: 100%'); + // eslint-disable-next-line + mountpoint.innerHTML = mainTemplate(appBasePath); + // bootstrap angular into detached element and attach it later to + // make angular-within-angular possible + const $injector = angular.bootstrap(mountpoint, [moduleName]); + element.appendChild(mountpoint); + return $injector; +} + +function createLocalAngularModule(core: AppMountContext['core']) { + createLocalI18nModule(); + createLocalTopNavModule(); + createLocalConfirmModalModule(); + + const graphAngularModule = angular.module(moduleName, [ + ...thirdPartyAngularDependencies, + 'graphI18n', + 'graphTopNav', + 'graphConfirmModal', + ]); + return graphAngularModule; +} + +function createLocalConfirmModalModule() { + angular + .module('graphConfirmModal', ['react']) + .factory('confirmModal', confirmModalFactory) + .directive('confirmModal', reactDirective => reactDirective(EuiConfirmModal)); +} + +function createLocalTopNavModule() { + angular + .module('graphTopNav', ['react']) + .directive('kbnTopNav', createTopNavDirective) + .directive('kbnTopNavHelper', createTopNavHelper); +} + +function createLocalI18nModule() { + angular + .module('graphI18n', []) + .provider('i18n', I18nProvider) + .filter('i18n', i18nFilter) + .directive('i18nId', i18nDirective); +} diff --git a/x-pack/legacy/plugins/graph/public/services/url.ts b/x-pack/legacy/plugins/graph/public/services/url.ts index 91e14564bf3aa..b709683a457fb 100644 --- a/x-pack/legacy/plugins/graph/public/services/url.ts +++ b/x-pack/legacy/plugins/graph/public/services/url.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { Chrome } from 'ui/chrome'; +import { ChromeStart } from 'kibana/public'; import { GraphWorkspaceSavedObject } from '../types'; import { MetaDataState } from '../state_management'; @@ -21,23 +21,26 @@ export function getEditPath({ id }: GraphWorkspaceSavedObject) { return `/workspace/${id}`; } -export function getEditUrl(chrome: Chrome, workspace: GraphWorkspaceSavedObject) { - return chrome.addBasePath(`#${getEditPath(workspace)}`); +export function getEditUrl( + addBasePath: (url: string) => string, + workspace: GraphWorkspaceSavedObject +) { + return addBasePath(`#${getEditPath(workspace)}`); } export type SetBreadcrumbOptions = | { - chrome: Chrome; + chrome: ChromeStart; } | { - chrome: Chrome; + chrome: ChromeStart; metaData: MetaDataState; navigateTo: (path: string) => void; }; export function setBreadcrumbs(options: SetBreadcrumbOptions) { if ('metaData' in options) { - options.chrome.breadcrumbs.set([ + options.chrome.setBreadcrumbs([ { text: i18n.translate('xpack.graph.home.breadcrumb', { defaultMessage: 'Graph', @@ -53,7 +56,7 @@ export function setBreadcrumbs(options: SetBreadcrumbOptions) { }, ]); } else { - options.chrome.breadcrumbs.set([ + options.chrome.setBreadcrumbs([ { text: i18n.translate('xpack.graph.home.breadcrumb', { defaultMessage: 'Graph', diff --git a/x-pack/legacy/plugins/graph/public/state_management/meta_data.test.ts b/x-pack/legacy/plugins/graph/public/state_management/meta_data.test.ts index 8ac3746158f3f..25be050edfc13 100644 --- a/x-pack/legacy/plugins/graph/public/state_management/meta_data.test.ts +++ b/x-pack/legacy/plugins/graph/public/state_management/meta_data.test.ts @@ -6,7 +6,6 @@ import { createMockGraphStore, MockedGraphEnvironment } from './mocks'; import { syncBreadcrumbSaga, updateMetaData } from './meta_data'; -import { Chrome } from 'ui/chrome'; describe('breadcrumb sync saga', () => { let env: MockedGraphEnvironment; @@ -14,22 +13,15 @@ describe('breadcrumb sync saga', () => { beforeEach(() => { env = createMockGraphStore({ sagas: [syncBreadcrumbSaga], - mockedDepsOverwrites: { - chrome: ({ - breadcrumbs: { - set: jest.fn(), - }, - } as unknown) as Chrome, - }, }); }); it('syncs breadcrumb initially', () => { - expect(env.mockedDeps.chrome.breadcrumbs.set).toHaveBeenCalled(); + expect(env.mockedDeps.chrome.setBreadcrumbs).toHaveBeenCalled(); }); it('syncs breadcrumb with each change to meta data', () => { env.store.dispatch(updateMetaData({})); - expect(env.mockedDeps.chrome.breadcrumbs.set).toHaveBeenCalledTimes(2); + expect(env.mockedDeps.chrome.setBreadcrumbs).toHaveBeenCalledTimes(2); }); }); diff --git a/x-pack/legacy/plugins/graph/public/state_management/mocks.ts b/x-pack/legacy/plugins/graph/public/state_management/mocks.ts index 11cbf84e759ea..9672edef31d6f 100644 --- a/x-pack/legacy/plugins/graph/public/state_management/mocks.ts +++ b/x-pack/legacy/plugins/graph/public/state_management/mocks.ts @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Chrome } from 'ui/chrome'; import { IndexPattern } from 'src/legacy/core_plugins/data/public'; import { NotificationsStart, HttpStart } from 'kibana/public'; import createSagaMiddleware from 'redux-saga'; import { createStore, applyMiddleware, AnyAction } from 'redux'; +import { ChromeStart } from 'kibana/public'; import { GraphStoreDependencies, createRootReducer, GraphStore, GraphState } from './store'; import { Workspace, GraphWorkspaceSavedObject, IndexPatternSavedObject } from '../types'; @@ -52,10 +52,8 @@ export function createMockGraphStore({ basePath: 'basepath', changeUrl: jest.fn(), chrome: ({ - breadcrumbs: { - set: jest.fn(), - }, - } as unknown) as Chrome, + setBreadcrumbs: jest.fn(), + } as unknown) as ChromeStart, createWorkspace: jest.fn(), getWorkspace: jest.fn(() => workspaceMock), getSavedWorkspace: jest.fn(() => savedWorkspace), diff --git a/x-pack/legacy/plugins/graph/public/state_management/store.ts b/x-pack/legacy/plugins/graph/public/state_management/store.ts index 752483e65d8cc..bb01f20196f87 100644 --- a/x-pack/legacy/plugins/graph/public/state_management/store.ts +++ b/x-pack/legacy/plugins/graph/public/state_management/store.ts @@ -6,8 +6,8 @@ import createSagaMiddleware, { SagaMiddleware } from 'redux-saga'; import { combineReducers, createStore, Store, AnyAction, Dispatch, applyMiddleware } from 'redux'; +import { ChromeStart } from 'kibana/public'; import { CoreStart } from 'src/core/public'; -import { Chrome } from 'ui/chrome'; import { fieldsReducer, FieldsState, @@ -61,7 +61,7 @@ export interface GraphStoreDependencies { setLiveResponseFields: (fields: WorkspaceField[]) => void; setUrlTemplates: (templates: UrlTemplate[]) => void; setWorkspaceInitialized: () => void; - chrome: Chrome; + chrome: ChromeStart; } export function createRootReducer(basePath: string) { From 210e643b0c453481ebfd33d01d7ef573376e66ed Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 25 Oct 2019 09:51:10 +0200 Subject: [PATCH 135/191] Add outline parameter to gauge (#47827) --- .../components/options/gauge/ranges_panel.tsx | 33 +++++++++++++++++-- .../kbn_vislib_vis_types/public/gauge.d.ts | 1 + src/legacy/ui/public/vislib/_index.scss | 1 + .../vislib/visualizations/gauges/_index.scss | 1 + .../vislib/visualizations/gauges/_meter.scss | 3 ++ .../vislib/visualizations/gauges/meter.js | 3 ++ 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 src/legacy/ui/public/vislib/visualizations/gauges/_index.scss create mode 100644 src/legacy/ui/public/vislib/visualizations/gauges/_meter.scss diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx index c1fa3475470f1..1045543512c6b 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/gauge/ranges_panel.tsx @@ -17,14 +17,16 @@ * under the License. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { ColorSchemas } from 'ui/vislib/components/color/colormaps'; import { ColorRanges, ColorSchemaOptions, SwitchOption } from '../../common'; -import { SetColorSchemaOptionsValue } from '../../common/color_schema'; import { GaugeOptionsInternalProps } from '.'; +import { ColorSchemaVislibParams } from '../../../types'; +import { Gauge } from '../../../gauge'; function RangesPanel({ setGaugeValue, @@ -35,6 +37,22 @@ function RangesPanel({ uiState, vis, }: GaugeOptionsInternalProps) { + const setColorSchemaOptions = useCallback( + (paramName: T, value: ColorSchemaVislibParams[T]) => { + setGaugeValue(paramName, value as Gauge[T]); + // set outline if color schema is changed to greys + // if outline wasn't set explicitly yet + if ( + paramName === 'colorSchema' && + (value as string) === ColorSchemas.Greys && + typeof stateParams.gauge.outline === 'undefined' + ) { + setGaugeValue('outline', true); + } + }, + [setGaugeValue, stateParams] + ); + return ( @@ -84,7 +102,16 @@ function RangesPanel({ colorSchemas={vis.type.editorConfig.collections.colorSchemas} invertColors={stateParams.gauge.invertColors} uiState={uiState} - setValue={setGaugeValue as SetColorSchemaOptionsValue} + setValue={setColorSchemaOptions} + /> + + this.getColorBucket(Math.max(min, d.y))); const smallContainer = svg.node().getBBox().height < 70; From a3e16bf286eca7ae7195b2b94381025deb3164b5 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Fri, 25 Oct 2019 01:17:47 -0700 Subject: [PATCH 136/191] [ML] Fix code editor console error. (#49193) Fixes console errors caused by EuiCodeEditor by adding a missing theme attribute. --- .../components/analytics_list/expanded_row_json_pane.tsx | 1 + .../create_analytics_advanced_editor.tsx | 1 + .../jobs/jobs_list/components/ml_job_editor/ml_job_editor.js | 4 ++++ .../components/aggregation_list/popover_form.tsx | 2 +- .../components/group_by_list/popover_form.tsx | 2 +- .../components/step_define/step_define_form.tsx | 2 ++ .../__snapshots__/expanded_row_json_pane.test.tsx.snap | 1 + .../components/transform_list/expanded_row_json_pane.tsx | 1 + 8 files changed, 12 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row_json_pane.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row_json_pane.tsx index d0e23f96de049..ac7fdcb129531 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row_json_pane.tsx +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row_json_pane.tsx @@ -28,6 +28,7 @@ export const ExpandedRowJsonPane: FC = ({ json }) => { readOnly={true} mode="json" style={{ width: '100%' }} + theme="textmate" />   diff --git a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx index 9a5344cd1f984..daf21d57b0510 100644 --- a/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx +++ b/x-pack/legacy/plugins/ml/public/data_frame_analytics/pages/analytics_management/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx @@ -127,6 +127,7 @@ export const CreateAnalyticsAdvancedEditor: FC = ({ ac fontSize: '12px', maxLines: 20, }} + theme="textmate" aria-label={i18n.translate( 'xpack.ml.dataframe.analytics.create.advancedEditor.codeEditorAriaLabel', { diff --git a/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/ml_job_editor/ml_job_editor.js b/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/ml_job_editor/ml_job_editor.js index 22d45a70075e9..39cd21688dec5 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/ml_job_editor/ml_job_editor.js +++ b/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/ml_job_editor/ml_job_editor.js @@ -21,6 +21,7 @@ export function MLJobEditor({ mode = EDITOR_MODE.JSON, readOnly = false, syntaxChecking = true, + theme = 'textmate', onChange = () => {} }) { return ( @@ -32,6 +33,7 @@ export function MLJobEditor({ readOnly={readOnly} wrapEnabled={true} showPrintMargin={false} + theme={theme} editorProps={{ $blockScrolling: true }} setOptions={{ useWorker: syntaxChecking, @@ -48,5 +50,7 @@ MLJobEditor.propTypes = { width: PropTypes.string, mode: PropTypes.string, readOnly: PropTypes.bool, + syntaxChecking: PropTypes.bool, + theme: PropTypes.string, onChange: PropTypes.func, }; diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/aggregation_list/popover_form.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/aggregation_list/popover_form.tsx index e7f79b240d81a..65dd8a34330a5 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/aggregation_list/popover_form.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/aggregation_list/popover_form.tsx @@ -142,7 +142,7 @@ export const PopoverForm: React.SFC = ({ {isUnsupportedAgg && ( = ({ = React.memo(({ overrides = {}, onChange setOptions={{ fontSize: '12px', }} + theme="textmate" aria-label={i18n.translate( 'xpack.transform.stepDefineForm.advancedSourceEditorAriaLabel', { @@ -751,6 +752,7 @@ export const StepDefineForm: SFC = React.memo(({ overrides = {}, onChange setOptions={{ fontSize: '12px', }} + theme="textmate" aria-label={i18n.translate( 'xpack.transform.stepDefineForm.advancedEditorAriaLabel', { diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/expanded_row_json_pane.test.tsx.snap b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/expanded_row_json_pane.test.tsx.snap index f185579fd9e4c..0d4a80a94ee51 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/expanded_row_json_pane.test.tsx.snap +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/__snapshots__/expanded_row_json_pane.test.tsx.snap @@ -15,6 +15,7 @@ exports[`Transform: Transform List Expanded Row Minimal "width": "100%", } } + theme="textmate" value="{ \\"id\\": \\"fq_date_histogram_1m_1441\\", \\"source\\": { diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_json_pane.tsx b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_json_pane.tsx index d24fc19f216a3..416d93007daba 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_json_pane.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/expanded_row_json_pane.tsx @@ -28,6 +28,7 @@ export const ExpandedRowJsonPane: SFC = ({ json }) => { readOnly={true} mode="json" style={{ width: '100%' }} + theme="textmate" />   From 058168dee944a689afbe4d72de0c37b2b571d527 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Fri, 25 Oct 2019 01:38:44 -0700 Subject: [PATCH 137/191] [ML] Transform: Fix transform creation. (#49221) Fixes a regression where creating a transform in the wizard would result in an error toast even if the transform was created successfully. The response format of the create API was handled in the wrong way. --- .../components/step_create/step_create_form.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx index 47ce0f19f8f69..9623ff6abeced 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx @@ -89,13 +89,14 @@ export const StepCreateForm: SFC = React.memo( try { const resp = await api.createTransform(transformId, transformConfig); - - if (resp.errors !== undefined) { - if (Array.isArray(resp.errors) && resp.errors.length === 1) { + if (resp.errors !== undefined && Array.isArray(resp.errors)) { + if (resp.errors.length === 1) { throw resp.errors[0]; } - throw resp.errors; + if (resp.errors.length > 1) { + throw resp.errors; + } } toastNotifications.addSuccess( From a5b541e0b65f8d6b0a8589ff117cb8f948fa48a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Fri, 25 Oct 2019 10:43:03 +0200 Subject: [PATCH 138/191] [Logs UI] Fix analysis page auto refresh (#49170) This fixes the auto-refresh not being triggered by the date-picker when a prop change happened before the timeout expired. The upstream issue is tracked in elastic/eui#2483. It also introduces tracking of the last change's timestamp to enable in-place refreshes such as when the selected time range is absolute. fixes #49152 --- .../log_analysis/log_analysis_results.tsx | 4 +- .../logs/analysis/page_results_content.tsx | 47 ++++++++++++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx index d834b825e414a..8bd9f1074ac54 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx @@ -14,11 +14,13 @@ export const useLogAnalysisResults = ({ startTime, endTime, bucketDuration = 15 * 60 * 1000, + lastRequestTime, }: { sourceId: string; startTime: number; endTime: number; bucketDuration?: number; + lastRequestTime: number; }) => { const { isLoading: isLoadingLogEntryRate, logEntryRate, getLogEntryRate } = useLogEntryRate({ sourceId, @@ -31,7 +33,7 @@ export const useLogAnalysisResults = ({ useEffect(() => { getLogEntryRate(); - }, [sourceId, startTime, endTime, bucketDuration]); + }, [sourceId, startTime, endTime, bucketDuration, lastRequestTime]); return { isLoading, diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx index e846d4e9e4ac5..ffc48a0af9de9 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx @@ -57,9 +57,13 @@ export const AnalysisResultsContent = ({ setAutoRefresh, } = useLogAnalysisResultsUrlState(); - const [queryTimeRange, setQueryTimeRange] = useState( - stringToNumericTimeRange(selectedTimeRange) - ); + const [queryTimeRange, setQueryTimeRange] = useState<{ + value: TimeRange; + lastChangedTime: number; + }>(() => ({ + value: stringToNumericTimeRange(selectedTimeRange), + lastChangedTime: Date.now(), + })); const bucketDuration = useMemo(() => { // This function takes the current time range in ms, @@ -69,18 +73,21 @@ export const AnalysisResultsContent = ({ // 900000 (15 minutes) to it, so that we don't end up with // jaggy bucket boundaries between the ML buckets and our // aggregation buckets. - const msRange = moment(queryTimeRange.endTime).diff(moment(queryTimeRange.startTime)); + const msRange = moment(queryTimeRange.value.endTime).diff( + moment(queryTimeRange.value.startTime) + ); const bucketIntervalInMs = msRange / 100; const result = bucketSpan * Math.round(bucketIntervalInMs / bucketSpan); const roundedResult = parseInt(Number(result).toFixed(0), 10); return roundedResult < bucketSpan ? bucketSpan : roundedResult; - }, [queryTimeRange.startTime, queryTimeRange.endTime]); + }, [queryTimeRange.value.startTime, queryTimeRange.value.endTime]); const { isLoading, logEntryRate } = useLogAnalysisResults({ sourceId, - startTime: queryTimeRange.startTime, - endTime: queryTimeRange.endTime, + startTime: queryTimeRange.value.startTime, + endTime: queryTimeRange.value.endTime, bucketDuration, + lastRequestTime: queryTimeRange.lastChangedTime, }); const hasResults = useMemo(() => logEntryRate && logEntryRate.histogramBuckets.length > 0, [ logEntryRate, @@ -88,7 +95,10 @@ export const AnalysisResultsContent = ({ const handleQueryTimeRangeChange = useCallback( ({ start: startTime, end: endTime }: { start: string; end: string }) => { - setQueryTimeRange(stringToNumericTimeRange({ startTime, endTime })); + setQueryTimeRange({ + value: stringToNumericTimeRange({ startTime, endTime }), + lastChangedTime: Date.now(), + }); }, [setQueryTimeRange] ); @@ -141,6 +151,16 @@ export const AnalysisResultsContent = ({ fetchJobStatus(); }, JOB_STATUS_POLLING_INTERVAL); + useInterval( + () => { + handleQueryTimeRangeChange({ + start: selectedTimeRange.startTime, + end: selectedTimeRange.endTime, + }); + }, + autoRefresh.isPaused ? null : autoRefresh.interval + ); + return ( <> {isLoading && !logEntryRate ? ( @@ -171,9 +191,11 @@ export const AnalysisResultsContent = ({ ), startTime: ( - {moment(queryTimeRange.startTime).format(dateFormat)} + {moment(queryTimeRange.value.startTime).format(dateFormat)} + ), + endTime: ( + {moment(queryTimeRange.value.endTime).format(dateFormat)} ), - endTime: {moment(queryTimeRange.endTime).format(dateFormat)}, }} /> @@ -187,7 +209,6 @@ export const AnalysisResultsContent = ({ isPaused={autoRefresh.isPaused} refreshInterval={autoRefresh.interval} onRefreshChange={handleAutoRefreshChange} - onRefresh={handleQueryTimeRangeChange} /> @@ -200,7 +221,7 @@ export const AnalysisResultsContent = ({ isLoading={isLoading} results={logEntryRate} setTimeRange={handleChartTimeRangeChange} - timeRange={queryTimeRange} + timeRange={queryTimeRange.value} /> @@ -214,7 +235,7 @@ export const AnalysisResultsContent = ({ results={logEntryRate} setTimeRange={handleChartTimeRangeChange} setupStatus={setupStatus} - timeRange={queryTimeRange} + timeRange={queryTimeRange.value} jobId={jobIds['log-entry-rate']} /> From a4c2fa2d7ef69bdd4d00c407075c1a0395b37992 Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Fri, 25 Oct 2019 11:22:07 +0200 Subject: [PATCH 139/191] Consistent capitalization for savedObjectsClientMock (#49162) --- src/core/server/mocks.ts | 2 +- .../export/get_sorted_objects_for_export.test.ts | 4 ++-- .../export/inject_nested_depdendencies.test.ts | 4 ++-- .../saved_objects/import/import_saved_objects.test.ts | 4 ++-- .../saved_objects/import/resolve_import_errors.test.ts | 4 ++-- .../server/saved_objects/import/validate_references.test.ts | 6 +++--- .../saved_objects/service/saved_objects_client.mock.ts | 2 +- src/core/server/ui_settings/ui_settings_service.test.ts | 4 ++-- .../server/lib/export/collect_references_deep.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/bulk_create.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/bulk_get.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/bulk_update.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/create.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/delete.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/export.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/find.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/get.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/import.test.ts | 4 ++-- .../saved_objects/routes/resolve_import_errors.test.ts | 4 ++-- src/legacy/server/saved_objects/routes/update.test.ts | 4 ++-- .../ui_settings/integration_tests/ui_settings_mixin.test.ts | 4 ++-- x-pack/legacy/plugins/actions/server/actions_client.test.ts | 4 ++-- .../actions/server/builtin_action_types/email.test.ts | 4 ++-- .../actions/server/builtin_action_types/es_index.test.ts | 4 ++-- .../actions/server/builtin_action_types/pagerduty.test.ts | 4 ++-- .../actions/server/builtin_action_types/server_log.test.ts | 4 ++-- .../actions/server/builtin_action_types/slack.test.ts | 4 ++-- .../plugins/actions/server/create_execute_function.test.ts | 4 ++-- .../plugins/actions/server/lib/action_executor.test.ts | 4 ++-- .../plugins/actions/server/lib/task_runner_factory.test.ts | 4 ++-- x-pack/legacy/plugins/actions/server/routes/_mock_server.ts | 4 ++-- x-pack/legacy/plugins/alerting/server/alerts_client.test.ts | 4 ++-- .../plugins/alerting/server/lib/task_runner_factory.test.ts | 4 ++-- .../lib/encrypted_saved_objects_client_wrapper.test.ts | 4 ++-- x-pack/legacy/plugins/task_manager/task_manager.test.ts | 4 ++-- x-pack/legacy/plugins/task_manager/task_store.test.ts | 4 ++-- .../spaces_saved_objects_client.test.ts | 4 ++-- 37 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index fb703c6c35008..deb5984564db1 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -29,7 +29,7 @@ export { configServiceMock } from './config/config_service.mock'; export { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock'; export { httpServiceMock } from './http/http_service.mock'; export { loggingServiceMock } from './logging/logging_service.mock'; -export { SavedObjectsClientMock } from './saved_objects/service/saved_objects_client.mock'; +export { savedObjectsClientMock } from './saved_objects/service/saved_objects_client.mock'; export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; export function pluginInitializerContextConfigMock(config: T) { diff --git a/src/core/server/saved_objects/export/get_sorted_objects_for_export.test.ts b/src/core/server/saved_objects/export/get_sorted_objects_for_export.test.ts index 1a2a843ebb2b8..9a3449b65a941 100644 --- a/src/core/server/saved_objects/export/get_sorted_objects_for_export.test.ts +++ b/src/core/server/saved_objects/export/get_sorted_objects_for_export.test.ts @@ -18,7 +18,7 @@ */ import { getSortedObjectsForExport } from './get_sorted_objects_for_export'; -import { SavedObjectsClientMock } from '../service/saved_objects_client.mock'; +import { savedObjectsClientMock } from '../service/saved_objects_client.mock'; import { Readable } from 'stream'; import { createPromiseFromStreams, createConcatStream } from '../../../../legacy/utils/streams'; @@ -27,7 +27,7 @@ async function readStreamToCompletion(stream: Readable) { } describe('getSortedObjectsForExport()', () => { - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); afterEach(() => { savedObjectsClient.find.mockReset(); diff --git a/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts b/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts index 57feebbf67ccd..a571f62e3d1c1 100644 --- a/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts +++ b/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts @@ -18,7 +18,7 @@ */ import { SavedObject } from '../types'; -import { SavedObjectsClientMock } from '../../mocks'; +import { savedObjectsClientMock } from '../../mocks'; import { getObjectReferencesToFetch, fetchNestedDependencies } from './inject_nested_depdendencies'; describe('getObjectReferencesToFetch()', () => { @@ -109,7 +109,7 @@ describe('getObjectReferencesToFetch()', () => { }); describe('injectNestedDependencies', () => { - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); afterEach(() => { jest.resetAllMocks(); diff --git a/src/core/server/saved_objects/import/import_saved_objects.test.ts b/src/core/server/saved_objects/import/import_saved_objects.test.ts index df95fb75f0f4f..f0719cbf4c829 100644 --- a/src/core/server/saved_objects/import/import_saved_objects.test.ts +++ b/src/core/server/saved_objects/import/import_saved_objects.test.ts @@ -20,7 +20,7 @@ import { Readable } from 'stream'; import { SavedObject } from '../types'; import { importSavedObjects } from './import_saved_objects'; -import { SavedObjectsClientMock } from '../../mocks'; +import { savedObjectsClientMock } from '../../mocks'; const emptyResponse = { saved_objects: [], @@ -63,7 +63,7 @@ describe('importSavedObjects()', () => { references: [], }, ]; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { jest.resetAllMocks(); diff --git a/src/core/server/saved_objects/import/resolve_import_errors.test.ts b/src/core/server/saved_objects/import/resolve_import_errors.test.ts index 6aab8ef5adf9e..c522d76f1ff04 100644 --- a/src/core/server/saved_objects/import/resolve_import_errors.test.ts +++ b/src/core/server/saved_objects/import/resolve_import_errors.test.ts @@ -20,7 +20,7 @@ import { Readable } from 'stream'; import { SavedObject } from '../types'; import { resolveImportErrors } from './resolve_import_errors'; -import { SavedObjectsClientMock } from '../../mocks'; +import { savedObjectsClientMock } from '../../mocks'; describe('resolveImportErrors()', () => { const savedObjects: SavedObject[] = [ @@ -63,7 +63,7 @@ describe('resolveImportErrors()', () => { ], }, ]; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { jest.resetAllMocks(); diff --git a/src/core/server/saved_objects/import/validate_references.test.ts b/src/core/server/saved_objects/import/validate_references.test.ts index 269cd3055b047..6642cf149eda9 100644 --- a/src/core/server/saved_objects/import/validate_references.test.ts +++ b/src/core/server/saved_objects/import/validate_references.test.ts @@ -18,10 +18,10 @@ */ import { getNonExistingReferenceAsKeys, validateReferences } from './validate_references'; -import { SavedObjectsClientMock } from '../../mocks'; +import { savedObjectsClientMock } from '../../mocks'; describe('getNonExistingReferenceAsKeys()', () => { - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { jest.resetAllMocks(); @@ -222,7 +222,7 @@ describe('getNonExistingReferenceAsKeys()', () => { }); describe('validateReferences()', () => { - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { jest.resetAllMocks(); diff --git a/src/core/server/saved_objects/service/saved_objects_client.mock.ts b/src/core/server/saved_objects/service/saved_objects_client.mock.ts index 63c9a0ee35ae0..c6de9fa94291c 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.mock.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.mock.ts @@ -33,4 +33,4 @@ const create = () => update: jest.fn(), } as unknown) as jest.Mocked); -export const SavedObjectsClientMock = { create }; +export const savedObjectsClientMock = { create }; diff --git a/src/core/server/ui_settings/ui_settings_service.test.ts b/src/core/server/ui_settings/ui_settings_service.test.ts index 832d61bdb4137..e219d0c962344 100644 --- a/src/core/server/ui_settings/ui_settings_service.test.ts +++ b/src/core/server/ui_settings/ui_settings_service.test.ts @@ -23,7 +23,7 @@ import { MockUiSettingsClientConstructor } from './ui_settings_service.test.mock import { UiSettingsService } from './ui_settings_service'; import { httpServiceMock } from '../http/http_service.mock'; import { loggingServiceMock } from '../logging/logging_service.mock'; -import { SavedObjectsClientMock } from '../mocks'; +import { savedObjectsClientMock } from '../mocks'; import { mockCoreContext } from '../core_context.mock'; const overrides = { @@ -43,7 +43,7 @@ const coreContext = mockCoreContext.create(); coreContext.configService.atPath.mockReturnValue(new BehaviorSubject({ overrides })); const httpSetup = httpServiceMock.createSetupContract(); const setupDeps = { http: httpSetup }; -const savedObjectsClient = SavedObjectsClientMock.create(); +const savedObjectsClient = savedObjectsClientMock.create(); afterEach(() => { MockUiSettingsClientConstructor.mockClear(); diff --git a/src/legacy/core_plugins/kibana/server/lib/export/collect_references_deep.test.ts b/src/legacy/core_plugins/kibana/server/lib/export/collect_references_deep.test.ts index b5e112a489ce4..8aedc6f7332dc 100644 --- a/src/legacy/core_plugins/kibana/server/lib/export/collect_references_deep.test.ts +++ b/src/legacy/core_plugins/kibana/server/lib/export/collect_references_deep.test.ts @@ -19,7 +19,7 @@ import { SavedObject, SavedObjectAttributes } from 'src/core/server'; import { collectReferencesDeep } from './collect_references_deep'; -import { SavedObjectsClientMock } from '../../../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../../core/server/mocks'; const data: Array> = [ { @@ -102,7 +102,7 @@ const data: Array> = [ ]; test('collects dashboard and all dependencies', async () => { - const savedObjectClient = SavedObjectsClientMock.create(); + const savedObjectClient = savedObjectsClientMock.create(); savedObjectClient.bulkGet.mockImplementation(objects => { if (!objects) { throw new Error('Invalid test data'); diff --git a/src/legacy/server/saved_objects/routes/bulk_create.test.ts b/src/legacy/server/saved_objects/routes/bulk_create.test.ts index 1e041bb28f75f..b49554995aab6 100644 --- a/src/legacy/server/saved_objects/routes/bulk_create.test.ts +++ b/src/legacy/server/saved_objects/routes/bulk_create.test.ts @@ -22,11 +22,11 @@ import { createMockServer } from './_mock_server'; import { createBulkCreateRoute } from './bulk_create'; // Disable lint errors for imports from src/core/* until SavedObjects migration is complete // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { SavedObjectsClientMock } from '../../../../core/server/saved_objects/service/saved_objects_client.mock'; +import { savedObjectsClientMock } from '../../../../core/server/saved_objects/service/saved_objects_client.mock'; describe('POST /api/saved_objects/_bulk_create', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { savedObjectsClient.bulkCreate.mockImplementation(() => Promise.resolve('' as any)); diff --git a/src/legacy/server/saved_objects/routes/bulk_get.test.ts b/src/legacy/server/saved_objects/routes/bulk_get.test.ts index 546164be65c9f..e154649e2cf04 100644 --- a/src/legacy/server/saved_objects/routes/bulk_get.test.ts +++ b/src/legacy/server/saved_objects/routes/bulk_get.test.ts @@ -20,11 +20,11 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createBulkGetRoute } from './bulk_get'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('POST /api/saved_objects/_bulk_get', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { savedObjectsClient.bulkGet.mockImplementation(() => diff --git a/src/legacy/server/saved_objects/routes/bulk_update.test.ts b/src/legacy/server/saved_objects/routes/bulk_update.test.ts index ee74ddfc535d2..dc21ab08035ce 100644 --- a/src/legacy/server/saved_objects/routes/bulk_update.test.ts +++ b/src/legacy/server/saved_objects/routes/bulk_update.test.ts @@ -20,11 +20,11 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createBulkUpdateRoute } from './bulk_update'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('PUT /api/saved_objects/_bulk_update', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { server = createMockServer(); diff --git a/src/legacy/server/saved_objects/routes/create.test.ts b/src/legacy/server/saved_objects/routes/create.test.ts index 85096228c3175..4f096a9ee5c93 100644 --- a/src/legacy/server/saved_objects/routes/create.test.ts +++ b/src/legacy/server/saved_objects/routes/create.test.ts @@ -20,7 +20,7 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createCreateRoute } from './create'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('POST /api/saved_objects/{type}', () => { let server: Hapi.Server; @@ -32,7 +32,7 @@ describe('POST /api/saved_objects/{type}', () => { references: [], attributes: {}, }; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { savedObjectsClient.create.mockImplementation(() => Promise.resolve(clientResponse)); diff --git a/src/legacy/server/saved_objects/routes/delete.test.ts b/src/legacy/server/saved_objects/routes/delete.test.ts index 9e2adcf9d3b91..f3e5e83771471 100644 --- a/src/legacy/server/saved_objects/routes/delete.test.ts +++ b/src/legacy/server/saved_objects/routes/delete.test.ts @@ -20,11 +20,11 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createDeleteRoute } from './delete'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('DELETE /api/saved_objects/{type}/{id}', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { savedObjectsClient.delete.mockImplementation(() => Promise.resolve('{}')); diff --git a/src/legacy/server/saved_objects/routes/export.test.ts b/src/legacy/server/saved_objects/routes/export.test.ts index 2670535ab995e..93ca3a419e6df 100644 --- a/src/legacy/server/saved_objects/routes/export.test.ts +++ b/src/legacy/server/saved_objects/routes/export.test.ts @@ -28,14 +28,14 @@ import * as exportMock from '../../../../core/server/saved_objects/export'; import { createMockServer } from './_mock_server'; import { createExportRoute } from './export'; import { createListStream } from '../../../utils/streams'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; const getSortedObjectsForExport = exportMock.getSortedObjectsForExport as jest.Mock; describe('POST /api/saved_objects/_export', () => { let server: Hapi.Server; const savedObjectsClient = { - ...SavedObjectsClientMock.create(), + ...savedObjectsClientMock.create(), errors: {} as any, }; diff --git a/src/legacy/server/saved_objects/routes/find.test.ts b/src/legacy/server/saved_objects/routes/find.test.ts index 89cd0dd28d035..4bf5f57fec199 100644 --- a/src/legacy/server/saved_objects/routes/find.test.ts +++ b/src/legacy/server/saved_objects/routes/find.test.ts @@ -20,11 +20,11 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createFindRoute } from './find'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('GET /api/saved_objects/_find', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); const clientResponse = { total: 0, diff --git a/src/legacy/server/saved_objects/routes/get.test.ts b/src/legacy/server/saved_objects/routes/get.test.ts index 2f7eaea1bc770..7ede2a8b4d7b4 100644 --- a/src/legacy/server/saved_objects/routes/get.test.ts +++ b/src/legacy/server/saved_objects/routes/get.test.ts @@ -20,11 +20,11 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createGetRoute } from './get'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('GET /api/saved_objects/{type}/{id}', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { savedObjectsClient.get.mockImplementation(() => diff --git a/src/legacy/server/saved_objects/routes/import.test.ts b/src/legacy/server/saved_objects/routes/import.test.ts index 1a0684a35ec79..2b8d9d7523507 100644 --- a/src/legacy/server/saved_objects/routes/import.test.ts +++ b/src/legacy/server/saved_objects/routes/import.test.ts @@ -20,11 +20,11 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createImportRoute } from './import'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('POST /api/saved_objects/_import', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); const emptyResponse = { saved_objects: [], total: 0, diff --git a/src/legacy/server/saved_objects/routes/resolve_import_errors.test.ts b/src/legacy/server/saved_objects/routes/resolve_import_errors.test.ts index 7988165207e63..44fa46bccfce5 100644 --- a/src/legacy/server/saved_objects/routes/resolve_import_errors.test.ts +++ b/src/legacy/server/saved_objects/routes/resolve_import_errors.test.ts @@ -20,11 +20,11 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createResolveImportErrorsRoute } from './resolve_import_errors'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('POST /api/saved_objects/_resolve_import_errors', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { server = createMockServer(); diff --git a/src/legacy/server/saved_objects/routes/update.test.ts b/src/legacy/server/saved_objects/routes/update.test.ts index 69a6fe3030009..aaeaff489d30a 100644 --- a/src/legacy/server/saved_objects/routes/update.test.ts +++ b/src/legacy/server/saved_objects/routes/update.test.ts @@ -20,11 +20,11 @@ import Hapi from 'hapi'; import { createMockServer } from './_mock_server'; import { createUpdateRoute } from './update'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; describe('PUT /api/saved_objects/{type}/{id?}', () => { let server: Hapi.Server; - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); beforeEach(() => { const clientResponse = { diff --git a/src/legacy/ui/ui_settings/integration_tests/ui_settings_mixin.test.ts b/src/legacy/ui/ui_settings/integration_tests/ui_settings_mixin.test.ts index 9f553b37935d7..3da7f83be4894 100644 --- a/src/legacy/ui/ui_settings/integration_tests/ui_settings_mixin.test.ts +++ b/src/legacy/ui/ui_settings/integration_tests/ui_settings_mixin.test.ts @@ -20,7 +20,7 @@ import sinon from 'sinon'; import expect from '@kbn/expect'; -import { SavedObjectsClientMock } from '../../../../core/server/mocks'; +import { savedObjectsClientMock } from '../../../../core/server/mocks'; import * as uiSettingsServiceFactoryNS from '../ui_settings_service_factory'; import * as getUiSettingsServiceForRequestNS from '../ui_settings_service_for_request'; // @ts-ignore @@ -129,7 +129,7 @@ describe('uiSettingsMixin()', () => { sinon.assert.notCalled(uiSettingsServiceFactoryStub); - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); decorations.server.uiSettingsServiceFactory({ savedObjectsClient, }); diff --git a/x-pack/legacy/plugins/actions/server/actions_client.test.ts b/x-pack/legacy/plugins/actions/server/actions_client.test.ts index b582d9f2a1b0d..b4940b23ba61c 100644 --- a/x-pack/legacy/plugins/actions/server/actions_client.test.ts +++ b/x-pack/legacy/plugins/actions/server/actions_client.test.ts @@ -11,9 +11,9 @@ import { ActionsClient } from './actions_client'; import { ExecutorType } from './types'; import { ActionExecutor, TaskRunnerFactory } from './lib'; import { taskManagerMock } from '../../task_manager/task_manager.mock'; -import { SavedObjectsClientMock } from '../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; -const savedObjectsClient = SavedObjectsClientMock.create(); +const savedObjectsClient = savedObjectsClientMock.create(); const mockTaskManager = taskManagerMock.create(); diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts index 4e2ef29dd740f..8e6b1f19b172c 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts +++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts @@ -10,7 +10,7 @@ jest.mock('./lib/send_email', () => ({ import { ActionType, ActionTypeExecutorOptions } from '../types'; import { validateConfig, validateSecrets, validateParams } from '../lib'; -import { SavedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; import { createActionTypeRegistry } from './index.test'; import { sendEmail } from './lib/send_email'; import { ActionParamsType, ActionTypeConfigType, ActionTypeSecretsType } from './email'; @@ -23,7 +23,7 @@ const NO_OP_FN = () => {}; const services = { log: NO_OP_FN, callCluster: async (path: string, opts: any) => {}, - savedObjectsClient: SavedObjectsClientMock.create(), + savedObjectsClient: savedObjectsClientMock.create(), }; let actionType: ActionType; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts index 57a107968ba70..35d81ba74fa72 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts +++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts @@ -10,7 +10,7 @@ jest.mock('./lib/send_email', () => ({ import { ActionType, ActionTypeExecutorOptions } from '../types'; import { validateConfig, validateParams } from '../lib'; -import { SavedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; import { createActionTypeRegistry } from './index.test'; import { ActionParamsType, ActionTypeConfigType } from './es_index'; @@ -20,7 +20,7 @@ const NO_OP_FN = () => {}; const services = { log: NO_OP_FN, callCluster: jest.fn(), - savedObjectsClient: SavedObjectsClientMock.create(), + savedObjectsClient: savedObjectsClientMock.create(), }; let actionType: ActionType; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts index a9f3ea757e33b..1d453d2bd2340 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts +++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts @@ -10,7 +10,7 @@ jest.mock('./lib/post_pagerduty', () => ({ import { ActionType, Services, ActionTypeExecutorOptions } from '../types'; import { validateConfig, validateSecrets, validateParams } from '../lib'; -import { SavedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; import { postPagerduty } from './lib/post_pagerduty'; import { createActionTypeRegistry } from './index.test'; @@ -20,7 +20,7 @@ const ACTION_TYPE_ID = '.pagerduty'; const services: Services = { callCluster: async (path: string, opts: any) => {}, - savedObjectsClient: SavedObjectsClientMock.create(), + savedObjectsClient: savedObjectsClientMock.create(), }; let actionType: ActionType; diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts index e3feec6d1bc67..76e639c994834 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts +++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts @@ -7,7 +7,7 @@ import { ActionType } from '../types'; import { validateParams } from '../lib'; import { Logger } from '../../../../../../src/core/server'; -import { SavedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; import { createActionTypeRegistry } from './index.test'; const ACTION_TYPE_ID = '.server-log'; @@ -92,7 +92,7 @@ describe('execute()', () => { actionId, services: { callCluster: async (path: string, opts: any) => {}, - savedObjectsClient: SavedObjectsClientMock.create(), + savedObjectsClient: savedObjectsClientMock.create(), }, params: { message: 'message text here', level: 'info' }, config: {}, diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts index 681f508b1d214..f6bd2d2b254df 100644 --- a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts +++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts @@ -6,7 +6,7 @@ import { ActionType, Services, ActionTypeExecutorOptions } from '../types'; import { ActionTypeRegistry } from '../action_type_registry'; -import { SavedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; import { ActionExecutor, validateParams, validateSecrets, TaskRunnerFactory } from '../lib'; import { getActionType } from './slack'; import { taskManagerMock } from '../../../task_manager/task_manager.mock'; @@ -15,7 +15,7 @@ const ACTION_TYPE_ID = '.slack'; const services: Services = { callCluster: async (path: string, opts: any) => {}, - savedObjectsClient: SavedObjectsClientMock.create(), + savedObjectsClient: savedObjectsClientMock.create(), }; let actionTypeRegistry: ActionTypeRegistry; diff --git a/x-pack/legacy/plugins/actions/server/create_execute_function.test.ts b/x-pack/legacy/plugins/actions/server/create_execute_function.test.ts index e928eb491c1b5..c6817b3bc12f3 100644 --- a/x-pack/legacy/plugins/actions/server/create_execute_function.test.ts +++ b/x-pack/legacy/plugins/actions/server/create_execute_function.test.ts @@ -6,10 +6,10 @@ import { taskManagerMock } from '../../task_manager/task_manager.mock'; import { createExecuteFunction } from './create_execute_function'; -import { SavedObjectsClientMock } from '../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../src/core/server/mocks'; const mockTaskManager = taskManagerMock.create(); -const savedObjectsClient = SavedObjectsClientMock.create(); +const savedObjectsClient = savedObjectsClientMock.create(); const getBasePath = jest.fn(); beforeEach(() => jest.resetAllMocks()); diff --git a/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts b/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts index 661a08df3dc30..c724717bef9eb 100644 --- a/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/legacy/plugins/actions/server/lib/action_executor.test.ts @@ -10,12 +10,12 @@ import { ActionExecutor } from './action_executor'; import { actionTypeRegistryMock } from '../action_type_registry.mock'; import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/plugin.mock'; import { - SavedObjectsClientMock, + savedObjectsClientMock, loggingServiceMock, } from '../../../../../../src/core/server/mocks'; const actionExecutor = new ActionExecutor(); -const savedObjectsClient = SavedObjectsClientMock.create(); +const savedObjectsClient = savedObjectsClientMock.create(); function getServices() { return { diff --git a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts b/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts index cc18c7b169429..6411bc7462c9f 100644 --- a/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts +++ b/x-pack/legacy/plugins/actions/server/lib/task_runner_factory.test.ts @@ -13,7 +13,7 @@ import { actionTypeRegistryMock } from '../action_type_registry.mock'; import { actionExecutorMock } from './action_executor.mock'; import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/plugin.mock'; import { - SavedObjectsClientMock, + savedObjectsClientMock, loggingServiceMock, } from '../../../../../../src/core/server/mocks'; @@ -54,7 +54,7 @@ afterAll(() => fakeTimer.restore()); const services = { log: jest.fn(), callCluster: jest.fn(), - savedObjectsClient: SavedObjectsClientMock.create(), + savedObjectsClient: savedObjectsClientMock.create(), }; const actionExecutorInitializerParams = { logger: loggingServiceMock.create().get(), diff --git a/x-pack/legacy/plugins/actions/server/routes/_mock_server.ts b/x-pack/legacy/plugins/actions/server/routes/_mock_server.ts index 340d341a5ef14..7f2341c1aa010 100644 --- a/x-pack/legacy/plugins/actions/server/routes/_mock_server.ts +++ b/x-pack/legacy/plugins/actions/server/routes/_mock_server.ts @@ -5,7 +5,7 @@ */ import Hapi from 'hapi'; -import { SavedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; import { actionsClientMock } from '../actions_client.mock'; import { actionTypeRegistryMock } from '../action_type_registry.mock'; import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/plugin.mock'; @@ -21,7 +21,7 @@ export function createMockServer(config: Record = defaultConfig) { const actionsClient = actionsClientMock.create(); const actionTypeRegistry = actionTypeRegistryMock.create(); - const savedObjectsClient = SavedObjectsClientMock.create(); + const savedObjectsClient = savedObjectsClientMock.create(); const encryptedSavedObjects = encryptedSavedObjectsMock.create(); server.config = () => { diff --git a/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts b/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts index 574aed3fe9329..093f5f7484004 100644 --- a/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts +++ b/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts @@ -6,13 +6,13 @@ import { schema } from '@kbn/config-schema'; import { AlertsClient } from './alerts_client'; -import { SavedObjectsClientMock, loggingServiceMock } from '../../../../../src/core/server/mocks'; +import { savedObjectsClientMock, loggingServiceMock } from '../../../../../src/core/server/mocks'; import { taskManagerMock } from '../../task_manager/task_manager.mock'; import { alertTypeRegistryMock } from './alert_type_registry.mock'; const taskManager = taskManagerMock.create(); const alertTypeRegistry = alertTypeRegistryMock.create(); -const savedObjectsClient = SavedObjectsClientMock.create(); +const savedObjectsClient = savedObjectsClientMock.create(); const alertsClientParams = { taskManager, diff --git a/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.test.ts b/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.test.ts index ccc91ae2a9034..23591692bca1f 100644 --- a/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.test.ts +++ b/x-pack/legacy/plugins/alerting/server/lib/task_runner_factory.test.ts @@ -11,7 +11,7 @@ import { ConcreteTaskInstance } from '../../../task_manager'; import { TaskRunnerContext, TaskRunnerFactory } from './task_runner_factory'; import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/plugin.mock'; import { - SavedObjectsClientMock, + savedObjectsClientMock, loggingServiceMock, } from '../../../../../../src/core/server/mocks'; @@ -51,7 +51,7 @@ beforeAll(() => { afterAll(() => fakeTimer.restore()); -const savedObjectsClient = SavedObjectsClientMock.create(); +const savedObjectsClient = savedObjectsClientMock.create(); const encryptedSavedObjectsPlugin = encryptedSavedObjectsMock.create(); const services = { log: jest.fn(), diff --git a/x-pack/legacy/plugins/encrypted_saved_objects/server/lib/encrypted_saved_objects_client_wrapper.test.ts b/x-pack/legacy/plugins/encrypted_saved_objects/server/lib/encrypted_saved_objects_client_wrapper.test.ts index 703ba64b95a7c..a9f41513fbf14 100644 --- a/x-pack/legacy/plugins/encrypted_saved_objects/server/lib/encrypted_saved_objects_client_wrapper.test.ts +++ b/x-pack/legacy/plugins/encrypted_saved_objects/server/lib/encrypted_saved_objects_client_wrapper.test.ts @@ -9,14 +9,14 @@ jest.mock('uuid', () => ({ v4: jest.fn().mockReturnValue('uuid-v4-id') })); import { EncryptedSavedObjectsClientWrapper } from './encrypted_saved_objects_client_wrapper'; import { EncryptedSavedObjectsService } from './encrypted_saved_objects_service'; import { createEncryptedSavedObjectsServiceMock } from './encrypted_saved_objects_service.mock'; -import { SavedObjectsClientMock } from 'src/core/server/saved_objects/service/saved_objects_client.mock'; +import { savedObjectsClientMock } from 'src/core/server/saved_objects/service/saved_objects_client.mock'; import { SavedObjectsClientContract } from 'src/core/server'; let wrapper: EncryptedSavedObjectsClientWrapper; let mockBaseClient: jest.Mocked; let encryptedSavedObjectsServiceMock: jest.Mocked; beforeEach(() => { - mockBaseClient = SavedObjectsClientMock.create(); + mockBaseClient = savedObjectsClientMock.create(); encryptedSavedObjectsServiceMock = createEncryptedSavedObjectsServiceMock([ { type: 'known-type', diff --git a/x-pack/legacy/plugins/task_manager/task_manager.test.ts b/x-pack/legacy/plugins/task_manager/task_manager.test.ts index 2bcfdb2f4d4e3..8592ff31d700f 100644 --- a/x-pack/legacy/plugins/task_manager/task_manager.test.ts +++ b/x-pack/legacy/plugins/task_manager/task_manager.test.ts @@ -7,11 +7,11 @@ import _ from 'lodash'; import sinon from 'sinon'; import { TaskManager, claimAvailableTasks } from './task_manager'; -import { SavedObjectsClientMock } from 'src/core/server/mocks'; +import { savedObjectsClientMock } from 'src/core/server/mocks'; import { SavedObjectsSerializer, SavedObjectsSchema } from 'src/core/server'; import { mockLogger } from './test_utils'; -const savedObjectsClient = SavedObjectsClientMock.create(); +const savedObjectsClient = savedObjectsClientMock.create(); const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); describe('TaskManager', () => { diff --git a/x-pack/legacy/plugins/task_manager/task_store.test.ts b/x-pack/legacy/plugins/task_manager/task_store.test.ts index 65b49820d6e6c..9779dc5efd28b 100644 --- a/x-pack/legacy/plugins/task_manager/task_store.test.ts +++ b/x-pack/legacy/plugins/task_manager/task_store.test.ts @@ -10,7 +10,7 @@ import uuid from 'uuid'; import { TaskDictionary, TaskDefinition, TaskInstance, TaskStatus } from './task'; import { FetchOpts, StoreOpts, OwnershipClaimingOpts, TaskStore } from './task_store'; import { mockLogger } from './test_utils'; -import { SavedObjectsClientMock } from 'src/core/server/mocks'; +import { savedObjectsClientMock } from 'src/core/server/mocks'; import { SavedObjectsSerializer, SavedObjectsSchema, SavedObjectAttributes } from 'src/core/server'; const taskDefinitions: TaskDictionary = { @@ -31,7 +31,7 @@ const taskDefinitions: TaskDictionary = { }, }; -const savedObjectsClient = SavedObjectsClientMock.create(); +const savedObjectsClient = savedObjectsClientMock.create(); const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); beforeEach(() => jest.resetAllMocks()); diff --git a/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.test.ts b/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.test.ts index 2e19f85875616..c2bc534f742a8 100644 --- a/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.test.ts +++ b/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.test.ts @@ -7,13 +7,13 @@ import { DEFAULT_SPACE_ID } from '../../../common/constants'; import { SpacesSavedObjectsClient } from './spaces_saved_objects_client'; import { spacesServiceMock } from '../../spaces_service/spaces_service.mock'; -import { SavedObjectsClientMock } from '../../../../../../src/core/server/mocks'; +import { savedObjectsClientMock } from '../../../../../../src/core/server/mocks'; const types = ['foo', 'bar', 'space']; const createMockRequest = () => ({}); -const createMockClient = () => SavedObjectsClientMock.create(); +const createMockClient = () => savedObjectsClientMock.create(); const createSpacesService = async (spaceId: string) => { return spacesServiceMock.createSetupContract(spaceId); From 5accc3c315994ef8f5256f1f8e86d0bd066bb58d Mon Sep 17 00:00:00 2001 From: Chris Mark Date: Fri, 25 Oct 2019 13:32:14 +0300 Subject: [PATCH 140/191] Add Consul Metricbeat module tutorial to Kibana home (#48497) --- .../consul_metrics/screenshot.png | Bin 0 -> 541112 bytes .../home/tutorial_resources/logos/consul.svg | 1 + .../server/tutorials/consul_metrics/index.js | 63 ++++++++++++++++++ .../kibana/server/tutorials/register.js | 2 + 4 files changed, 66 insertions(+) create mode 100644 src/legacy/core_plugins/kibana/public/home/tutorial_resources/consul_metrics/screenshot.png create mode 100644 src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg create mode 100644 src/legacy/core_plugins/kibana/server/tutorials/consul_metrics/index.js diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/consul_metrics/screenshot.png b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/consul_metrics/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..90aaa7477e8eb24d3bc3a1d3f0fefb164596a56f GIT binary patch literal 541112 zcmbTebySmY{Qs|Df{3(;fKIv_X@nsm(w#~-(gHF>L`plM%E3g!ck~+CWqyb@F~yfeIlZ;J7fN#rU}TlVZP`0TRwiwwt!&fS^2zpv=}O$Rj>6m|Ji)gM|#jn9St`F>x&BiSYkf#Al~wbt(y zUNdDT7XRmq3rf`dFG#Gme3JV2AfZbXR)P*-N%sw&mW=at5DfpRI=qxfCie_Ed*j)y zzf1=IFF4rc5>$Y1+L?yq^nd+^xa2avaH9LyH>;zu`$;rXx7ekv5b^oa!!I%op6L)v z!+)*?8EVcw|NRNu65=c7?i=j#O9y0c^JaeV_a=7>i*uAJohP^I{eR3QL0>2y6zUY; zN|ACsNV%1gEK|0JF|BL%|Ko3ltJf(?qw%oa3btGKSScShj z@nO2;cf-LX8CR-ZTu;f1n8V{oR0d&tlJ(F;x z#&ku_>@>P+RCU+3Dv2G7#hS}Ktq~dpUU?frqN|U+FsIi0{QoxD-_$JU(RW(I9?uu# zQ_Viy3P9*Tp_V#P9rpi3vhJ0r3tEosgV^xuv+3Nu39c33KlL@2nfllC|8x8~iNC>*0GMT%w8Wc&wa*%u%ZjC`Q(h8X8SBB1tLqkJ}}qPS(zDQ!q{7 z$&-&^kBo2HamOqq1}N0`3_n=$Rio0?$?)KML&OLBt$%SVJA%k;jiFNHUz6W9&qyJM zEU}WSH)&O(7m~LI_pD<-??FsOsPk39QWO^(r{y=ZZ#Oo-YSFqno;XPxXZpDibed5G ziIJ%!KeINr@IoOE?+{BM2qc~XE;K|g=EP;busdv<(4^f zrk|7lP{5svYm2uEY&Jf)BP*-@qp~qx`QucXF~RYrOg(xoFi9pg0bK2YVZ<`j{=+&e zKFVrpjw)sjws>E$koo%hwhCUr)#&GnOcUE{;%aIr<}wo!aMR^&#`Swx`>lwY4Ib

8uwLFC~a3<f7@2Mzgx?zm>Cie{L!=INgvOm(xiR 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⪼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

p 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�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 Z&$SSpFWZP3I|l!W-;ueUD|-LI{{hu?(PjVu literal 0 HcmV?d00001 diff --git a/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg new file mode 100644 index 0000000000000..28bbadd24c8a6 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/home/tutorial_resources/logos/consul.svg @@ -0,0 +1 @@ +Asset 1 \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/server/tutorials/consul_metrics/index.js b/src/legacy/core_plugins/kibana/server/tutorials/consul_metrics/index.js new file mode 100644 index 0000000000000..8823fe5ee5067 --- /dev/null +++ b/src/legacy/core_plugins/kibana/server/tutorials/consul_metrics/index.js @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; +import { TUTORIAL_CATEGORY } from '../../../common/tutorials/tutorial_category'; +import { onPremInstructions, cloudInstructions, onPremCloudInstructions } from '../../../common/tutorials/metricbeat_instructions'; + +export function consulMetricsSpecProvider(server, context) { + const moduleName = 'consul'; + return { + id: 'consulMetrics', + name: i18n.translate('kbn.server.tutorials.consulMetrics.nameTitle', { + defaultMessage: 'Consul metrics', + }), + category: TUTORIAL_CATEGORY.METRICS, + shortDescription: i18n.translate('kbn.server.tutorials.consulMetrics.shortDescription', { + defaultMessage: 'Fetch monitoring metrics from the Consul server.', + }), + longDescription: i18n.translate('kbn.server.tutorials.consulMetrics.longDescription', { + defaultMessage: 'The `consul` Metricbeat module fetches monitoring metrics from Consul. \ +[Learn more]({learnMoreLink}).', + values: { + learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-consul.html', + }, + }), + euiIconType: '/plugins/kibana/home/tutorial_resources/logos/consul.svg', + artifacts: { + dashboards: [ + { + id: '496910f0-b952-11e9-a579-f5c0a5d81340', + linkLabel: i18n.translate('kbn.server.tutorials.consulMetrics.artifacts.dashboards.linkLabel', { + defaultMessage: 'Consul metrics dashboard', + }), + isOverview: true + } + ], + exportedFields: { + documentationUrl: '{config.docs.beats.metricbeat}/exported-fields-consul.html' + } + }, + completionTimeMinutes: 10, + previewImagePath: '/plugins/kibana/home/tutorial_resources/consul_metrics/screenshot.png', + onPrem: onPremInstructions(moduleName, null, null, null, context), + elasticCloud: cloudInstructions(moduleName), + onPremElasticCloud: onPremCloudInstructions(moduleName) + }; +} diff --git a/src/legacy/core_plugins/kibana/server/tutorials/register.js b/src/legacy/core_plugins/kibana/server/tutorials/register.js index 0299d00856c64..70bc0f4d3c9eb 100644 --- a/src/legacy/core_plugins/kibana/server/tutorials/register.js +++ b/src/legacy/core_plugins/kibana/server/tutorials/register.js @@ -77,6 +77,7 @@ import { ciscoLogsSpecProvider } from './cisco_logs'; import { envoyproxyLogsSpecProvider } from './envoyproxy_logs'; import { couchdbMetricsSpecProvider } from './couchdb_metrics'; import { emsBoundariesSpecProvider } from './ems'; +import { consulMetricsSpecProvider } from './consul_metrics'; export function registerTutorials(server) { server.registerTutorial(systemLogsSpecProvider); @@ -139,4 +140,5 @@ export function registerTutorials(server) { server.registerTutorial(envoyproxyLogsSpecProvider); server.registerTutorial(couchdbMetricsSpecProvider); server.registerTutorial(emsBoundariesSpecProvider); + server.registerTutorial(consulMetricsSpecProvider); } From 2ddbc9eef6cff440dfd264c2cf6f6373280fe5bb Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Fri, 25 Oct 2019 13:35:24 +0200 Subject: [PATCH 141/191] Revert "Set values as html to table rows" (#49306) * Revert "Set values as html to table rows (#48911)" This reverts commit 3fd9f914374f08e17afd4b054c22eca6d5a65ffe. * Remove unrelated change from the revert --- .../kbn_doc_views/public/views/table/table_row.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx b/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx index cfc539eafe7b9..2059e35b2c42e 100644 --- a/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx +++ b/src/legacy/core_plugins/kbn_doc_views/public/views/table/table_row.tsx @@ -93,11 +93,9 @@ export function DocViewTableRow({ )} {displayUnderscoreWarning && } {displayNoMappingWarning && } -

+
+ {value} +
); From bcbdb92135e43e3c66a06fd732750f94a2684f92 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 25 Oct 2019 13:04:06 +0100 Subject: [PATCH 142/191] [ML] Adding advanced wizard duplicate detector warning (#49305) --- .../advanced_view/detector_list.tsx | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx index 2500cf79535d9..b82cc9b9c24bc 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx @@ -18,10 +18,12 @@ import { EuiSpacer, EuiCallOut, EuiHorizontalRule, + EuiFormRow, } from '@elastic/eui'; import { JobCreatorContext } from '../../../job_creator_context'; import { AdvancedJobCreator } from '../../../../../common/job_creator'; +import { Validation } from '../../../../../common/job_validator'; import { detectorToString } from '../../../../../../../util/string_utils'; interface Props { @@ -31,14 +33,21 @@ interface Props { } export const DetectorList: FC = ({ isActive, onEditJob, onDeleteJob }) => { - const { jobCreator: jc, jobCreatorUpdated } = useContext(JobCreatorContext); + const { jobCreator: jc, jobCreatorUpdated, jobValidator, jobValidatorUpdated } = useContext( + JobCreatorContext + ); const jobCreator = jc as AdvancedJobCreator; const [detectors, setDetectors] = useState(jobCreator.detectors); + const [validation, setValidation] = useState(jobValidator.duplicateDetectors); useEffect(() => { setDetectors(jobCreator.detectors); }, [jobCreatorUpdated]); + useEffect(() => { + setValidation(jobValidator.duplicateDetectors); + }, [jobValidatorUpdated]); + const Buttons: FC<{ index: number }> = ({ index }) => { return ( @@ -113,6 +122,7 @@ export const DetectorList: FC = ({ isActive, onEditJob, onDeleteJob }) => ))} + ); }; @@ -140,3 +150,17 @@ const NoDetectorsWarning: FC<{ show: boolean }> = ({ show }) => { ); }; + +const DuplicateDetectorsWarning: FC<{ validation: Validation }> = ({ validation }) => { + if (validation.valid === true) { + return null; + } + return ( + + + + + + + ); +}; From 54a9de8d48b53969adc2158290ea5f2db0d41322 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Fri, 25 Oct 2019 08:56:42 -0400 Subject: [PATCH 143/191] [SIEM] General Performance for 7.5 (#49138) * add useCallback to avoid re-render of component + fix memoize on the SourceQuery/Timeline/DetailsTimeline + Avoid all the events to re-render when pinned and/or adding note to an event * Update x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx Co-Authored-By: Garrett Spong * fix merging + bug --- .../drag_drop_context_wrapper.tsx | 37 ++-- .../components/edit_data_provider/index.tsx | 26 +-- .../event_details/stateful_event_details.tsx | 5 +- .../public/components/events_viewer/index.tsx | 50 +++-- .../fields_browser/field_browser.tsx | 34 ++-- .../components/fields_browser/index.test.tsx | 20 +- .../components/fields_browser/index.tsx | 96 ++++----- .../public/components/flyout/header/index.tsx | 58 +++--- .../public/components/flyout/pane/index.tsx | 31 +-- .../components/lazy_accordion/index.tsx | 10 +- .../components/notes/note_cards/index.tsx | 13 +- .../public/components/open_timeline/index.tsx | 145 +++++++------- .../open_timeline_modal/index.tsx | 24 ++- .../page/hosts/hosts_table/index.tsx | 31 +-- .../page/network/network_dns_table/index.tsx | 44 ++-- .../network_top_n_flow_table/index.tsx | 43 ++-- .../page/network/tls_table/index.tsx | 36 ++-- .../page/network/users_table/index.tsx | 35 ++-- .../public/components/search_bar/index.tsx | 188 ++++++++++-------- .../components/super_date_picker/index.tsx | 134 +++++++------ .../body/events/event_column_view.tsx | 15 +- .../components/timeline/body/events/index.tsx | 5 +- .../timeline/body/events/stateful_event.tsx | 39 ++-- .../body/events/stateful_event_child.tsx | 26 +-- .../components/timeline/body/helpers.ts | 9 +- .../components/timeline/body/index.test.tsx | 4 +- .../timeline/body/stateful_body.tsx | 62 +++--- .../data_providers/provider_item_badge.tsx | 18 +- .../components/timeline/footer/index.tsx | 10 +- .../siem/public/components/timeline/index.tsx | 137 +++++++------ .../components/timeline/properties/index.tsx | 14 +- .../timeline/search_or_filter/index.tsx | 42 ++-- .../components/with_hover_actions/index.tsx | 11 +- .../siem/public/containers/source/index.tsx | 26 ++- .../public/containers/timeline/all/index.tsx | 70 +++---- .../containers/timeline/details/index.tsx | 9 +- .../siem/public/store/app/selectors.ts | 8 +- 37 files changed, 831 insertions(+), 734 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx index 11b604571378b..c513f7a451240 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx @@ -5,7 +5,7 @@ */ import { defaultTo, noop } from 'lodash/fp'; -import * as React from 'react'; +import React, { useCallback } from 'react'; import { DragDropContext, DropResult, DragStart } from 'react-beautiful-dnd'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; @@ -59,22 +59,25 @@ const onDragEndHandler = ({ */ export const DragDropContextWrapperComponent = React.memo( ({ browserFields, children, dataProviders, dispatch }) => { - function onDragEnd(result: DropResult) { - enableScrolling(); - - if (dataProviders != null) { - onDragEndHandler({ - browserFields, - result, - dataProviders, - dispatch, - }); - } - - if (!draggableIsField(result)) { - document.body.classList.remove(IS_DRAGGING_CLASS_NAME); - } - } + const onDragEnd = useCallback( + (result: DropResult) => { + enableScrolling(); + + if (dataProviders != null) { + onDragEndHandler({ + browserFields, + result, + dataProviders, + dispatch, + }); + } + + if (!draggableIsField(result)) { + document.body.classList.remove(IS_DRAGGING_CLASS_NAME); + } + }, + [browserFields, dataProviders] + ); return ( {children} diff --git a/x-pack/legacy/plugins/siem/public/components/edit_data_provider/index.tsx b/x-pack/legacy/plugins/siem/public/components/edit_data_provider/index.tsx index dc7f2185c26b7..ec6646fc76085 100644 --- a/x-pack/legacy/plugins/siem/public/components/edit_data_provider/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/edit_data_provider/index.tsx @@ -17,7 +17,7 @@ import { EuiSpacer, EuiToolTip, } from '@elastic/eui'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useCallback } from 'react'; import styled, { injectGlobal } from 'styled-components'; import { BrowserFields } from '../../containers/source'; @@ -101,7 +101,7 @@ export const StatefulEditDataProvider = React.memo( const [updatedValue, setUpdatedValue] = useState(value); /** Focuses the Value input if it is visible, falling back to the Save button if it's not */ - function focusInput() { + const focusInput = () => { const elements = document.getElementsByClassName(VALUE_INPUT_CLASS_NAME); if (elements.length > 0) { @@ -113,25 +113,25 @@ export const StatefulEditDataProvider = React.memo( (saveElements[0] as HTMLElement).focus(); } } - } + }; - function onFieldSelected(selectedField: EuiComboBoxOptionProps[]) { + const onFieldSelected = useCallback((selectedField: EuiComboBoxOptionProps[]) => { setUpdatedField(selectedField); focusInput(); - } + }, []); - function onOperatorSelected(operatorSelected: EuiComboBoxOptionProps[]) { + const onOperatorSelected = useCallback((operatorSelected: EuiComboBoxOptionProps[]) => { setUpdatedOperator(operatorSelected); focusInput(); - } + }, []); - function onValueChange(e: React.ChangeEvent) { + const onValueChange = useCallback((e: React.ChangeEvent) => { setUpdatedValue(e.target.value); - } + }, []); - function disableScrolling() { + const disableScrolling = () => { const x = window.pageXOffset !== undefined ? window.pageXOffset @@ -143,11 +143,11 @@ export const StatefulEditDataProvider = React.memo( : (document.documentElement || document.body.parentNode || document.body).scrollTop; window.onscroll = () => window.scrollTo(x, y); - } + }; - function enableScrolling() { + const enableScrolling = () => { window.onscroll = () => noop; - } + }; useEffect(() => { disableScrolling(); diff --git a/x-pack/legacy/plugins/siem/public/components/event_details/stateful_event_details.tsx b/x-pack/legacy/plugins/siem/public/components/event_details/stateful_event_details.tsx index cb67736829878..c614fd52316bc 100644 --- a/x-pack/legacy/plugins/siem/public/components/event_details/stateful_event_details.tsx +++ b/x-pack/legacy/plugins/siem/public/components/event_details/stateful_event_details.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { BrowserFields } from '../../containers/source'; import { ColumnHeader } from '../timeline/body/column_headers/column_header'; @@ -27,6 +27,7 @@ export const StatefulEventDetails = React.memo( ({ browserFields, columnHeaders, data, id, onUpdateColumns, timelineId, toggleColumn }) => { const [view, setView] = useState('table-view'); + const handleSetView = useCallback(newView => setView(newView), []); return ( ( data={data} id={id} onUpdateColumns={onUpdateColumns} - onViewSelected={newView => setView(newView)} + onViewSelected={handleSetView} timelineId={timelineId} toggleColumn={toggleColumn} view={view} diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx index 0ecfb15a67f3b..9483c60dcc552 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx @@ -6,7 +6,7 @@ import { Filter } from '@kbn/es-query'; import { isEqual } from 'lodash/fp'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useCallback } from 'react'; import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; import { Query } from 'src/plugins/data/common'; @@ -102,32 +102,40 @@ const StatefulEventsViewerComponent = React.memo( }; }, []); - const onChangeItemsPerPage: OnChangeItemsPerPage = itemsChangedPerPage => - updateItemsPerPage({ id, itemsPerPage: itemsChangedPerPage }); - - const toggleColumn = (column: ColumnHeader) => { - const exists = columns.findIndex(c => c.id === column.id) !== -1; + const onChangeItemsPerPage: OnChangeItemsPerPage = useCallback( + itemsChangedPerPage => updateItemsPerPage({ id, itemsPerPage: itemsChangedPerPage }), + [id, updateItemsPerPage] + ); - if (!exists && upsertColumn != null) { - upsertColumn({ - column, - id, - index: 1, - }); - } + const toggleColumn = useCallback( + (column: ColumnHeader) => { + const exists = columns.findIndex(c => c.id === column.id) !== -1; + + if (!exists && upsertColumn != null) { + upsertColumn({ + column, + id, + index: 1, + }); + } + + if (exists && removeColumn != null) { + removeColumn({ + columnId: column.id, + id, + }); + } + }, + [columns, id, upsertColumn, removeColumn] + ); - if (exists && removeColumn != null) { - removeColumn({ - columnId: column.id, - id, - }); - } - }; + const handleOnMouseEnter = useCallback(() => setShowInspect(true), []); + const handleOnMouseLeave = useCallback(() => setShowInspect(false), []); return ( {({ indexPattern, browserFields }) => ( -
setShowInspect(true)} onMouseLeave={() => setShowInspect(false)}> +
( width, }) => { /** Focuses the input that filters the field browser */ - function focusInput() { + const focusInput = () => { const elements = document.getElementsByClassName( getFieldBrowserSearchInputClassName(timelineId) ); @@ -130,22 +130,28 @@ export const FieldsBrowser = React.memo( if (elements.length > 0) { (elements[0] as HTMLElement).focus(); // this cast is required because focus() does not exist on every `Element` returned by `getElementsByClassName` } - } + }; /** Invoked when the user types in the input to filter the field browser */ - function onInputChange(event: React.ChangeEvent) { - onSearchInputChange(event.target.value); - } + const onInputChange = useCallback( + (event: React.ChangeEvent) => { + onSearchInputChange(event.target.value); + }, + [onSearchInputChange] + ); - function selectFieldAndHide(fieldId: string) { - if (onFieldSelected != null) { - onFieldSelected(fieldId); - } + const selectFieldAndHide = useCallback( + (fieldId: string) => { + if (onFieldSelected != null) { + onFieldSelected(fieldId); + } - onHideFieldBrowser(); - } + onHideFieldBrowser(); + }, + [onFieldSelected, onHideFieldBrowser] + ); - function scrollViews() { + const scrollViews = () => { if (selectedCategoryId !== '') { const categoryPaneTitles = document.getElementsByClassName( getCategoryPaneCategoryClassName({ @@ -171,7 +177,7 @@ export const FieldsBrowser = React.memo( } focusInput(); // always re-focus the input to enable additional filtering - } + }; useEffect(() => { scrollViews(); diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx index 2a13d1549d90a..8948f765b8fbc 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx @@ -13,7 +13,7 @@ import { TestProviders } from '../../mock'; import { FIELD_BROWSER_HEIGHT, FIELD_BROWSER_WIDTH } from './helpers'; -import { INPUT_TIMEOUT, StatefulFieldsBrowser } from '.'; +import { StatefulFieldsBrowser } from '.'; // Suppress warnings about "act" until async/await syntax is supported: https://github.com/facebook/react/issues/14769 /* eslint-disable no-console */ const originalError = console.error; @@ -95,7 +95,7 @@ describe('StatefulFieldsBrowser', () => { describe('updateSelectedCategoryId', () => { beforeEach(() => { - jest.setTimeout(10000); + jest.useFakeTimers(); }); test('it updates the selectedCategoryId state, which makes the category bold, when the user clicks a category name in the left hand side of the field browser', () => { const wrapper = mount( @@ -127,7 +127,8 @@ describe('StatefulFieldsBrowser', () => { wrapper.find(`.field-browser-category-pane-auditd-${timelineId}`).first() ).toHaveStyleRule('font-weight', 'bold', { modifier: '.euiText' }); }); - test('it updates the selectedCategoryId state according to most fields returned', done => { + + test('it updates the selectedCategoryId state according to most fields returned', () => { const wrapper = mount( { .last() .simulate('change', { target: { value: 'cloud' } }); - setTimeout(() => { - wrapper.update(); - expect( - wrapper.find(`.field-browser-category-pane-cloud-${timelineId}`).first() - ).toHaveStyleRule('font-weight', 'bold', { modifier: '.euiText' }); - wrapper.unmount(); - done(); - }, INPUT_TIMEOUT); + jest.runOnlyPendingTimers(); + wrapper.update(); + expect( + wrapper.find(`.field-browser-category-pane-cloud-${timelineId}`).first() + ).toHaveStyleRule('font-weight', 'bold', { modifier: '.euiText' }); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx index a58721eb5a87f..2c8092a3295ad 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx @@ -6,7 +6,7 @@ import { EuiButtonEmpty, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { noop } from 'lodash/fp'; -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState, useCallback, useMemo } from 'react'; import { connect } from 'react-redux'; import styled from 'styled-components'; import { ActionCreator } from 'typescript-fsa'; @@ -82,77 +82,79 @@ export const StatefulFieldsBrowserComponent = React.memo { setShow(!show); - } + }, [show]); /** Invoked when the user types in the filter input */ - function updateFilter(newFilterInput: string) { - setFilterInput(newFilterInput); - setIsSearching(true); - - if (inputTimeoutId.current !== 0) { - clearTimeout(inputTimeoutId.current); // ⚠️ mutation: cancel any previous timers - } - // ⚠️ mutation: schedule a new timer that will apply the filter when it fires: - inputTimeoutId.current = window.setTimeout(() => { - const newFilteredBrowserFields = filterBrowserFieldsByFieldName({ - browserFields: mergeBrowserFieldsWithDefaultCategory(browserFields), - substring: newFilterInput, - }); - - setFilteredBrowserFields(newFilteredBrowserFields); - setIsSearching(false); - - const newSelectedCategoryId = - newFilterInput === '' || Object.keys(newFilteredBrowserFields).length === 0 - ? DEFAULT_CATEGORY_NAME - : Object.keys(newFilteredBrowserFields) - .sort() - .reduce( - (selected, category) => - newFilteredBrowserFields[category].fields != null && - newFilteredBrowserFields[selected].fields != null && - Object.keys(newFilteredBrowserFields[category].fields!).length > - Object.keys(newFilteredBrowserFields[selected].fields!).length - ? category - : selected, - Object.keys(newFilteredBrowserFields)[0] - ); - setSelectedCategoryId(newSelectedCategoryId); - }, INPUT_TIMEOUT); - } + const updateFilter = useCallback( + (newFilterInput: string) => { + setFilterInput(newFilterInput); + setIsSearching(true); + if (inputTimeoutId.current !== 0) { + clearTimeout(inputTimeoutId.current); // ⚠️ mutation: cancel any previous timers + } + // ⚠️ mutation: schedule a new timer that will apply the filter when it fires: + inputTimeoutId.current = window.setTimeout(() => { + const newFilteredBrowserFields = filterBrowserFieldsByFieldName({ + browserFields: mergeBrowserFieldsWithDefaultCategory(browserFields), + substring: newFilterInput, + }); + setFilteredBrowserFields(newFilteredBrowserFields); + setIsSearching(false); + + const newSelectedCategoryId = + newFilterInput === '' || Object.keys(newFilteredBrowserFields).length === 0 + ? DEFAULT_CATEGORY_NAME + : Object.keys(newFilteredBrowserFields) + .sort() + .reduce( + (selected, category) => + newFilteredBrowserFields[category].fields != null && + newFilteredBrowserFields[selected].fields != null && + Object.keys(newFilteredBrowserFields[category].fields!).length > + Object.keys(newFilteredBrowserFields[selected].fields!).length + ? category + : selected, + Object.keys(newFilteredBrowserFields)[0] + ); + setSelectedCategoryId(newSelectedCategoryId); + }, INPUT_TIMEOUT); + }, + [browserFields, filterInput, inputTimeoutId.current] + ); /** * Invoked when the user clicks a category name in the left-hand side of * the field browser */ - function updateSelectedCategoryId(categoryId: string) { + const updateSelectedCategoryId = useCallback((categoryId: string) => { setSelectedCategoryId(categoryId); - } + }, []); /** * Invoked when the user clicks on the context menu to view a category's * columns in the timeline, this function dispatches the action that * causes the timeline display those columns. */ - function updateColumnsAndSelectCategoryId(columns: ColumnHeader[]) { + const updateColumnsAndSelectCategoryId = useCallback((columns: ColumnHeader[]) => { onUpdateColumns(columns); // show the category columns in the timeline - } + }, []); /** Invoked when the field browser should be hidden */ - function hideFieldBrowser() { + const hideFieldBrowser = useCallback(() => { setFilterInput(''); setFilterInput(''); setFilteredBrowserFields(null); setIsSearching(false); setSelectedCategoryId(DEFAULT_CATEGORY_NAME); setShow(false); - } + }, []); // only merge in the default category if the field browser is visible - const browserFieldsWithDefaultCategory = show - ? mergeBrowserFieldsWithDefaultCategory(browserFields) - : {}; + const browserFieldsWithDefaultCategory = useMemo( + () => (show ? mergeBrowserFieldsWithDefaultCategory(browserFields) : {}), + [show, browserFields] + ); return ( <> diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx index 1d0e03265f5ea..2f4da30672e8c 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import * as React from 'react'; +import React, { useCallback } from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; import { ActionCreator } from 'typescript-fsa'; @@ -22,7 +22,7 @@ import { import { UpdateNote } from '../../notes/helpers'; import { defaultHeaders } from '../../timeline/body/column_headers/default_headers'; import { Properties } from '../../timeline/properties'; -import { appActions } from '../../../store/app'; +import { appActions, appModel } from '../../../store/app'; import { inputsActions } from '../../../store/inputs'; import { timelineActions } from '../../../store/actions'; import { TimelineModel } from '../../../store/timeline/model'; @@ -36,7 +36,7 @@ interface OwnProps { interface StateReduxProps { description: string; - getNotesByIds: (noteIds: string[]) => Note[]; + notesById: appModel.NotesById; isDataInTimeline: boolean; isDatepickerLocked: boolean; isFavorite: boolean; @@ -75,13 +75,13 @@ const StatefulFlyoutHeader = React.memo( associateNote, createTimeline, description, - getNotesByIds, isFavorite, isDataInTimeline, isDatepickerLocked, title, width = DEFAULT_TIMELINE_WIDTH, noteIds, + notesById, timelineId, toggleLock, updateDescription, @@ -89,27 +89,33 @@ const StatefulFlyoutHeader = React.memo( updateNote, updateTitle, usersViewing, - }) => ( - - ) + }) => { + const getNotesByIds = useCallback( + (noteIdsVar: string[]): Note[] => appSelectors.getNotes(notesById, noteIdsVar), + [notesById] + ); + return ( + + ); + } ); StatefulFlyoutHeader.displayName = 'StatefulFlyoutHeader'; @@ -139,7 +145,7 @@ const makeMapStateToProps = () => { return { description, - getNotesByIds: getNotesByIds(state), + notesById: getNotesByIds(state), history, isDataInTimeline: !isEmpty(dataProviders) || !isEmpty(get('filterQuery.kuery.expression', kqlQuery)), diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx index ceaff289f776c..ba5275ed79aef 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx @@ -5,7 +5,7 @@ */ import { EuiButtonIcon, EuiFlyout, EuiFlyoutBody, EuiFlyoutHeader, EuiToolTip } from '@elastic/eui'; -import * as React from 'react'; +import React, { useCallback } from 'react'; import { connect } from 'react-redux'; import styled from 'styled-components'; import { ActionCreator } from 'typescript-fsa'; @@ -122,19 +122,22 @@ const FlyoutPaneComponent = React.memo( usersViewing, width, }) => { - const renderFlyout = () => <>; - - const onResize: OnResize = ({ delta, id }) => { - const bodyClientWidthPixels = document.body.clientWidth; - - applyDeltaToWidth({ - bodyClientWidthPixels, - delta, - id, - maxWidthPercent, - minWidthPixels, - }); - }; + const renderFlyout = useCallback(() => <>, []); + + const onResize: OnResize = useCallback( + ({ delta, id }) => { + const bodyClientWidthPixels = document.body.clientWidth; + + applyDeltaToWidth({ + bodyClientWidthPixels, + delta, + id, + maxWidthPercent, + minWidthPixels, + }); + }, + [applyDeltaToWidth, maxWidthPercent, minWidthPixels] + ); return ( > & { forceExpand?: boolean; @@ -42,19 +42,19 @@ export const LazyAccordion = React.memo( renderExpandedContent, }) => { const [expanded, setExpanded] = useState(false); - const onCollapsedClick = () => { + const onCollapsedClick = useCallback(() => { setExpanded(true); if (onExpand != null) { onExpand(); } - }; + }, [onExpand]); - const onExpandedClick = () => { + const onExpandedClick = useCallback(() => { setExpanded(false); if (onCollapse != null) { onCollapse(); } - }; + }, [onCollapse]); return ( <> diff --git a/x-pack/legacy/plugins/siem/public/components/notes/note_cards/index.tsx b/x-pack/legacy/plugins/siem/public/components/notes/note_cards/index.tsx index aa9415aadeda1..6664660eb6bdc 100644 --- a/x-pack/legacy/plugins/siem/public/components/notes/note_cards/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/notes/note_cards/index.tsx @@ -5,7 +5,7 @@ */ import { EuiFlexGroup, EuiPanel } from '@elastic/eui'; -import React, { useState } from 'react'; +import React, { useState, useCallback } from 'react'; import styled from 'styled-components'; import { Note } from '../../../lib/note'; @@ -66,10 +66,13 @@ export const NoteCards = React.memo( }) => { const [newNote, setNewNote] = useState(''); - const associateNoteAndToggleShow = (noteId: string) => { - associateNote(noteId); - toggleShowAddNote(); - }; + const associateNoteAndToggleShow = useCallback( + (noteId: string) => { + associateNote(noteId); + toggleShowAddNote(); + }, + [associateNote, toggleShowAddNote] + ); return ( diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx index d101d1f4d39f4..c96d25f0d11f0 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx @@ -5,7 +5,7 @@ */ import ApolloClient from 'apollo-client'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useCallback } from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; @@ -98,9 +98,9 @@ export const StatefulOpenTimelineComponent = React.memo( const [sortField, setSortField] = useState(DEFAULT_SORT_FIELD); /** Invoked when the user presses enters to submit the text in the search input */ - const onQueryChange: OnQueryChange = (query: EuiSearchBarQuery) => { + const onQueryChange: OnQueryChange = useCallback((query: EuiSearchBarQuery) => { setSearch(query.queryText.trim()); - }; + }, []); /** Focuses the input that filters the field browser */ const focusInput = () => { @@ -126,23 +126,26 @@ export const StatefulOpenTimelineComponent = React.memo( // } // }; - const onDeleteOneTimeline: OnDeleteOneTimeline = (timelineIds: string[]) => { - deleteTimelines(timelineIds, { - search, - pageInfo: { - pageIndex: pageIndex + 1, - pageSize, - }, - sort: { - sortField: sortField as SortFieldTimeline, - sortOrder: sortDirection as Direction, - }, - onlyUserFavorite: onlyFavorites, - }); - }; + const onDeleteOneTimeline: OnDeleteOneTimeline = useCallback( + (timelineIds: string[]) => { + deleteTimelines(timelineIds, { + search, + pageInfo: { + pageIndex: pageIndex + 1, + pageSize, + }, + sort: { + sortField: sortField as SortFieldTimeline, + sortOrder: sortDirection as Direction, + }, + onlyUserFavorite: onlyFavorites, + }); + }, + [search, pageIndex, pageSize, sortField, sortDirection, onlyFavorites] + ); /** Invoked when the user clicks the action to delete the selected timelines */ - const onDeleteSelected: OnDeleteSelected = () => { + const onDeleteSelected: OnDeleteSelected = useCallback(() => { deleteTimelines(getSelectedTimelineIds(selectedItems), { search, pageInfo: { @@ -161,79 +164,81 @@ export const StatefulOpenTimelineComponent = React.memo( resetSelectionState(); // TODO: the query must re-execute to show the results of the deletion - }; + }, [selectedItems, search, pageIndex, pageSize, sortField, sortDirection, onlyFavorites]); /** Invoked when the user selects (or de-selects) timelines */ - const onSelectionChange: OnSelectionChange = (newSelectedItems: OpenTimelineResult[]) => { - setSelectedItems(newSelectedItems); // <-- this is NOT passed down as props to the table: https://github.com/elastic/eui/issues/1077 - }; + const onSelectionChange: OnSelectionChange = useCallback( + (newSelectedItems: OpenTimelineResult[]) => { + setSelectedItems(newSelectedItems); // <-- this is NOT passed down as props to the table: https://github.com/elastic/eui/issues/1077 + }, + [] + ); /** Invoked by the EUI table implementation when the user interacts with the table (i.e. to update sorting) */ - const onTableChange: OnTableChange = ({ page, sort }: OnTableChangeParams) => { + const onTableChange: OnTableChange = useCallback(({ page, sort }: OnTableChangeParams) => { const { index, size } = page; const { field, direction } = sort; setPageIndex(index); setPageSize(size); setSortDirection(direction); setSortField(field); - }; + }, []); /** Invoked when the user toggles the option to only view favorite timelines */ - const onToggleOnlyFavorites: OnToggleOnlyFavorites = () => { + const onToggleOnlyFavorites: OnToggleOnlyFavorites = useCallback(() => { setOnlyFavorites(!onlyFavorites); - }; + }, [onlyFavorites]); /** Invoked when the user toggles the expansion or collapse of inline notes in a table row */ - const onToggleShowNotes: OnToggleShowNotes = ( - newItemIdToExpandedNotesRowMap: Record - ) => { - setItemIdToExpandedNotesRowMap(newItemIdToExpandedNotesRowMap); - }; + const onToggleShowNotes: OnToggleShowNotes = useCallback( + (newItemIdToExpandedNotesRowMap: Record) => { + setItemIdToExpandedNotesRowMap(newItemIdToExpandedNotesRowMap); + }, + [] + ); /** Resets the selection state such that all timelines are unselected */ - const resetSelectionState = () => { + const resetSelectionState = useCallback(() => { setSelectedItems([]); - }; + }, []); - const openTimeline: OnOpenTimeline = ({ - duplicate, - timelineId, - }: { - duplicate: boolean; - timelineId: string; - }) => { - if (isModal && closeModalTimeline != null) { - closeModalTimeline(); - } + const openTimeline: OnOpenTimeline = useCallback( + ({ duplicate, timelineId }: { duplicate: boolean; timelineId: string }) => { + if (isModal && closeModalTimeline != null) { + closeModalTimeline(); + } - queryTimelineById({ - apolloClient, - duplicate, - timelineId, - updateIsLoading, - updateTimeline, - }); - }; + queryTimelineById({ + apolloClient, + duplicate, + timelineId, + updateIsLoading, + updateTimeline, + }); + }, + [apolloClient, updateIsLoading, updateTimeline] + ); + + const deleteTimelines: DeleteTimelines = useCallback( + (timelineIds: string[], variables?: AllTimelinesVariables) => { + if (timelineIds.includes(timeline.savedObjectId || '')) { + createNewTimeline({ id: 'timeline-1', columns: defaultHeaders, show: false }); + } + apolloClient.mutate({ + mutation: deleteTimelineMutation, + fetchPolicy: 'no-cache', + variables: { id: timelineIds }, + refetchQueries: [ + { + query: allTimelinesQuery, + variables, + }, + ], + }); + }, + [apolloClient, createNewTimeline, timeline] + ); - const deleteTimelines: DeleteTimelines = ( - timelineIds: string[], - variables?: AllTimelinesVariables - ) => { - if (timelineIds.includes(timeline.savedObjectId || '')) { - createNewTimeline({ id: 'timeline-1', columns: defaultHeaders, show: false }); - } - apolloClient.mutate({ - mutation: deleteTimelineMutation, - fetchPolicy: 'no-cache', - variables: { id: timelineIds }, - refetchQueries: [ - { - query: allTimelinesQuery, - variables, - }, - ], - }); - }; useEffect(() => { focusInput(); }, []); diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.tsx index 41907e07d5c1b..e8242237cd2c8 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/open_timeline_modal/index.tsx @@ -5,7 +5,7 @@ */ import { EuiButtonEmpty, EuiModal, EuiOverlayMask } from '@elastic/eui'; -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { ApolloConsumer } from 'react-apollo'; import * as i18n from '../translations'; @@ -29,16 +29,20 @@ export const OpenTimelineModalButton = React.memo( const [showModal, setShowModal] = useState(false); /** shows or hides the `Open Timeline` modal */ - function toggleShowModal() { + const openModal = useCallback(() => { if (onToggle != null) { onToggle(); } - setShowModal(!showModal); - } + setShowModal(true); + }, [onToggle]); + + const closeModal = useCallback(() => { + if (onToggle != null) { + onToggle(); + } + setShowModal(false); + }, [onToggle]); - function closeModalTimeline() { - toggleShowModal(); - } return ( {client => ( @@ -48,7 +52,7 @@ export const OpenTimelineModalButton = React.memo( data-test-subj="open-timeline-button" iconSide="left" iconType="folderOpen" - onClick={toggleShowModal} + onClick={openModal} > {i18n.OPEN_TIMELINE} @@ -58,11 +62,11 @@ export const OpenTimelineModalButton = React.memo( ( updateTableActivePage, updateTableLimit, }) => { - const onChange = (criteria: Criteria) => { - if (criteria.sort != null) { - const sort: HostsSortField = { - field: getSortField(criteria.sort.field), - direction: criteria.sort.direction, - }; - if (sort.direction !== direction || sort.field !== sortField) { - updateHostsSort({ - sort, - hostsType: type, - }); + const onChange = useCallback( + (criteria: Criteria) => { + if (criteria.sort != null) { + const sort: HostsSortField = { + field: getSortField(criteria.sort.field), + direction: criteria.sort.direction, + }; + if (sort.direction !== direction || sort.field !== sortField) { + updateHostsSort({ + sort, + hostsType: type, + }); + } } - } - }; + }, + [direction, sortField, type] + ); const hostsColumns = useMemo(() => getHostsColumns(), []); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx index c1c1bec80d676..ac5470ee4f236 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx @@ -5,7 +5,7 @@ */ import { isEqual } from 'lodash/fp'; -import React from 'react'; +import React, { useCallback } from 'react'; import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; @@ -77,24 +77,34 @@ export const NetworkDnsTableComponent = React.memo( type, updateNetworkTable, }) => { - const onChange = (criteria: Criteria) => { - if (criteria.sort != null) { - const newDnsSortField: NetworkDnsSortField = { - field: criteria.sort.field.split('.')[1] as NetworkDnsFields, - direction: criteria.sort.direction, - }; - if (!isEqual(newDnsSortField, sort)) { - updateNetworkTable({ networkType: type, tableType, updates: { sort: newDnsSortField } }); + const onChange = useCallback( + (criteria: Criteria) => { + if (criteria.sort != null) { + const newDnsSortField: NetworkDnsSortField = { + field: criteria.sort.field.split('.')[1] as NetworkDnsFields, + direction: criteria.sort.direction, + }; + if (!isEqual(newDnsSortField, sort)) { + updateNetworkTable({ + networkType: type, + tableType, + updates: { sort: newDnsSortField }, + }); + } } - } - }; + }, + [sort, type] + ); - const onChangePtrIncluded = () => - updateNetworkTable({ - networkType: type, - tableType, - updates: { isPtrIncluded: !isPtrIncluded }, - }); + const onChangePtrIncluded = useCallback( + () => + updateNetworkTable({ + networkType: type, + tableType, + updates: { isPtrIncluded: !isPtrIncluded }, + }), + [type, isPtrIncluded] + ); return ( ( type, updateNetworkTable, }) => { - const onChange = (criteria: Criteria, tableType: networkModel.TopNTableType) => { - if (criteria.sort != null) { - const splitField = criteria.sort.field.split('.'); - const field = last(splitField); - const newSortDirection = field !== sort.field ? Direction.desc : criteria.sort.direction; // sort by desc on init click - const newTopNFlowSort: NetworkTopTablesSortField = { - field: field as NetworkTopTablesFields, - direction: newSortDirection, - }; - if (!isEqual(newTopNFlowSort, sort)) { - updateNetworkTable({ - networkType: type, - tableType, - updates: { - sort: newTopNFlowSort, - }, - }); + const onChange = useCallback( + (criteria: Criteria, tableType: networkModel.TopNTableType) => { + if (criteria.sort != null) { + const splitField = criteria.sort.field.split('.'); + const field = last(splitField); + const newSortDirection = field !== sort.field ? Direction.desc : criteria.sort.direction; // sort by desc on init click + const newTopNFlowSort: NetworkTopTablesSortField = { + field: field as NetworkTopTablesFields, + direction: newSortDirection, + }; + if (!isEqual(newTopNFlowSort, sort)) { + updateNetworkTable({ + networkType: type, + tableType, + updates: { + sort: newTopNFlowSort, + }, + }); + } } - } - }; + }, + [sort, type] + ); let tableType: networkModel.TopNTableType; const headerTitle: string = diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx index 3a4712e53c4d4..6adb335839982 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx @@ -5,7 +5,7 @@ */ import { isEqual } from 'lodash/fp'; -import React from 'react'; +import React, { useCallback } from 'react'; import { connect } from 'react-redux'; import { compose } from 'redux'; import { ActionCreator } from 'typescript-fsa'; @@ -78,22 +78,26 @@ const TlsTableComponent = React.memo( type === networkModel.NetworkType.page ? networkModel.NetworkTableType.tls : networkModel.IpDetailsTableType.tls; - const onChange = (criteria: Criteria) => { - if (criteria.sort != null) { - const splitField = criteria.sort.field.split('.'); - const newTlsSort: TlsSortField = { - field: getSortFromString(splitField[splitField.length - 1]), - direction: criteria.sort.direction, - }; - if (!isEqual(newTlsSort, sort)) { - updateNetworkTable({ - networkType: type, - tableType, - updates: { sort: newTlsSort }, - }); + + const onChange = useCallback( + (criteria: Criteria) => { + if (criteria.sort != null) { + const splitField = criteria.sort.field.split('.'); + const newTlsSort: TlsSortField = { + field: getSortFromString(splitField[splitField.length - 1]), + direction: criteria.sort.direction, + }; + if (!isEqual(newTlsSort, sort)) { + updateNetworkTable({ + networkType: type, + tableType, + updates: { sort: newTlsSort }, + }); + } } - } - }; + }, + [sort, type] + ); return ( ( updateNetworkTable, sort, }) => { - const onChange = (criteria: Criteria) => { - if (criteria.sort != null) { - const splitField = criteria.sort.field.split('.'); - const newUsersSort: UsersSortField = { - field: getSortFromString(splitField[splitField.length - 1]), - direction: criteria.sort.direction, - }; - if (!isEqual(newUsersSort, sort)) { - updateNetworkTable({ - networkType: type, - tableType, - updates: { sort: newUsersSort }, - }); + const onChange = useCallback( + (criteria: Criteria) => { + if (criteria.sort != null) { + const splitField = criteria.sort.field.split('.'); + const newUsersSort: UsersSortField = { + field: getSortFromString(splitField[splitField.length - 1]), + direction: criteria.sort.direction, + }; + if (!isEqual(newUsersSort, sort)) { + updateNetworkTable({ + networkType: type, + tableType, + updates: { sort: newUsersSort }, + }); + } } - } - }; + }, + [sort, type] + ); return ( { - const isQuickSelection = - payload.dateRange.from.includes('now') || payload.dateRange.to.includes('now'); - let updateSearchBar: UpdateReduxSearchBar = { - id, - end: toStr != null ? toStr : new Date(end).toISOString(), - start: fromStr != null ? fromStr : new Date(start).toISOString(), - isInvalid: false, - isQuickSelection, - updateTime: false, - }; - let isStateUpdated = false; - - if ( - (isQuickSelection && - (fromStr !== payload.dateRange.from || toStr !== payload.dateRange.to)) || - (!isQuickSelection && - (start !== formatDate(payload.dateRange.from) || - end !== formatDate(payload.dateRange.to))) - ) { - isStateUpdated = true; - updateSearchBar.updateTime = true; - updateSearchBar.end = payload.dateRange.to; - updateSearchBar.start = payload.dateRange.from; - } - - if (payload.query != null && !isEqual(payload.query, filterQuery)) { - isStateUpdated = true; - updateSearchBar = set('query', payload.query, updateSearchBar); - } - - if (!isStateUpdated) { - // That mean we are doing a refresh! - if (isQuickSelection) { + const onQuerySubmit = useCallback( + (payload: { dateRange: TimeRange; query?: Query }) => { + const isQuickSelection = + payload.dateRange.from.includes('now') || payload.dateRange.to.includes('now'); + let updateSearchBar: UpdateReduxSearchBar = { + id, + end: toStr != null ? toStr : new Date(end).toISOString(), + start: fromStr != null ? fromStr : new Date(start).toISOString(), + isInvalid: false, + isQuickSelection, + updateTime: false, + }; + let isStateUpdated = false; + + if ( + (isQuickSelection && + (fromStr !== payload.dateRange.from || toStr !== payload.dateRange.to)) || + (!isQuickSelection && + (start !== formatDate(payload.dateRange.from) || + end !== formatDate(payload.dateRange.to))) + ) { + isStateUpdated = true; updateSearchBar.updateTime = true; updateSearchBar.end = payload.dateRange.to; updateSearchBar.start = payload.dateRange.from; - } else { - queries.forEach(q => q.refetch && (q.refetch as inputsModel.Refetch)()); } - } - window.setTimeout(() => updateSearch(updateSearchBar), 0); - }; + if (payload.query != null && !isEqual(payload.query, filterQuery)) { + isStateUpdated = true; + updateSearchBar = set('query', payload.query, updateSearchBar); + } - const onRefresh = (payload: { dateRange: TimeRange }) => { - if (payload.dateRange.from.includes('now') || payload.dateRange.to.includes('now')) { - updateSearch({ - id, - end: payload.dateRange.to, - start: payload.dateRange.from, - isInvalid: false, - isQuickSelection: true, - updateTime: true, - }); - } else { - queries.forEach(q => q.refetch && (q.refetch as inputsModel.Refetch)()); - } - }; + if (!isStateUpdated) { + // That mean we are doing a refresh! + if (isQuickSelection) { + updateSearchBar.updateTime = true; + updateSearchBar.end = payload.dateRange.to; + updateSearchBar.start = payload.dateRange.from; + } else { + queries.forEach(q => q.refetch && (q.refetch as inputsModel.Refetch)()); + } + } - const onSaved = (newSavedQuery: SavedQuery) => { - setSavedQuery({ id, savedQuery: newSavedQuery }); - }; + window.setTimeout(() => updateSearch(updateSearchBar), 0); + }, + [id, end, filterQuery, fromStr, queries, start, toStr] + ); - const onSavedQueryUpdated = (savedQueryUpdated: SavedQuery) => { - const isQuickSelection = savedQueryUpdated.attributes.timefilter - ? savedQueryUpdated.attributes.timefilter.from.includes('now') || - savedQueryUpdated.attributes.timefilter.to.includes('now') - : false; + const onRefresh = useCallback( + (payload: { dateRange: TimeRange }) => { + if (payload.dateRange.from.includes('now') || payload.dateRange.to.includes('now')) { + updateSearch({ + id, + end: payload.dateRange.to, + start: payload.dateRange.from, + isInvalid: false, + isQuickSelection: true, + updateTime: true, + }); + } else { + queries.forEach(q => q.refetch && (q.refetch as inputsModel.Refetch)()); + } + }, + [id, queries] + ); - let updateSearchBar: UpdateReduxSearchBar = { - id, - filters: savedQueryUpdated.attributes.filters || [], - end: toStr != null ? toStr : new Date(end).toISOString(), - start: fromStr != null ? fromStr : new Date(start).toISOString(), - isInvalid: false, - isQuickSelection, - updateTime: false, - }; + const onSaved = useCallback( + (newSavedQuery: SavedQuery) => { + setSavedQuery({ id, savedQuery: newSavedQuery }); + }, + [id] + ); - if (savedQueryUpdated.attributes.timefilter) { - updateSearchBar.end = savedQueryUpdated.attributes.timefilter - ? savedQueryUpdated.attributes.timefilter.to - : updateSearchBar.end; - updateSearchBar.start = savedQueryUpdated.attributes.timefilter - ? savedQueryUpdated.attributes.timefilter.from - : updateSearchBar.start; - updateSearchBar.updateTime = true; - } + const onSavedQueryUpdated = useCallback( + (savedQueryUpdated: SavedQuery) => { + const isQuickSelection = savedQueryUpdated.attributes.timefilter + ? savedQueryUpdated.attributes.timefilter.from.includes('now') || + savedQueryUpdated.attributes.timefilter.to.includes('now') + : false; + + let updateSearchBar: UpdateReduxSearchBar = { + id, + filters: savedQueryUpdated.attributes.filters || [], + end: toStr != null ? toStr : new Date(end).toISOString(), + start: fromStr != null ? fromStr : new Date(start).toISOString(), + isInvalid: false, + isQuickSelection, + updateTime: false, + }; + + if (savedQueryUpdated.attributes.timefilter) { + updateSearchBar.end = savedQueryUpdated.attributes.timefilter + ? savedQueryUpdated.attributes.timefilter.to + : updateSearchBar.end; + updateSearchBar.start = savedQueryUpdated.attributes.timefilter + ? savedQueryUpdated.attributes.timefilter.from + : updateSearchBar.start; + updateSearchBar.updateTime = true; + } - updateSearchBar = set('query', savedQueryUpdated.attributes.query, updateSearchBar); - updateSearchBar = set('savedQuery', savedQueryUpdated, updateSearchBar); + updateSearchBar = set('query', savedQueryUpdated.attributes.query, updateSearchBar); + updateSearchBar = set('savedQuery', savedQueryUpdated, updateSearchBar); - updateSearch(updateSearchBar); - }; + updateSearch(updateSearchBar); + }, + [id, end, fromStr, start, toStr] + ); - const onClearSavedQuery = () => { + const onClearSavedQuery = useCallback(() => { if (savedQuery != null) { updateSearch({ id, @@ -222,7 +234,7 @@ const SearchBarComponent = memo { let isSubscribed = true; @@ -246,13 +258,13 @@ const SearchBarComponent = memo [indexPattern as IndexPattern], [indexPattern]); return ( ( const [recentlyUsedRanges, setRecentlyUsedRanges] = useState( [] ); - const onRefresh = ({ start: newStart, end: newEnd }: OnRefreshProps): void => { - updateReduxTime({ - end: newEnd, - id, - isInvalid: false, - isQuickSelection, - kql: kqlQuery, - start: newStart, - timelineId, - }); - const currentStart = formatDate(newStart); - const currentEnd = isQuickSelection - ? formatDate(newEnd, { roundUp: true }) - : formatDate(newEnd); - if (!isQuickSelection || (start === currentStart && end === currentEnd)) { - refetchQuery(queries); - } - }; - - const onRefreshChange = ({ isPaused, refreshInterval }: OnRefreshChangeProps): void => { - if (duration !== refreshInterval) { - setDuration({ id, duration: refreshInterval }); - } - - if (isPaused && policy === 'interval') { - stopAutoReload({ id }); - } else if (!isPaused && policy === 'manual') { - startAutoReload({ id }); - } - - if (!isPaused && (!isQuickSelection || (isQuickSelection && toStr !== 'now'))) { - refetchQuery(queries); - } - }; - - const refetchQuery = (newQueries: inputsModel.GlobalGraphqlQuery[]) => { - newQueries.forEach(q => q.refetch && (q.refetch as inputsModel.Refetch)()); - }; - - const onTimeChange = ({ - start: newStart, - end: newEnd, - isQuickSelection: newIsQuickSelection, - isInvalid, - }: OnTimeChangeProps) => { - if (!isInvalid) { + const onRefresh = useCallback( + ({ start: newStart, end: newEnd }: OnRefreshProps): void => { updateReduxTime({ end: newEnd, id, - isInvalid, - isQuickSelection: newIsQuickSelection, + isInvalid: false, + isQuickSelection, kql: kqlQuery, start: newStart, timelineId, }); - const newRecentlyUsedRanges = [ - { start: newStart, end: newEnd }, - ...take( - MAX_RECENTLY_USED_RANGES, - recentlyUsedRanges.filter( - recentlyUsedRange => - !(recentlyUsedRange.start === newStart && recentlyUsedRange.end === newEnd) - ) - ), - ]; + const currentStart = formatDate(newStart); + const currentEnd = isQuickSelection + ? formatDate(newEnd, { roundUp: true }) + : formatDate(newEnd); + if (!isQuickSelection || (start === currentStart && end === currentEnd)) { + refetchQuery(queries); + } + }, + [end, id, isQuickSelection, kqlQuery, start, timelineId] + ); + + const onRefreshChange = useCallback( + ({ isPaused, refreshInterval }: OnRefreshChangeProps): void => { + if (duration !== refreshInterval) { + setDuration({ id, duration: refreshInterval }); + } - setRecentlyUsedRanges(newRecentlyUsedRanges); - setIsQuickSelection(newIsQuickSelection); - } + if (isPaused && policy === 'interval') { + stopAutoReload({ id }); + } else if (!isPaused && policy === 'manual') { + startAutoReload({ id }); + } + + if (!isPaused && (!isQuickSelection || (isQuickSelection && toStr !== 'now'))) { + refetchQuery(queries); + } + }, + [id, isQuickSelection, duration, policy, toStr] + ); + + const refetchQuery = (newQueries: inputsModel.GlobalGraphqlQuery[]) => { + newQueries.forEach(q => q.refetch && (q.refetch as inputsModel.Refetch)()); }; + + const onTimeChange = useCallback( + ({ + start: newStart, + end: newEnd, + isQuickSelection: newIsQuickSelection, + isInvalid, + }: OnTimeChangeProps) => { + if (!isInvalid) { + updateReduxTime({ + end: newEnd, + id, + isInvalid, + isQuickSelection: newIsQuickSelection, + kql: kqlQuery, + start: newStart, + timelineId, + }); + const newRecentlyUsedRanges = [ + { start: newStart, end: newEnd }, + ...take( + MAX_RECENTLY_USED_RANGES, + recentlyUsedRanges.filter( + recentlyUsedRange => + !(recentlyUsedRange.start === newStart && recentlyUsedRange.end === newEnd) + ) + ), + ]; + + setRecentlyUsedRanges(newRecentlyUsedRanges); + setIsQuickSelection(newIsQuickSelection); + } + }, + [recentlyUsedRanges, kqlQuery] + ); + const endDate = kind === 'relative' ? toStr : new Date(end).toISOString(); const startDate = kind === 'relative' ? fromStr : new Date(start).toISOString(); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/event_column_view.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/event_column_view.tsx index 7afa6ca70ff9b..96cb9f754f525 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/event_column_view.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/event_column_view.tsx @@ -15,7 +15,7 @@ import { EventsTrData } from '../../styles'; import { Actions } from '../actions'; import { ColumnHeader } from '../column_headers/column_header'; import { DataDrivenColumns } from '../data_driven_columns'; -import { eventHasNotes, eventIsPinned, getPinOnClick } from '../helpers'; +import { eventHasNotes, getPinOnClick } from '../helpers'; import { ColumnRenderer } from '../renderers/column_renderer'; interface Props { @@ -28,13 +28,13 @@ interface Props { eventIdToNoteIds: Readonly>; expanded: boolean; getNotesByIds: (noteIds: string[]) => Note[]; + isEventPinned: boolean; isEventViewer?: boolean; loading: boolean; onColumnResized: OnColumnResized; onEventToggled: () => void; onPinEvent: OnPinEvent; onUnPinEvent: OnUnPinEvent; - pinnedEventIds: Readonly>; showNotes: boolean; timelineId: string; toggleShowNotes: () => void; @@ -56,13 +56,13 @@ export const EventColumnView = React.memo( eventIdToNoteIds, expanded, getNotesByIds, + isEventPinned = false, isEventViewer = false, loading, onColumnResized, onEventToggled, onPinEvent, onUnPinEvent, - pinnedEventIds, showNotes, timelineId, toggleShowNotes, @@ -76,10 +76,7 @@ export const EventColumnView = React.memo( expanded={expanded} data-test-subj="actions" eventId={id} - eventIsPinned={eventIsPinned({ - eventId: id, - pinnedEventIds, - })} + eventIsPinned={isEventPinned} getNotesByIds={getNotesByIds} isEventViewer={isEventViewer} loading={loading} @@ -90,7 +87,7 @@ export const EventColumnView = React.memo( eventId: id, onPinEvent, onUnPinEvent, - pinnedEventIds, + isEventPinned, })} showCheckboxes={false} showNotes={showNotes} @@ -118,7 +115,7 @@ export const EventColumnView = React.memo( prevProps.eventIdToNoteIds === nextProps.eventIdToNoteIds && prevProps.expanded === nextProps.expanded && prevProps.loading === nextProps.loading && - prevProps.pinnedEventIds === nextProps.pinnedEventIds && + prevProps.isEventPinned === nextProps.isEventPinned && prevProps.showNotes === nextProps.showNotes && prevProps.timelineId === nextProps.timelineId ); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/index.tsx index 78992dceea4dc..34281219bcc0c 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import * as React from 'react'; +import React from 'react'; import { BrowserFields } from '../../../../containers/source'; import { TimelineItem } from '../../../../graphql/types'; @@ -17,6 +17,7 @@ import { ColumnHeader } from '../column_headers/column_header'; import { ColumnRenderer } from '../renderers/column_renderer'; import { RowRenderer } from '../renderers/row_renderer'; import { StatefulEvent } from './stateful_event'; +import { eventIsPinned } from '../helpers'; interface Props { actionsColumnWidth: number; @@ -74,6 +75,7 @@ export const Events = React.memo( event={event} eventIdToNoteIds={eventIdToNoteIds} getNotesByIds={getNotesByIds} + isEventPinned={eventIsPinned({ eventId: event._id, pinnedEventIds })} isEventViewer={isEventViewer} key={event._id} maxDelay={maxDelay(i)} @@ -81,7 +83,6 @@ export const Events = React.memo( onPinEvent={onPinEvent} onUnPinEvent={onUnPinEvent} onUpdateColumns={onUpdateColumns} - pinnedEventIds={pinnedEventIds} rowRenderers={rowRenderers} timelineId={id} toggleColumn={toggleColumn} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx index 766a75c05f17c..d54fe8df28a85 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState, useCallback } from 'react'; import uuid from 'uuid'; import VisibilitySensor from 'react-visibility-sensor'; @@ -21,7 +21,6 @@ import { STATEFUL_EVENT_CSS_CLASS_NAME } from '../../helpers'; import { EventsTrGroup, EventsTrSupplement, OFFSET_SCROLLBAR } from '../../styles'; import { useTimelineWidthContext } from '../../timeline_context'; import { ColumnHeader } from '../column_headers/column_header'; -import { eventIsPinned } from '../helpers'; import { ColumnRenderer } from '../renderers/column_renderer'; import { getRowRenderer } from '../renderers/get_row_renderer'; import { RowRenderer } from '../renderers/row_renderer'; @@ -42,7 +41,7 @@ interface Props { onPinEvent: OnPinEvent; onUnPinEvent: OnUnPinEvent; onUpdateColumns: OnUpdateColumns; - pinnedEventIds: Readonly>; + isEventPinned: boolean; rowRenderers: RowRenderer[]; timelineId: string; toggleColumn: (column: ColumnHeader) => void; @@ -110,12 +109,12 @@ export const StatefulEvent = React.memo( eventIdToNoteIds, getNotesByIds, isEventViewer = false, + isEventPinned = false, maxDelay = 0, onColumnResized, onPinEvent, onUnPinEvent, onUpdateColumns, - pinnedEventIds, rowRenderers, timelineId, toggleColumn, @@ -127,27 +126,28 @@ export const StatefulEvent = React.memo( const divElement = useRef(null); - const onToggleShowNotes = (eventId: string): (() => void) => () => { + const onToggleShowNotes = useCallback(() => { + const eventId = event._id; setShowNotes({ ...showNotes, [eventId]: !showNotes[eventId] }); - }; + }, [event, showNotes]); - const onToggleExpanded = (eventId: string): (() => void) => () => { + const onToggleExpanded = useCallback(() => { + const eventId = event._id; setExpanded({ ...expanded, [eventId]: !expanded[eventId], }); - }; + }, [event, expanded]); - const associateNote = ( - eventId: string, - addNoteToEventChild: AddNoteToEvent, - onPinEventChild: OnPinEvent - ): ((noteId: string) => void) => (noteId: string) => { - addNoteToEventChild({ eventId, noteId }); - if (!eventIsPinned({ eventId, pinnedEventIds })) { - onPinEventChild(eventId); // pin the event, because it has notes - } - }; + const associateNote = useCallback( + (noteId: string) => { + addNoteToEvent({ eventId: event._id, noteId }); + if (!isEventPinned) { + onPinEvent(event._id); // pin the event, because it has notes + } + }, + [addNoteToEvent, event, isEventPinned, onPinEvent] + ); /** * Incrementally loads the events when it mounts by trying to @@ -155,7 +155,6 @@ export const StatefulEvent = React.memo( * indicate to React that it should render its self by setting * its initialRender to true. */ - useEffect(() => { let _isMounted = true; @@ -222,6 +221,7 @@ export const StatefulEvent = React.memo( expanded={!!expanded[event._id]} getNotesByIds={getNotesByIds} id={event._id} + isEventPinned={isEventPinned} isEventViewer={isEventViewer} loading={loading} onColumnResized={onColumnResized} @@ -229,7 +229,6 @@ export const StatefulEvent = React.memo( onToggleExpanded={onToggleExpanded} onToggleShowNotes={onToggleShowNotes} onUnPinEvent={onUnPinEvent} - pinnedEventIds={pinnedEventIds} showNotes={!!showNotes[event._id]} timelineId={timelineId} updateNote={updateNote} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event_child.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event_child.tsx index 4a623ce99c9e9..668139349a377 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event_child.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/events/stateful_event_child.tsx @@ -29,21 +29,17 @@ interface Props { expanded: boolean; eventIdToNoteIds: Readonly>; isEventViewer?: boolean; + isEventPinned: boolean; loading: boolean; onColumnResized: OnColumnResized; onUnPinEvent: OnUnPinEvent; - pinnedEventIds: Readonly>; showNotes: boolean; timelineId: string; updateNote: UpdateNote; - onToggleExpanded: (eventId: string) => () => void; - onToggleShowNotes: (eventId: string) => () => void; + onToggleExpanded: () => void; + onToggleShowNotes: () => void; getNotesByIds: (noteIds: string[]) => Note[]; - associateNote: ( - eventId: string, - addNoteToEvent: AddNoteToEvent, - onPinEvent: OnPinEvent - ) => (noteId: string) => void; + associateNote: (noteId: string) => void; } export const getNewNoteId = (): string => uuid.v4(); @@ -64,11 +60,11 @@ export const StatefulEventChild = React.memo( eventIdToNoteIds, getNotesByIds, isEventViewer = false, + isEventPinned = false, loading, onColumnResized, onToggleExpanded, onUnPinEvent, - pinnedEventIds, showNotes, timelineId, onToggleShowNotes, @@ -84,23 +80,23 @@ export const StatefulEventChild = React.memo( @@ -110,13 +106,13 @@ export const StatefulEventChild = React.memo( style={{ width: `${width - OFFSET_SCROLLBAR}px` }} > diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/helpers.ts b/x-pack/legacy/plugins/siem/public/components/timeline/body/helpers.ts index 1cd83cb5560ea..0b1d21b2371ee 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/helpers.ts @@ -55,7 +55,7 @@ export interface GetPinOnClickParams { eventId: string; onPinEvent: OnPinEvent; onUnPinEvent: OnUnPinEvent; - pinnedEventIds: Readonly>; + isEventPinned: boolean; } export const getPinOnClick = ({ @@ -63,15 +63,12 @@ export const getPinOnClick = ({ eventId, onPinEvent, onUnPinEvent, - pinnedEventIds, + isEventPinned, }: GetPinOnClickParams): (() => void) => { if (!allowUnpinning) { return noop; } - - return eventIsPinned({ eventId, pinnedEventIds }) - ? () => onUnPinEvent(eventId) - : () => onPinEvent(eventId); + return isEventPinned ? () => onUnPinEvent(eventId) : () => onPinEvent(eventId); }; export const getColumnWidthFromType = (type: string): number => diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx index 73b208757c7ad..86a6ebe22799b 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx @@ -215,7 +215,7 @@ describe('Body', () => { wrapper.update(); wrapper .find('[data-test-subj="new-note-tabs"] textarea') - .simulate('change', { target: { value: 'hello world' } }); + .simulate('change', { target: { value: note } }); wrapper.update(); wrapper .find('button[data-test-subj="add-note"]') @@ -314,13 +314,11 @@ describe('Body', () => { /> ); addaNoteToEvent(wrapper, 'hello world'); - dispatchAddNoteToEvent.mockClear(); dispatchOnPinEvent.mockClear(); wrapper.setProps({ pinnedEventIds: { 1: true } }); wrapper.update(); addaNoteToEvent(wrapper, 'new hello world'); - expect(dispatchAddNoteToEvent).toHaveBeenCalled(); expect(dispatchOnPinEvent).not.toHaveBeenCalled(); }); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx index d93446b2af95b..531e61dd7dc60 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx @@ -6,14 +6,14 @@ import { noop } from 'lodash/fp'; import memoizeOne from 'memoize-one'; -import * as React from 'react'; +import React, { useCallback } from 'react'; import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; import { BrowserFields } from '../../../containers/source'; import { TimelineItem } from '../../../graphql/types'; import { Note } from '../../../lib/note'; -import { appSelectors, State, timelineSelectors } from '../../../store'; +import { appModel, appSelectors, State, timelineSelectors } from '../../../store'; import { AddNoteToEvent, UpdateNote } from '../../notes/helpers'; import { OnColumnRemoved, @@ -45,7 +45,7 @@ interface OwnProps { interface ReduxProps { columnHeaders: ColumnHeader[]; eventIdToNoteIds: Readonly>; - getNotesByIds: (noteIds: string[]) => Note[]; + notesById: appModel.NotesById; pinnedEventIds: Readonly>; range?: string; } @@ -92,10 +92,10 @@ const StatefulBodyComponent = React.memo( columnHeaders, data, eventIdToNoteIds, - getNotesByIds, height, id, isEventViewer = false, + notesById, pinEvent, pinnedEventIds, range, @@ -107,30 +107,44 @@ const StatefulBodyComponent = React.memo( updateNote, updateSort, }) => { - const onAddNoteToEvent: AddNoteToEvent = ({ - eventId, - noteId, - }: { - eventId: string; - noteId: string; - }) => addNoteToEvent!({ id, eventId, noteId }); - - const onColumnSorted: OnColumnSorted = sorted => { - updateSort!({ id, sort: sorted }); - }; + const getNotesByIds = useCallback( + (noteIds: string[]): Note[] => appSelectors.getNotes(notesById, noteIds), + [notesById] + ); - const onColumnRemoved: OnColumnRemoved = columnId => removeColumn!({ id, columnId }); + const onAddNoteToEvent: AddNoteToEvent = useCallback( + ({ eventId, noteId }: { eventId: string; noteId: string }) => + addNoteToEvent!({ id, eventId, noteId }), + [id] + ); - const onColumnResized: OnColumnResized = ({ columnId, delta }) => - applyDeltaToColumnWidth!({ id, columnId, delta }); + const onColumnSorted: OnColumnSorted = useCallback( + sorted => { + updateSort!({ id, sort: sorted }); + }, + [id] + ); - const onPinEvent: OnPinEvent = eventId => pinEvent!({ id, eventId }); + const onColumnRemoved: OnColumnRemoved = useCallback( + columnId => removeColumn!({ id, columnId }), + [id] + ); - const onUnPinEvent: OnUnPinEvent = eventId => unPinEvent!({ id, eventId }); + const onColumnResized: OnColumnResized = useCallback( + ({ columnId, delta }) => applyDeltaToColumnWidth!({ id, columnId, delta }), + [id] + ); + + const onPinEvent: OnPinEvent = useCallback(eventId => pinEvent!({ id, eventId }), [id]); - const onUpdateNote: UpdateNote = (note: Note) => updateNote!({ note }); + const onUnPinEvent: OnUnPinEvent = useCallback(eventId => unPinEvent!({ id, eventId }), [id]); - const onUpdateColumns: OnUpdateColumns = columns => updateColumns!({ id, columns }); + const onUpdateNote: UpdateNote = useCallback((note: Note) => updateNote!({ note }), []); + + const onUpdateColumns: OnUpdateColumns = useCallback( + columns => updateColumns!({ id, columns }), + [id] + ); return ( ( prevProps.columnHeaders === nextProps.columnHeaders && prevProps.data === nextProps.data && prevProps.eventIdToNoteIds === nextProps.eventIdToNoteIds && - prevProps.getNotesByIds === nextProps.getNotesByIds && + prevProps.notesById === nextProps.notesById && prevProps.height === nextProps.height && prevProps.id === nextProps.id && prevProps.isEventViewer === nextProps.isEventViewer && @@ -194,7 +208,7 @@ const makeMapStateToProps = () => { return { columnHeaders: memoizedColumnHeaders(columns, browserFields), eventIdToNoteIds, - getNotesByIds: getNotesByIds(state), + notesById: getNotesByIds(state), id, pinnedEventIds, }; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx index 98cf0a78b1d1f..79f9c32a176f5 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx @@ -5,7 +5,7 @@ */ import { noop } from 'lodash/fp'; -import React, { useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { BrowserFields } from '../../../containers/source'; @@ -51,23 +51,23 @@ export const ProviderItemBadge = React.memo( }) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); - function togglePopover() { + const togglePopover = useCallback(() => { setIsPopoverOpen(!isPopoverOpen); - } + }, [isPopoverOpen]); - function closePopover() { + const closePopover = useCallback(() => { setIsPopoverOpen(false); - } + }, []); - function onToggleEnabledProvider() { + const onToggleEnabledProvider = useCallback(() => { toggleEnabledProvider(); closePopover(); - } + }, [toggleEnabledProvider]); - function onToggleExcludedProvider() { + const onToggleExcludedProvider = useCallback(() => { toggleExcludedProvider(); closePopover(); - } + }, [toggleExcludedProvider]); return ( diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/footer/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/footer/index.tsx index c1772d9e55577..a0942cbaba091 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/footer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/footer/index.tsx @@ -18,7 +18,7 @@ import { EuiToolTip, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { pure } from 'recompose'; import styled from 'styled-components'; @@ -182,14 +182,14 @@ export const Footer = React.memo( const [paginationLoading, setPaginationLoading] = useState(false); const [updatedAt, setUpdatedAt] = useState(null); - const loadMore = () => { + const loadMore = useCallback(() => { setPaginationLoading(true); onLoadMore(nextCursor, tieBreaker); - }; + }, [nextCursor, tieBreaker, onLoadMore]); - const onButtonClick = () => setIsPopoverOpen(!isPopoverOpen); + const onButtonClick = useCallback(() => setIsPopoverOpen(!isPopoverOpen), [isPopoverOpen]); - const closePopover = () => setIsPopoverOpen(false); + const closePopover = useCallback(() => setIsPopoverOpen(false), []); useEffect(() => { if (paginationLoading && !isLoading) { diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx index ab92f22a4c89f..78a9488b2fdbb 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx @@ -5,7 +5,7 @@ */ import { isEqual } from 'lodash/fp'; -import React, { useEffect } from 'react'; +import React, { useEffect, useCallback } from 'react'; import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; @@ -159,79 +159,84 @@ const StatefulTimelineComponent = React.memo( updateItemsPerPage, upsertColumn, }) => { - const onDataProviderRemoved: OnDataProviderRemoved = ( - providerId: string, - andProviderId?: string - ) => removeProvider!({ id, providerId, andProviderId }); + const onDataProviderRemoved: OnDataProviderRemoved = useCallback( + (providerId: string, andProviderId?: string) => + removeProvider!({ id, providerId, andProviderId }), + [id] + ); - const onToggleDataProviderEnabled: OnToggleDataProviderEnabled = ({ - providerId, - enabled, - andProviderId, - }) => - updateDataProviderEnabled!({ - id, - enabled, - providerId, - andProviderId, - }); + const onToggleDataProviderEnabled: OnToggleDataProviderEnabled = useCallback( + ({ providerId, enabled, andProviderId }) => + updateDataProviderEnabled!({ + id, + enabled, + providerId, + andProviderId, + }), + [id] + ); - const onToggleDataProviderExcluded: OnToggleDataProviderExcluded = ({ - providerId, - excluded, - andProviderId, - }) => - updateDataProviderExcluded!({ - id, - excluded, - providerId, - andProviderId, - }); + const onToggleDataProviderExcluded: OnToggleDataProviderExcluded = useCallback( + ({ providerId, excluded, andProviderId }) => + updateDataProviderExcluded!({ + id, + excluded, + providerId, + andProviderId, + }), + [id] + ); - const onDataProviderEditedLocal: OnDataProviderEdited = ({ - andProviderId, - excluded, - field, - operator, - providerId, - value, - }) => - onDataProviderEdited!({ - andProviderId, - excluded, - field, - id, - operator, - providerId, - value, - }); - const onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery = ({ providerId, kqlQuery }) => - updateDataProviderKqlQuery!({ id, kqlQuery, providerId }); + const onDataProviderEditedLocal: OnDataProviderEdited = useCallback( + ({ andProviderId, excluded, field, operator, providerId, value }) => + onDataProviderEdited!({ + andProviderId, + excluded, + field, + id, + operator, + providerId, + value, + }), + [id] + ); - const onChangeItemsPerPage: OnChangeItemsPerPage = itemsChangedPerPage => - updateItemsPerPage!({ id, itemsPerPage: itemsChangedPerPage }); + const onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery = useCallback( + ({ providerId, kqlQuery }) => updateDataProviderKqlQuery!({ id, kqlQuery, providerId }), + [id] + ); - const onChangeDroppableAndProvider: OnChangeDroppableAndProvider = providerId => - updateHighlightedDropAndProviderId!({ id, providerId }); + const onChangeItemsPerPage: OnChangeItemsPerPage = useCallback( + itemsChangedPerPage => updateItemsPerPage!({ id, itemsPerPage: itemsChangedPerPage }), + [id] + ); - const toggleColumn = (column: ColumnHeader) => { - const exists = columns.findIndex(c => c.id === column.id) !== -1; + const onChangeDroppableAndProvider: OnChangeDroppableAndProvider = useCallback( + providerId => updateHighlightedDropAndProviderId!({ id, providerId }), + [id] + ); - if (!exists && upsertColumn != null) { - upsertColumn({ - column, - id, - index: 1, - }); - } + const toggleColumn = useCallback( + (column: ColumnHeader) => { + const exists = columns.findIndex(c => c.id === column.id) !== -1; - if (exists && removeColumn != null) { - removeColumn({ - columnId: column.id, - id, - }); - } - }; + if (!exists && upsertColumn != null) { + upsertColumn({ + column, + id, + index: 1, + }); + } + + if (exists && removeColumn != null) { + removeColumn({ + columnId: column.id, + id, + }); + } + }, + [columns, id] + ); useEffect(() => { if (createTimeline != null) { diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx index b983963c34f55..111e31479932a 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/properties/index.tsx @@ -5,7 +5,7 @@ */ import { EuiAvatar, EuiFlexItem, EuiIcon } from '@elastic/eui'; -import React, { useState } from 'react'; +import React, { useState, useCallback } from 'react'; import styled, { injectGlobal } from 'styled-components'; import { Note } from '../../../lib/note'; @@ -114,17 +114,17 @@ export const Properties = React.memo( const [showActions, setShowActions] = useState(false); const [showNotes, setShowNotes] = useState(false); - const onButtonClick = () => { + const onButtonClick = useCallback(() => { setShowActions(!showActions); - }; + }, [showActions]); - const onToggleShowNotes = () => { + const onToggleShowNotes = useCallback(() => { setShowNotes(!showNotes); - }; + }, [showNotes]); - const onClosePopover = () => { + const onClosePopover = useCallback(() => { setShowActions(false); - }; + }, []); const datePickerWidth = width - diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx index 91113a545821d..0ebceccfa90c5 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx @@ -5,7 +5,7 @@ */ import { getOr } from 'lodash/fp'; -import * as React from 'react'; +import React, { useCallback } from 'react'; import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; import { StaticIndexPattern } from 'ui/index_patterns'; @@ -56,26 +56,32 @@ const StatefulSearchOrFilterComponent = React.memo( timelineId, updateKqlMode, }) => { - const applyFilterQueryFromKueryExpression = (expression: string) => - applyKqlFilterQuery({ - id: timelineId, - filterQuery: { - kuery: { + const applyFilterQueryFromKueryExpression = useCallback( + (expression: string) => + applyKqlFilterQuery({ + id: timelineId, + filterQuery: { + kuery: { + kind: 'kuery', + expression, + }, + serializedQuery: convertKueryToElasticSearchQuery(expression, indexPattern), + }, + }), + [indexPattern, timelineId] + ); + + const setFilterQueryDraftFromKueryExpression = useCallback( + (expression: string) => + setKqlFilterQueryDraft({ + id: timelineId, + filterQueryDraft: { kind: 'kuery', expression, }, - serializedQuery: convertKueryToElasticSearchQuery(expression, indexPattern), - }, - }); - - const setFilterQueryDraftFromKueryExpression = (expression: string) => - setKqlFilterQueryDraft({ - id: timelineId, - filterQueryDraft: { - kind: 'kuery', - expression, - }, - }); + }), + [timelineId] + ); return ( ( ({ alwaysShow = false, hoverContent, render }) => { const [showHoverContent, setShowHoverContent] = useState(false); - function onMouseEnter() { + const onMouseEnter = useCallback(() => { setShowHoverContent(true); - } + }, []); - function onMouseLeave() { + const onMouseLeave = useCallback(() => { setShowHoverContent(false); - } + }, []); + return ( <>{render(showHoverContent)} diff --git a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx index edd5740f62879..ff6e5e4d0c788 100644 --- a/x-pack/legacy/plugins/siem/public/containers/source/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/source/index.tsx @@ -57,30 +57,28 @@ interface WithSourceProps { sourceId: string; } -export const WithSource = React.memo(({ children, sourceId }) => { - const getIndexFields = (title: string, fields: IndexField[]): StaticIndexPattern => +const getIndexFields = memoizeOne( + (title: string, fields: IndexField[]): StaticIndexPattern => fields && fields.length > 0 ? { fields: fields.map(field => pick(['name', 'searchable', 'type', 'aggregatable'], field)), title, } - : { fields: [], title }; + : { fields: [], title } +); - const getBrowserFields = (fields: IndexField[]): BrowserFields => +const getBrowserFields = memoizeOne( + (fields: IndexField[]): BrowserFields => fields && fields.length > 0 ? fields.reduce( (accumulator: BrowserFields, field: IndexField) => set([field.category, 'fields', field.name], field, accumulator), {} ) - : {}; - const getBrowserFieldsMemo: (fields: IndexField[]) => BrowserFields = memoizeOne( - getBrowserFields - ); - const getIndexFieldsMemo: ( - title: string, - fields: IndexField[] - ) => StaticIndexPattern = memoizeOne(getIndexFields); + : {} +); + +export const WithSource = React.memo(({ children, sourceId }) => { return ( query={sourceQuery} @@ -94,8 +92,8 @@ export const WithSource = React.memo(({ children, sourceId }) = {({ data }) => children({ indicesExist: get('source.status.indicesExist', data), - browserFields: getBrowserFieldsMemo(get('source.status.indexFields', data)), - indexPattern: getIndexFieldsMemo( + browserFields: getBrowserFields(get('source.status.indexFields', data)), + indexPattern: getIndexFields( chrome .getUiSettingsClient() .get(DEFAULT_INDEX_KEY) diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/all/index.tsx b/x-pack/legacy/plugins/siem/public/containers/timeline/all/index.tsx index c3bff998fdefd..5ff28480f1b3f 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/all/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/all/index.tsx @@ -36,43 +36,43 @@ interface OwnProps extends AllTimelinesVariables { children?: (args: AllTimelinesArgs) => React.ReactNode; } -const getAllTimeline = (variables: string, timelines: TimelineResult[]): OpenTimelineResult[] => - timelines.map(timeline => ({ - created: timeline.created, - description: timeline.description, - eventIdToNoteIds: - timeline.eventIdToNoteIds != null - ? timeline.eventIdToNoteIds.reduce((acc, note) => { - if (note.eventId != null) { - const notes = getOr([], note.eventId, acc); - return { ...acc, [note.eventId]: [...notes, note.noteId] }; - } - return acc; - }, {}) - : null, - favorite: timeline.favorite, - noteIds: timeline.noteIds, - notes: - timeline.notes != null - ? timeline.notes.map(note => ({ ...note, savedObjectId: note.noteId })) - : null, - pinnedEventIds: - timeline.pinnedEventIds != null - ? timeline.pinnedEventIds.reduce( - (acc, pinnedEventId) => ({ ...acc, [pinnedEventId]: true }), - {} - ) - : null, - savedObjectId: timeline.savedObjectId, - title: timeline.title, - updated: timeline.updated, - updatedBy: timeline.updatedBy, - })); +const getAllTimeline = memoizeOne( + (variables: string, timelines: TimelineResult[]): OpenTimelineResult[] => + timelines.map(timeline => ({ + created: timeline.created, + description: timeline.description, + eventIdToNoteIds: + timeline.eventIdToNoteIds != null + ? timeline.eventIdToNoteIds.reduce((acc, note) => { + if (note.eventId != null) { + const notes = getOr([], note.eventId, acc); + return { ...acc, [note.eventId]: [...notes, note.noteId] }; + } + return acc; + }, {}) + : null, + favorite: timeline.favorite, + noteIds: timeline.noteIds, + notes: + timeline.notes != null + ? timeline.notes.map(note => ({ ...note, savedObjectId: note.noteId })) + : null, + pinnedEventIds: + timeline.pinnedEventIds != null + ? timeline.pinnedEventIds.reduce( + (acc, pinnedEventId) => ({ ...acc, [pinnedEventId]: true }), + {} + ) + : null, + savedObjectId: timeline.savedObjectId, + title: timeline.title, + updated: timeline.updated, + updatedBy: timeline.updatedBy, + })) +); export const AllTimelinesQuery = React.memo( ({ children, onlyUserFavorite, pageInfo, search, sort }) => { - const memoizedAllTimeline = memoizeOne(getAllTimeline); - const variables: GetAllTimeline.Variables = { onlyUserFavorite, pageInfo, @@ -90,7 +90,7 @@ export const AllTimelinesQuery = React.memo( return children!({ loading, totalCount: getOr(0, 'getAllTimeline.totalCount', data), - timelines: memoizedAllTimeline( + timelines: getAllTimeline( JSON.stringify(variables), getOr([], 'getAllTimeline.timeline', data) ), diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/details/index.tsx b/x-pack/legacy/plugins/siem/public/containers/timeline/details/index.tsx index 54dd44063f5da..cfb3f8bd8dc77 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/details/index.tsx @@ -28,11 +28,12 @@ export interface TimelineDetailsProps { sourceId: string; } +const getDetailsEvent = memoizeOne( + (variables: string, detail: DetailItem[]): DetailItem[] => detail +); + export const TimelineDetailsComponentQuery = React.memo( ({ children, indexName, eventId, executeQuery, sourceId }) => { - const getDetailsEvent = (variables: string, detail: DetailItem[]): DetailItem[] => detail; - const getDetailsEventMemo = memoizeOne(getDetailsEvent); - const variables: GetTimelineDetailsQuery.Variables = { sourceId, indexName, @@ -49,7 +50,7 @@ export const TimelineDetailsComponentQuery = React.memo( {({ data, loading, refetch }) => { return children!({ loading, - detailsData: getDetailsEventMemo( + detailsData: getDetailsEvent( JSON.stringify(variables), getOr([], 'source.TimelineDetails.data', data) ), diff --git a/x-pack/legacy/plugins/siem/public/store/app/selectors.ts b/x-pack/legacy/plugins/siem/public/store/app/selectors.ts index cc006b216da8e..9037583d278a7 100644 --- a/x-pack/legacy/plugins/siem/public/store/app/selectors.ts +++ b/x-pack/legacy/plugins/siem/public/store/app/selectors.ts @@ -17,14 +17,15 @@ const selectNotesById = (state: State): NotesById => state.app.notesById; const getErrors = (state: State): ErrorModel => state.app.errors; -const getNotes = (notesById: NotesById, noteIds: string[]) => +export const getNotes = memoizeOne((notesById: NotesById, noteIds: string[]): Note[] => keys(notesById).reduce((acc: Note[], noteId: string) => { if (noteIds.includes(noteId)) { const note: Note = notesById[noteId]; return [...acc, note]; } return acc; - }, []); + }, []) +); export const selectNotesByIdSelector = createSelector( selectNotesById, @@ -34,8 +35,7 @@ export const selectNotesByIdSelector = createSelector( export const notesByIdsSelector = () => createSelector( selectNotesById, - (notesById: NotesById) => - memoizeOne((noteIds: string[]): Note[] => getNotes(notesById, noteIds)) + (notesById: NotesById) => notesById ); export const errorsSelector = () => From 6deac56d583ef87ad5211e8d2e021f6799b6cc76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Casper=20H=C3=BCbertz?= Date: Fri, 25 Oct 2019 15:36:36 +0200 Subject: [PATCH 144/191] [APM] Update metadata order (#49313) Reordering the metadata sections for transactions, errors and spans. --- .../shared/MetadataTable/ErrorMetadata/sections.ts | 2 +- .../shared/MetadataTable/SpanMetadata/sections.ts | 8 ++++---- .../shared/MetadataTable/TransactionMetadata/sections.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts index 526bb4e5bcf71..1eeebc8543d72 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts +++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts @@ -20,8 +20,8 @@ import { } from '../sections'; export const ERROR_METADATA_SECTIONS: Section[] = [ - ERROR, { ...LABELS, required: true }, + ERROR, HTTP, HOST, CONTAINER, diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts index 01e56bdb09f19..7012bbcc8fcea 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts +++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts @@ -15,10 +15,10 @@ import { } from '../sections'; export const SPAN_METADATA_SECTIONS: Section[] = [ + LABELS, SPAN, - AGENT, - SERVICE, TRANSACTION, - LABELS, - TRACE + TRACE, + SERVICE, + AGENT ]; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts index 04a0d64077c15..6b30c82bc35a0 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts +++ b/x-pack/legacy/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts @@ -22,8 +22,8 @@ import { } from '../sections'; export const TRANSACTION_METADATA_SECTIONS: Section[] = [ - TRANSACTION, { ...LABELS, required: true }, + TRANSACTION, HTTP, HOST, CONTAINER, From f104e23b42fe75661e328d75846821e95ddd61f9 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Fri, 25 Oct 2019 15:44:59 +0200 Subject: [PATCH 145/191] [Discover] Centralize dependencies in kibana_services.ts (#48072) * Move doc folder to discover folder * Move doc_viewer folder to discover folder * Move context folder to discover folder * Move context scss import to discover folder * Introduce angular folder, start migration * Add basic NP structure, structural refactoring * Add context placeholder readme * Move doc_viewer directive to angular * Move doc_table directive to angular directory * Migrate doc_table dependencies to central file * Create kibana_services.ts * Centralize context deps * Centralize embeddable deps * Migrate context to angular folder * Add dependencies to kibana_services.ts, implement getServices function * Refactor SEARCH_EMBEDDABLE_TYPE to contants.ts * Fix tests --- .../__tests__/directives/discover_field.js | 1 - .../__tests__/directives/field_calculator.js | 1 - .../__tests__/directives/field_chooser.js | 1 - .../kibana/public/discover/_index.scss | 4 +- .../index.html => angular/context.html} | 0 .../{context/index.js => angular/context.js} | 16 +-- .../discover/{ => angular}/context/NOTES.md | 0 .../{ => angular}/context/_index.scss | 0 .../context/api/__tests__/_stubs.js | 2 +- .../context/api/__tests__/anchor.js | 0 .../context/api/__tests__/predecessors.js | 0 .../context/api/__tests__/successors.js | 0 .../{ => angular}/context/api/anchor.js | 5 +- .../{ => angular}/context/api/context.ts | 6 +- .../utils/__tests__/date_conversion.test.ts | 0 .../api/utils/__tests__/sorting.test.ts | 0 .../context/api/utils/date_conversion.ts | 0 .../api/utils/fetch_hits_in_interval.ts | 2 +- .../context/api/utils/generate_intervals.ts | 0 .../api/utils/get_es_query_search_after.ts | 0 .../context/api/utils/get_es_query_sort.ts | 0 .../context/api/utils/sorting.ts | 2 +- .../components/action_bar/_action_bar.scss | 0 .../context/components/action_bar/_index.scss | 0 .../components/action_bar/action_bar.test.tsx | 0 .../components/action_bar/action_bar.tsx | 0 .../action_bar/action_bar_directive.ts | 6 +- .../action_bar/action_bar_warning.tsx | 0 .../context/components/action_bar/index.ts | 0 .../{ => angular}/context/query/actions.js | 4 +- .../{ => angular}/context/query/constants.js | 0 .../{ => angular}/context/query/index.js | 0 .../{ => angular}/context/query/state.js | 0 .../query_parameters/__tests__/_utils.js | 0 .../__tests__/action_add_filter.js | 6 +- .../__tests__/action_set_predecessor_count.js | 0 .../__tests__/action_set_query_parameters.js | 0 .../__tests__/action_set_successor_count.js | 0 .../context/query_parameters/actions.js | 5 +- .../context/query_parameters/constants.ts | 0 .../context/query_parameters/index.js | 0 .../context/query_parameters/state.ts | 0 .../app.html => angular/context_app.html} | 0 .../app.js => angular/context_app.js} | 17 ++- .../discover/angular/directives/histogram.tsx | 14 +- .../discover/angular/directives/index.js | 7 +- .../discover/angular/directives/no_results.js | 5 +- .../angular/directives/no_results.test.js | 69 +++++----- .../directives/unsupported_index_pattern.js | 1 - .../{index.html => angular/discover.html} | 0 .../public/discover/angular/discover.js | 104 +++++++-------- .../{doc/index.html => angular/doc.html} | 0 .../discover/{doc/index.ts => angular/doc.ts} | 25 +++- .../doc_table/__tests__/actions/filter.js | 0 .../doc_table/__tests__/doc_table.js | 0 .../doc_table/__tests__/lib/get_sort.js | 0 .../doc_table/__tests__/lib/rows_headers.js | 0 .../{ => angular}/doc_table/_doc_table.scss | 0 .../{ => angular}/doc_table/_index.scss | 0 .../doc_table/actions/columns.ts | 0 .../{ => angular}/doc_table/actions/filter.js | 0 .../doc_table/components/_index.scss | 0 .../doc_table/components/_table_header.scss | 0 .../tool_bar_pager_buttons.test.tsx.snap | 0 .../tool_bar_pager_text.test.tsx.snap | 0 .../doc_table/components/pager/index.js | 6 +- .../pager/tool_bar_pager_buttons.test.tsx | 0 .../pager/tool_bar_pager_buttons.tsx | 0 .../pager/tool_bar_pager_text.test.tsx | 0 .../components/pager/tool_bar_pager_text.tsx | 0 .../doc_table/components/table_header.ts | 5 +- .../__snapshots__/table_header.test.tsx.snap | 0 .../components/table_header/helpers.tsx | 5 +- .../table_header/table_header.test.tsx | 2 +- .../components/table_header/table_header.tsx | 5 +- .../table_header/table_header_column.tsx | 3 - .../doc_table/components/table_row.js | 9 +- .../doc_table/components/table_row/_cell.scss | 0 .../components/table_row/_details.scss | 0 .../components/table_row/_index.scss | 0 .../doc_table/components/table_row/_open.scss | 0 .../doc_table/components/table_row/cell.html | 0 .../components/table_row/details.html | 0 .../doc_table/components/table_row/open.html | 0 .../table_row/truncate_by_height.html | 0 .../{ => angular}/doc_table/doc_table.html | 0 .../{ => angular}/doc_table/doc_table.js | 6 +- .../doc_table/doc_table_strings.js | 0 .../index.js => angular/doc_table/index.ts} | 0 .../doc_table/infinite_scroll.js | 5 +- .../{ => angular}/doc_table/lib/get_sort.d.ts | 2 +- .../{ => angular}/doc_table/lib/get_sort.js | 0 .../lib/get_sort_for_search_source.ts | 2 +- .../doc_table/lib/pager/index.js | 0 .../doc_table/lib/pager/pager.js | 0 .../doc_table/lib/pager/pager_factory.js | 4 +- .../doc_viewer.ts} | 6 +- .../doc_directive.ts => angular/index.ts} | 23 +--- .../{breadcrumbs.js => breadcrumbs.ts} | 10 +- .../components/fetch_error/fetch_error.js | 44 +++---- .../field_chooser/discover_field.js | 8 +- .../discover_field_search_directive.ts | 5 +- .../discover_index_pattern_directive.ts | 5 +- .../components/field_chooser/field_chooser.js | 12 +- .../field_chooser/string_progress_bar.js | 8 +- .../components/help_menu/help_menu.js | 5 +- .../components/help_menu/help_menu_util.js | 2 +- .../kibana/public/discover/context/README.md | 4 + .../kibana/public/discover/doc/doc.test.tsx | 31 ++++- .../kibana/public/discover/doc/doc.tsx | 10 +- .../public/discover/doc/use_es_doc_search.ts | 3 +- .../discover/doc_viewer/doc_viewer.test.tsx | 20 ++- .../public/discover/doc_viewer/doc_viewer.tsx | 35 ++--- .../doc_viewer/doc_viewer_render_tab.test.tsx | 2 +- .../doc_viewer/doc_viewer_render_tab.tsx | 2 +- .../discover/doc_viewer/doc_viewer_tab.tsx | 2 +- .../index.ts => embeddable/constants.ts} | 5 +- .../public/discover/embeddable/index.ts | 1 + .../discover/embeddable/search_embeddable.ts | 48 +++---- .../embeddable/search_embeddable_factory.ts | 31 +++-- .../public/discover/embeddable/types.ts | 4 +- .../discover/helpers/register_feature.ts | 41 ++++++ .../kibana/public/discover/index.js | 46 ------- .../kibana/public/discover/index.ts | 32 +++++ .../kibana/public/discover/kibana_services.ts | 121 ++++++++++++++++++ .../kibana/public/discover/plugin.ts | 60 +++++++++ .../discover/saved_searches/_saved_search.js | 10 +- .../saved_searches/saved_search_register.js | 4 +- .../discover/top_nav/open_search_panel.js | 3 +- .../top_nav/open_search_panel.test.js | 8 ++ .../kibana/public/discover/types.d.ts | 4 +- .../expression_types/embeddable_types.ts | 2 +- 132 files changed, 617 insertions(+), 397 deletions(-) rename src/legacy/core_plugins/kibana/public/discover/{context/index.html => angular/context.html} (100%) rename src/legacy/core_plugins/kibana/public/discover/{context/index.js => angular/context.js} (87%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/NOTES.md (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/_index.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/__tests__/_stubs.js (98%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/__tests__/anchor.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/__tests__/predecessors.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/__tests__/successors.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/anchor.js (95%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/context.ts (97%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/utils/__tests__/date_conversion.test.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/utils/__tests__/sorting.test.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/utils/date_conversion.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/utils/fetch_hits_in_interval.ts (97%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/utils/generate_intervals.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/utils/get_es_query_search_after.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/utils/get_es_query_sort.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/api/utils/sorting.ts (96%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/components/action_bar/_action_bar.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/components/action_bar/_index.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/components/action_bar/action_bar.test.tsx (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/components/action_bar/action_bar.tsx (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/components/action_bar/action_bar_directive.ts (89%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/components/action_bar/action_bar_warning.tsx (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/components/action_bar/index.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query/actions.js (97%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query/constants.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query/index.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query/state.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/__tests__/_utils.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/__tests__/action_add_filter.js (94%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/__tests__/action_set_predecessor_count.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/__tests__/action_set_query_parameters.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/__tests__/action_set_successor_count.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/actions.js (92%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/constants.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/index.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/context/query_parameters/state.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{context/app.html => angular/context_app.html} (100%) rename src/legacy/core_plugins/kibana/public/discover/{context/app.js => angular/context_app.js} (92%) rename src/legacy/core_plugins/kibana/public/discover/{index.html => angular/discover.html} (100%) rename src/legacy/core_plugins/kibana/public/discover/{doc/index.html => angular/doc.html} (100%) rename src/legacy/core_plugins/kibana/public/discover/{doc/index.ts => angular/doc.ts} (71%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/__tests__/actions/filter.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/__tests__/doc_table.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/__tests__/lib/get_sort.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/__tests__/lib/rows_headers.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/_doc_table.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/_index.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/actions/columns.ts (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/actions/filter.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/_index.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/_table_header.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/pager/index.js (91%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/pager/tool_bar_pager_buttons.test.tsx (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/pager/tool_bar_pager_buttons.tsx (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/pager/tool_bar_pager_text.test.tsx (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/pager/tool_bar_pager_text.tsx (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_header.ts (93%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_header/helpers.tsx (94%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_header/table_header.test.tsx (98%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_header/table_header.tsx (91%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_header/table_header_column.tsx (98%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row.js (96%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row/_cell.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row/_details.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row/_index.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row/_open.scss (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row/cell.html (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row/details.html (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row/open.html (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/components/table_row/truncate_by_height.html (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/doc_table.html (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/doc_table.js (95%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/doc_table_strings.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{doc_table/index.js => angular/doc_table/index.ts} (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/infinite_scroll.js (94%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/lib/get_sort.d.ts (94%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/lib/get_sort.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/lib/get_sort_for_search_source.ts (96%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/lib/pager/index.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/lib/pager/pager.js (100%) rename src/legacy/core_plugins/kibana/public/discover/{ => angular}/doc_table/lib/pager/pager_factory.js (89%) rename src/legacy/core_plugins/kibana/public/discover/{doc_viewer/doc_viewer_directive.ts => angular/doc_viewer.ts} (90%) rename src/legacy/core_plugins/kibana/public/discover/{doc/doc_directive.ts => angular/index.ts} (58%) rename src/legacy/core_plugins/kibana/public/discover/{breadcrumbs.js => breadcrumbs.ts} (88%) create mode 100644 src/legacy/core_plugins/kibana/public/discover/context/README.md rename src/legacy/core_plugins/kibana/public/discover/{doc_viewer/index.ts => embeddable/constants.ts} (92%) create mode 100644 src/legacy/core_plugins/kibana/public/discover/helpers/register_feature.ts delete mode 100644 src/legacy/core_plugins/kibana/public/discover/index.js create mode 100644 src/legacy/core_plugins/kibana/public/discover/index.ts create mode 100644 src/legacy/core_plugins/kibana/public/discover/kibana_services.ts create mode 100644 src/legacy/core_plugins/kibana/public/discover/plugin.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js index 5e8cfc8e1609c..9ac76bfcfe04e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/discover_field.js @@ -23,7 +23,6 @@ import _ from 'lodash'; import sinon from 'sinon'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; -import 'ui/private'; import '../../components/field_chooser/discover_field'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js index 3130ac29eb84d..3ddee3495f36d 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_calculator.js @@ -22,7 +22,6 @@ import _ from 'lodash'; import ngMock from 'ng_mock'; import { fieldCalculator } from '../../components/field_chooser/lib/field_calculator'; import expect from '@kbn/expect'; -import 'ui/private'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; // Load the kibana app dependencies. diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js index c2be750ec7f63..a5b55e50eb90e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js +++ b/src/legacy/core_plugins/kibana/public/discover/__tests__/directives/field_chooser.js @@ -23,7 +23,6 @@ import _ from 'lodash'; import sinon from 'sinon'; import expect from '@kbn/expect'; import $ from 'jquery'; -import 'ui/private'; import '../../components/field_chooser/field_chooser'; import FixturesHitsProvider from 'fixtures/hits'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; diff --git a/src/legacy/core_plugins/kibana/public/discover/_index.scss b/src/legacy/core_plugins/kibana/public/discover/_index.scss index 0b0bd12cb268b..b311dd8a34778 100644 --- a/src/legacy/core_plugins/kibana/public/discover/_index.scss +++ b/src/legacy/core_plugins/kibana/public/discover/_index.scss @@ -11,7 +11,7 @@ @import 'components/fetch_error/index'; @import 'components/field_chooser/index'; @import 'angular/directives/index'; -@import 'doc_table/index'; +@import 'angular/doc_table/index'; @import 'hacks'; @@ -23,4 +23,4 @@ @import 'doc_viewer/index'; // Context styles -@import 'context/index'; +@import 'angular/context/index'; diff --git a/src/legacy/core_plugins/kibana/public/discover/context/index.html b/src/legacy/core_plugins/kibana/public/discover/angular/context.html similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/index.html rename to src/legacy/core_plugins/kibana/public/discover/angular/context.html diff --git a/src/legacy/core_plugins/kibana/public/discover/context/index.js b/src/legacy/core_plugins/kibana/public/discover/angular/context.js similarity index 87% rename from src/legacy/core_plugins/kibana/public/discover/context/index.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context.js index 902bee2badb7c..58d1626ca4b14 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/index.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context.js @@ -18,16 +18,13 @@ */ import _ from 'lodash'; - -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; -import uiRoutes from 'ui/routes'; import { i18n } from '@kbn/i18n'; +import { getServices, subscribeWithScope } from './../kibana_services'; -import './app'; -import contextAppRouteTemplate from './index.html'; +import './context_app'; +import contextAppRouteTemplate from './context.html'; import { getRootBreadcrumbs } from '../breadcrumbs'; -import { npStart } from 'ui/new_platform'; -import { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; +const { FilterBarQueryFilterProvider, uiRoutes, chrome } = getServices(); const k7Breadcrumbs = $route => { const { indexPattern } = $route.current.locals; @@ -47,12 +44,11 @@ const k7Breadcrumbs = $route => { ]; }; - uiRoutes // deprecated route, kept for compatibility // should be removed in the future .when('/context/:indexPatternId/:type/:id*', { - redirectTo: '/context/:indexPatternId/:id' + redirectTo: '/context/:indexPatternId/:id', }) .when('/context/:indexPatternId/:id*', { controller: ContextAppRouteController, @@ -92,7 +88,7 @@ function ContextAppRouteController($routeParams, $scope, AppState, config, index }); this.anchorId = $routeParams.id; this.indexPattern = indexPattern; - this.discoverUrl = npStart.core.chrome.navLinks.get('kibana:discover').url; + this.discoverUrl = chrome.navLinks.get('kibana:discover').url; this.filters = _.cloneDeep(queryFilter.getFilters()); } diff --git a/src/legacy/core_plugins/kibana/public/discover/context/NOTES.md b/src/legacy/core_plugins/kibana/public/discover/angular/context/NOTES.md similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/NOTES.md rename to src/legacy/core_plugins/kibana/public/discover/angular/context/NOTES.md diff --git a/src/legacy/core_plugins/kibana/public/discover/context/_index.scss b/src/legacy/core_plugins/kibana/public/discover/angular/context/_index.scss similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/_index.scss rename to src/legacy/core_plugins/kibana/public/discover/angular/context/_index.scss diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/_stubs.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/_stubs.js similarity index 98% rename from src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/_stubs.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/_stubs.js index ecb22b20e4d86..f472ff9250eb5 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/_stubs.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/_stubs.js @@ -19,7 +19,7 @@ import sinon from 'sinon'; import moment from 'moment'; -import { SearchSource } from 'ui/courier'; +import { SearchSource } from '../../../../kibana_services'; export function createIndexPatternsStub() { return { diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/anchor.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/anchor.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/anchor.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/anchor.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/predecessors.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/predecessors.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/predecessors.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/predecessors.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/successors.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/successors.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/__tests__/successors.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/__tests__/successors.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/anchor.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/anchor.js similarity index 95% rename from src/legacy/core_plugins/kibana/public/discover/context/api/anchor.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/anchor.js index 02a309eaa0165..62bbc6166662f 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/api/anchor.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/anchor.js @@ -18,11 +18,10 @@ */ import _ from 'lodash'; - import { i18n } from '@kbn/i18n'; +import { getServices } from '../../../kibana_services'; -import { SearchSource } from 'ui/courier'; - +const { SearchSource } = getServices(); export function fetchAnchorProvider(indexPatterns) { return async function fetchAnchor( indexPatternId, diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/context.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts similarity index 97% rename from src/legacy/core_plugins/kibana/public/discover/context/api/context.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts index 48ac59f1f0855..268f176f2c61e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/api/context.ts +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/context.ts @@ -17,10 +17,8 @@ * under the License. */ -// @ts-ignore -import { SearchSource } from 'ui/courier'; import { Filter } from '@kbn/es-query'; -import { IndexPatterns, IndexPattern } from 'ui/index_patterns'; +import { IndexPatterns, IndexPattern, getServices } from '../../../kibana_services'; import { reverseSortDir, SortDirection } from './utils/sorting'; import { extractNanos, convertIsoToMillis } from './utils/date_conversion'; import { fetchHitsInInterval } from './utils/fetch_hits_in_interval'; @@ -36,6 +34,8 @@ export interface EsHitRecord { } export type EsHitRecordList = EsHitRecord[]; +const { SearchSource } = getServices(); + const DAY_MILLIS = 24 * 60 * 60 * 1000; // look from 1 day up to 10000 days into the past and future diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/__tests__/date_conversion.test.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/__tests__/date_conversion.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/utils/__tests__/date_conversion.test.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/__tests__/date_conversion.test.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/__tests__/sorting.test.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/__tests__/sorting.test.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/utils/__tests__/sorting.test.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/__tests__/sorting.test.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/date_conversion.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/date_conversion.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/utils/date_conversion.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/date_conversion.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/fetch_hits_in_interval.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/fetch_hits_in_interval.ts similarity index 97% rename from src/legacy/core_plugins/kibana/public/discover/context/api/utils/fetch_hits_in_interval.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/fetch_hits_in_interval.ts index 9a5436b59714d..2810e5d9d7e66 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/fetch_hits_in_interval.ts +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/fetch_hits_in_interval.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { SearchSource } from 'ui/courier'; +import { SearchSource } from '../../../../kibana_services'; import { convertTimeValueToIso } from './date_conversion'; import { SortDirection } from './sorting'; import { EsHitRecordList } from '../context'; diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/generate_intervals.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/generate_intervals.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/utils/generate_intervals.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/generate_intervals.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/get_es_query_search_after.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/get_es_query_search_after.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/utils/get_es_query_search_after.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/get_es_query_search_after.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/get_es_query_sort.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/get_es_query_sort.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/api/utils/get_es_query_sort.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/get_es_query_sort.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/sorting.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/sorting.ts similarity index 96% rename from src/legacy/core_plugins/kibana/public/discover/context/api/utils/sorting.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/sorting.ts index b673270d7a645..4a0f531845f46 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/api/utils/sorting.ts +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/api/utils/sorting.ts @@ -17,7 +17,7 @@ * under the License. */ -import { IndexPattern } from 'src/legacy/core_plugins/data/public'; +import { IndexPattern } from '../../../../kibana_services'; export enum SortDirection { asc = 'asc', diff --git a/src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/_action_bar.scss b/src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/_action_bar.scss similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/_action_bar.scss rename to src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/_action_bar.scss diff --git a/src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/_index.scss b/src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/_index.scss similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/_index.scss rename to src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/_index.scss diff --git a/src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar.test.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar.test.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar.tsx diff --git a/src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar_directive.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar_directive.ts similarity index 89% rename from src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar_directive.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar_directive.ts index 0942539e63785..579d9d95c6f71 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar_directive.ts +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar_directive.ts @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -// @ts-ignore -import { uiModules } from 'ui/modules'; -import { wrapInI18nContext } from 'ui/i18n'; +import { getServices } from '../../../../kibana_services'; import { ActionBar } from './action_bar'; +const { uiModules, wrapInI18nContext } = getServices(); + uiModules.get('apps/context').directive('contextActionBar', function(reactDirective: any) { return reactDirective(wrapInI18nContext(ActionBar)); }); diff --git a/src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar_warning.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar_warning.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/action_bar_warning.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/action_bar_warning.tsx diff --git a/src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/index.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/index.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/components/action_bar/index.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/components/action_bar/index.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query/actions.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query/actions.js similarity index 97% rename from src/legacy/core_plugins/kibana/public/discover/context/query/actions.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query/actions.js index c55dcc374fa5a..b88e54379f448 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/query/actions.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/query/actions.js @@ -20,13 +20,13 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { toastNotifications } from 'ui/notify'; +import { toastNotifications } from '../../../kibana_services'; import { fetchAnchorProvider } from '../api/anchor'; import { fetchContextProvider } from '../api/context'; import { QueryParameterActionsProvider } from '../query_parameters'; import { FAILURE_REASONS, LOADING_STATUS } from './constants'; -import { MarkdownSimple } from '../../../../../kibana_react/public'; +import { MarkdownSimple } from '../../../../../../kibana_react/public'; export function QueryActionsProvider(Private, Promise) { const fetchAnchor = Private(fetchAnchorProvider); diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query/constants.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query/constants.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query/constants.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query/constants.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query/index.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query/index.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query/index.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query/index.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query/state.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query/state.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query/state.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query/state.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/_utils.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/_utils.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/_utils.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/_utils.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_add_filter.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_add_filter.js similarity index 94% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_add_filter.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_add_filter.js index 1c96cbeec04a3..b136b03bd500b 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_add_filter.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_add_filter.js @@ -20,9 +20,7 @@ import expect from '@kbn/expect'; import ngMock from 'ng_mock'; import sinon from 'sinon'; - -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; - +import { getServices } from '../../../../kibana_services'; import { createStateStub } from './_utils'; import { QueryParameterActionsProvider } from '../actions'; @@ -36,7 +34,7 @@ describe('context app', function () { beforeEach(ngMock.inject(function createPrivateStubs(Private) { filterManagerStub = createQueryFilterStub(); - Private.stub(FilterBarQueryFilterProvider, filterManagerStub); + Private.stub(getServices().FilterBarQueryFilterProvider, filterManagerStub); addFilter = Private(QueryParameterActionsProvider).addFilter; })); diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_set_predecessor_count.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_set_predecessor_count.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_set_predecessor_count.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_set_predecessor_count.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_set_query_parameters.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_set_query_parameters.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_set_query_parameters.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_set_query_parameters.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_set_successor_count.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_set_successor_count.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/__tests__/action_set_successor_count.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/__tests__/action_set_successor_count.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/actions.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/actions.js similarity index 92% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/actions.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/actions.js index 1c895b8d9e1c5..9f7b180e8fe7d 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/actions.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/actions.js @@ -18,9 +18,8 @@ */ import _ from 'lodash'; +import { getServices, getFilterGenerator } from '../../../kibana_services'; -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; -import { getFilterGenerator } from 'ui/filter_manager'; import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE, @@ -29,7 +28,7 @@ import { export function QueryParameterActionsProvider(indexPatterns, Private) { - const queryFilter = Private(FilterBarQueryFilterProvider); + const queryFilter = Private(getServices().FilterBarQueryFilterProvider); const filterGen = getFilterGenerator(queryFilter); const setPredecessorCount = (state) => (predecessorCount) => ( diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/constants.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/constants.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/constants.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/constants.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/index.js b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/index.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/index.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/index.js diff --git a/src/legacy/core_plugins/kibana/public/discover/context/query_parameters/state.ts b/src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/state.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/query_parameters/state.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/context/query_parameters/state.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/context/app.html b/src/legacy/core_plugins/kibana/public/discover/angular/context_app.html similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/context/app.html rename to src/legacy/core_plugins/kibana/public/discover/angular/context_app.html diff --git a/src/legacy/core_plugins/kibana/public/discover/context/app.js b/src/legacy/core_plugins/kibana/public/discover/angular/context_app.js similarity index 92% rename from src/legacy/core_plugins/kibana/public/discover/context/app.js rename to src/legacy/core_plugins/kibana/public/discover/angular/context_app.js index 7754f743632cb..c9856ad794952 100644 --- a/src/legacy/core_plugins/kibana/public/discover/context/app.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/context_app.js @@ -18,24 +18,23 @@ */ import _ from 'lodash'; - -import { callAfterBindingsWorkaround } from 'ui/compat'; -import { uiModules } from 'ui/modules'; -import contextAppTemplate from './app.html'; -import './components/action_bar'; -import { getFirstSortableField } from './api/utils/sorting'; +import { getServices, callAfterBindingsWorkaround } from './../kibana_services'; +import contextAppTemplate from './context_app.html'; +import './context/components/action_bar'; +import { getFirstSortableField } from './context/api/utils/sorting'; import { createInitialQueryParametersState, QueryParameterActionsProvider, QUERY_PARAMETER_KEYS, -} from './query_parameters'; +} from './context/query_parameters'; import { createInitialLoadingStatusState, FAILURE_REASONS, LOADING_STATUS, QueryActionsProvider, -} from './query'; -import { timefilter } from 'ui/timefilter'; +} from './context/query'; + +const { uiModules, timefilter } = getServices(); // load directives import '../../../../data/public/legacy'; diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/directives/histogram.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/directives/histogram.tsx index 0dca912653f6c..ab336396b5bed 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/directives/histogram.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/angular/directives/histogram.tsx @@ -23,7 +23,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import lightEuiTheme from '@elastic/eui/dist/eui_theme_light.json'; import darkEuiTheme from '@elastic/eui/dist/eui_theme_dark.json'; -import { npStart } from 'ui/new_platform'; import { AnnotationDomainTypes, @@ -44,12 +43,9 @@ import { } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; - -import chrome from 'ui/chrome'; -// @ts-ignore: path dynamic for kibana -import { timezoneProvider } from 'ui/vis/lib/timezone'; import { EuiChartThemeType } from '@elastic/eui/src/themes/charts/themes'; import { Subscription } from 'rxjs'; +import { getServices, timezoneProvider } from '../../kibana_services'; export interface DiscoverHistogramProps { chartData: any; @@ -68,12 +64,12 @@ export class DiscoverHistogram extends Component this.setState({ chartsTheme })); } @@ -145,7 +141,7 @@ export class DiscoverHistogram extends Component diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/directives/no_results.js b/src/legacy/core_plugins/kibana/public/discover/angular/directives/no_results.js index 5f6d32681b50e..b5d3e8a5a01ca 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/directives/no_results.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/directives/no_results.js @@ -32,6 +32,7 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { getServices } from '../../kibana_services'; // eslint-disable-next-line react/prefer-stateless-function export class DiscoverNoResults extends Component { @@ -39,7 +40,6 @@ export class DiscoverNoResults extends Component { shardFailures: PropTypes.array, timeFieldName: PropTypes.string, queryLanguage: PropTypes.string, - getDocLink: PropTypes.func.isRequired, }; render() { @@ -47,7 +47,6 @@ export class DiscoverNoResults extends Component { shardFailures, timeFieldName, queryLanguage, - getDocLink, } = this.props; let shardFailuresMessage; @@ -226,7 +225,7 @@ export class DiscoverNoResults extends Component { queryStringSyntaxLink: ( { + return { + getServices: () => ({ + docLinks: { + links: { + query: { + luceneQuerySyntax: 'documentation-link', + }, + }, + }, + }), + }; +}); + +beforeEach(() => { + jest.clearAllMocks(); +}); describe('DiscoverNoResults', () => { describe('props', () => { describe('shardFailures', () => { test('renders failures list when there are failures', () => { - const shardFailures = [{ - index: 'A', - shard: '1', - reason: { reason: 'Awful error' }, - }, { - index: 'B', - shard: '2', - reason: { reason: 'Bad error' }, - }]; + const shardFailures = [ + { + index: 'A', + shard: '1', + reason: { reason: 'Awful error' }, + }, + { + index: 'B', + shard: '2', + reason: { reason: 'Bad error' }, + }, + ]; - const component = renderWithIntl( - ''} - /> - ); + const component = renderWithIntl(); expect(component).toMatchSnapshot(); }); @@ -51,12 +65,7 @@ describe('DiscoverNoResults', () => { test(`doesn't render failures list when there are no failures`, () => { const shardFailures = []; - const component = renderWithIntl( - ''} - /> - ); + const component = renderWithIntl(); expect(component).toMatchSnapshot(); }); @@ -64,12 +73,7 @@ describe('DiscoverNoResults', () => { describe('timeFieldName', () => { test('renders time range feedback', () => { - const component = renderWithIntl( - ''} - /> - ); + const component = renderWithIntl(); expect(component).toMatchSnapshot(); }); @@ -78,10 +82,7 @@ describe('DiscoverNoResults', () => { describe('queryLanguage', () => { test('supports lucene and renders doc link', () => { const component = renderWithIntl( - 'documentation-link'} - /> + 'documentation-link'} /> ); expect(component).toMatchSnapshot(); diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/directives/unsupported_index_pattern.js b/src/legacy/core_plugins/kibana/public/discover/angular/directives/unsupported_index_pattern.js index ac26203dafc4a..b1c1c47e39291 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/directives/unsupported_index_pattern.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/directives/unsupported_index_pattern.js @@ -18,7 +18,6 @@ */ import React, { Fragment } from 'react'; - import { EuiCallOut, EuiFlexGroup, diff --git a/src/legacy/core_plugins/kibana/public/discover/index.html b/src/legacy/core_plugins/kibana/public/discover/angular/discover.html similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/index.html rename to src/legacy/core_plugins/kibana/public/discover/angular/discover.html diff --git a/src/legacy/core_plugins/kibana/public/discover/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/angular/discover.js index 840152fc40ced..ed5049aa912e0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/discover.js @@ -18,63 +18,65 @@ */ import _ from 'lodash'; -import { i18n } from '@kbn/i18n'; import React from 'react'; -import angular from 'angular'; import { Subscription } from 'rxjs'; import moment from 'moment'; -import chrome from 'ui/chrome'; import dateMath from '@elastic/datemath'; +import { i18n } from '@kbn/i18n'; +import '../saved_searches/saved_searches'; +import '../components/field_chooser/field_chooser'; // doc table -import '../doc_table'; -import { getSort } from '../doc_table/lib/get_sort'; -import { getSortForSearchSource } from '../doc_table/lib/get_sort_for_search_source'; -import * as columnActions from '../doc_table/actions/columns'; -import * as filterActions from '../doc_table/actions/filter'; - -import 'ui/directives/listen'; -import 'ui/visualize'; -import 'ui/fixed_scroll'; -import 'ui/index_patterns'; -import 'ui/state_management/app_state'; -import { timefilter } from 'ui/timefilter'; -import { hasSearchStategyForIndexPattern, isDefaultTypeIndexPattern } from 'ui/courier'; -import { toastNotifications } from 'ui/notify'; -import { VisProvider } from 'ui/vis'; -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; -import { vislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; -import { docTitle } from 'ui/doc_title'; -import { intervalOptions } from 'ui/agg_types/buckets/_interval_options'; -import { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; -import uiRoutes from 'ui/routes'; -import { uiModules } from 'ui/modules'; -import indexTemplate from '../index.html'; -import { StateProvider } from 'ui/state_management/state'; -import { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; -import { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; -import { getFilterGenerator } from 'ui/filter_manager'; - -import { getDocLink } from 'ui/documentation_links'; -import '../components/fetch_error'; -import { getPainlessError } from './get_painless_error'; -import { showShareContextMenu, ShareContextMenuExtensionsRegistryProvider } from 'ui/share'; -import { getUnhashableStatesProvider } from 'ui/state_management/state_hashing'; -import { Inspector } from 'ui/inspector'; -import { RequestAdapter } from 'ui/inspector/adapters'; -import { getRequestInspectorStats, getResponseInspectorStats } from 'ui/courier/utils/courier_inspector_utils'; +import './doc_table'; +import { getSort } from './doc_table/lib/get_sort'; +import { getSortForSearchSource } from './doc_table/lib/get_sort_for_search_source'; +import * as columnActions from './doc_table/actions/columns'; +import * as filterActions from './doc_table/actions/filter'; + +import indexTemplate from './discover.html'; import { showOpenSearchPanel } from '../top_nav/show_open_search_panel'; -import { tabifyAggResponse } from 'ui/agg_response/tabify'; -import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; -import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; -import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../breadcrumbs'; -import { buildVislibDimensions } from 'ui/visualize/loader/pipeline_helpers/build_pipeline'; -import 'ui/capabilities/route_setup'; import { addHelpMenuToAppChrome } from '../components/help_menu/help_menu_util'; +import '../components/fetch_error'; +import { getPainlessError } from './get_painless_error'; +import { + angular, + buildVislibDimensions, + getFilterGenerator, + getRequestInspectorStats, + getResponseInspectorStats, + getServices, + getUnhashableStatesProvider, + hasSearchStategyForIndexPattern, + intervalOptions, + isDefaultTypeIndexPattern, + migrateLegacyQuery, + RequestAdapter, + showSaveModal, + showShareContextMenu, + stateMonitorFactory, + subscribeWithScope, + tabifyAggResponse, + vislibSeriesResponseHandlerProvider, + VisProvider, + SavedObjectSaveModal, +} from '../kibana_services'; + +const { + chrome, + docTitle, + FilterBarQueryFilterProvider, + ShareContextMenuExtensionsRegistryProvider, + StateProvider, + timefilter, + toastNotifications, + uiModules, + uiRoutes, +} = getServices(); +import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../breadcrumbs'; import { extractTimeFilter, changeTimeFilter } from '../../../../data/public'; import { start as data } from '../../../../data/public/legacy'; -import { npStart } from 'ui/new_platform'; + const { savedQueryService } = data.search.services; @@ -151,7 +153,7 @@ uiRoutes return savedSearches.get(savedSearchId) .then((savedSearch) => { if (savedSearchId) { - npStart.core.chrome.recentlyAccessed.add( + chrome.recentlyAccessed.add( savedSearch.getFullPath(), savedSearch.title, savedSearchId); @@ -211,8 +213,6 @@ function discoverController( mode: 'absolute', }); }; - - $scope.getDocLink = getDocLink; $scope.intervalOptions = intervalOptions; $scope.showInterval = false; $scope.minimumVisibleRows = 50; @@ -354,7 +354,7 @@ function discoverController( }), testId: 'openInspectorButton', run() { - Inspector.open(inspectorAdapters, { + getServices().inspector.open(inspectorAdapters, { title: savedSearch.title }); } @@ -401,12 +401,12 @@ function discoverController( }); if (savedSearch.id && savedSearch.title) { - chrome.breadcrumbs.set([{ + chrome.setBreadcrumbs([{ text: discoverBreadcrumbsTitle, href: '#/discover', }, { text: savedSearch.title }]); } else { - chrome.breadcrumbs.set([{ + chrome.setBreadcrumbs([{ text: discoverBreadcrumbsTitle, }]); } diff --git a/src/legacy/core_plugins/kibana/public/discover/doc/index.html b/src/legacy/core_plugins/kibana/public/discover/angular/doc.html similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc/index.html rename to src/legacy/core_plugins/kibana/public/discover/angular/doc.html diff --git a/src/legacy/core_plugins/kibana/public/discover/doc/index.ts b/src/legacy/core_plugins/kibana/public/discover/angular/doc.ts similarity index 71% rename from src/legacy/core_plugins/kibana/public/discover/doc/index.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/doc.ts index b969bd6a48126..e6c890c9a66a2 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc/index.ts +++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc.ts @@ -16,14 +16,25 @@ * specific language governing permissions and limitations * under the License. */ -import uiRoutes from 'ui/routes'; -import { IndexPatterns } from 'ui/index_patterns'; -import { timefilter } from 'ui/timefilter'; +import { getServices, IndexPatterns } from '../kibana_services'; // @ts-ignore -import { getRootBreadcrumbs } from 'plugins/kibana/discover/breadcrumbs'; -// @ts-ignore -import html from './index.html'; -import './doc_directive'; +import { getRootBreadcrumbs } from '../breadcrumbs'; +import html from './doc.html'; +import { Doc } from '../doc/doc'; +const { uiRoutes, uiModules, wrapInI18nContext, timefilter } = getServices(); +uiModules.get('apps/discover').directive('discoverDoc', function(reactDirective: any) { + return reactDirective( + wrapInI18nContext(Doc), + [ + ['id', { watchDepth: 'value' }], + ['index', { watchDepth: 'value' }], + ['indexPatternId', { watchDepth: 'reference' }], + ['indexPatternService', { watchDepth: 'reference' }], + ['esClient', { watchDepth: 'reference' }], + ], + { restrict: 'E' } + ); +}); uiRoutes // the old, pre 8.0 route, no longer used, keep it to stay compatible diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/actions/filter.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/actions/filter.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/actions/filter.js rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/actions/filter.js diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/doc_table.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/doc_table.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/doc_table.js rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/doc_table.js diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/lib/get_sort.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/lib/get_sort.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/lib/get_sort.js rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/lib/get_sort.js diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/lib/rows_headers.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/lib/rows_headers.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/lib/rows_headers.js rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/__tests__/lib/rows_headers.js diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/_doc_table.scss b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/_doc_table.scss similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/_doc_table.scss rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/_doc_table.scss diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/_index.scss b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/_index.scss similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/_index.scss rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/_index.scss diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/actions/columns.ts b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/actions/columns.ts similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/actions/columns.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/actions/columns.ts diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/actions/filter.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/actions/filter.js similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/actions/filter.js rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/actions/filter.js diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/_index.scss b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/_index.scss similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/_index.scss rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/_index.scss diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/_table_header.scss b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/_table_header.scss similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/_table_header.scss rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/_table_header.scss diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/index.js b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/index.js similarity index 91% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/index.js rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/index.js index e6d638d88bc27..7462de544dbce 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/index.js +++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/index.js @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - -import { uiModules } from 'ui/modules'; +import { getServices } from '../../../../kibana_services'; import { ToolBarPagerText } from './tool_bar_pager_text'; import { ToolBarPagerButtons } from './tool_bar_pager_buttons'; -import { wrapInI18nContext } from 'ui/i18n'; + +const { wrapInI18nContext, uiModules } = getServices(); const app = uiModules.get('kibana'); diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/tool_bar_pager_buttons.test.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_buttons.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/tool_bar_pager_buttons.test.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_buttons.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/tool_bar_pager_buttons.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/tool_bar_pager_buttons.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/tool_bar_pager_text.test.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_text.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/tool_bar_pager_text.test.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_text.test.tsx diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/tool_bar_pager_text.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_text.tsx similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/pager/tool_bar_pager_text.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/pager/tool_bar_pager_text.tsx diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header.ts b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header.ts similarity index 93% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header.ts index e054120c08474..f447c54507729 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header.ts +++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header.ts @@ -17,10 +17,9 @@ * under the License. */ import { wrapInI18nContext } from 'ui/i18n'; -// @ts-ignore -import { uiModules } from 'ui/modules'; +import { getServices } from '../../../kibana_services'; import { TableHeader } from './table_header/table_header'; -const module = uiModules.get('app/discover'); +const module = getServices().uiModules.get('app/discover'); module.directive('kbnTableHeader', function(reactDirective: any, config: any) { return reactDirective( diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap similarity index 100% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/helpers.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/helpers.tsx similarity index 94% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/helpers.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/helpers.tsx index ddf960091d476..80f963c8ccb3e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/helpers.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/helpers.tsx @@ -16,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - -import { IndexPattern } from 'ui/index_patterns'; +import { IndexPattern } from '../../../../kibana_services'; // @ts-ignore -import { shortenDottedString } from '../../../../../common/utils/shorten_dotted_string'; +import { shortenDottedString } from '../../../../../../common/utils/shorten_dotted_string'; export type SortOrder = [string, 'asc' | 'desc']; export interface ColumnProps { diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header.test.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/table_header.test.tsx similarity index 98% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header.test.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/table_header.test.tsx index ea2c65b1b8487..09ba77c7c4999 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/table_header.test.tsx @@ -23,7 +23,7 @@ import { TableHeader } from './table_header'; // @ts-ignore import { findTestSubject } from '@elastic/eui/lib/test'; import { SortOrder } from './helpers'; -import { IndexPattern, FieldType } from 'ui/index_patterns'; +import { IndexPattern, FieldType } from '../../../../kibana_services'; function getMockIndexPattern() { return ({ diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header.tsx b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/table_header.tsx similarity index 91% rename from src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header.tsx rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/table_header.tsx index abc8077afb669..71674710ac855 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_table/components/table_header/table_header.tsx @@ -17,9 +17,8 @@ * under the License. */ import React from 'react'; -import { IndexPattern } from 'ui/index_patterns'; +import { IndexPattern } from '../../../../kibana_services'; // @ts-ignore -import { shortenDottedString } from '../../../../../common/utils/shorten_dotted_string'; import { TableHeaderColumn } from './table_header_column'; import { SortOrder, getDisplayedColumns } from './helpers'; @@ -48,7 +47,7 @@ export function TableHeader({ return ( - + {displayedColumns.map(col => { return ( { return { diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_directive.ts b/src/legacy/core_plugins/kibana/public/discover/angular/doc_viewer.ts similarity index 90% rename from src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_directive.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/doc_viewer.ts index fa6145c45f55f..c13c354528413 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_directive.ts +++ b/src/legacy/core_plugins/kibana/public/discover/angular/doc_viewer.ts @@ -18,8 +18,10 @@ */ // @ts-ignore -import { uiModules } from 'ui/modules'; -import { DocViewer } from './doc_viewer'; +import { getServices } from '../kibana_services'; +import { DocViewer } from '../doc_viewer/doc_viewer'; + +const { uiModules } = getServices(); uiModules.get('apps/discover').directive('docViewer', (reactDirective: any) => { return reactDirective( diff --git a/src/legacy/core_plugins/kibana/public/discover/doc/doc_directive.ts b/src/legacy/core_plugins/kibana/public/discover/angular/index.ts similarity index 58% rename from src/legacy/core_plugins/kibana/public/discover/doc/doc_directive.ts rename to src/legacy/core_plugins/kibana/public/discover/angular/index.ts index 3ee510f47ce5b..5bae0d9d551e5 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc/doc_directive.ts +++ b/src/legacy/core_plugins/kibana/public/discover/angular/index.ts @@ -16,21 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import { wrapInI18nContext } from 'ui/i18n'; -// @ts-ignore -import { uiModules } from 'ui/modules'; -import { Doc } from './doc'; - -uiModules.get('apps/discover').directive('discoverDoc', function(reactDirective: any) { - return reactDirective( - wrapInI18nContext(Doc), - [ - ['id', { watchDepth: 'value' }], - ['index', { watchDepth: 'value' }], - ['indexPatternId', { watchDepth: 'reference' }], - ['indexPatternService', { watchDepth: 'reference' }], - ['esClient', { watchDepth: 'reference' }], - ], - { restrict: 'E' } - ); -}); +import './discover'; +import './doc'; +import './context'; +import './doc_viewer'; +import './directives'; diff --git a/src/legacy/core_plugins/kibana/public/discover/breadcrumbs.js b/src/legacy/core_plugins/kibana/public/discover/breadcrumbs.ts similarity index 88% rename from src/legacy/core_plugins/kibana/public/discover/breadcrumbs.js rename to src/legacy/core_plugins/kibana/public/discover/breadcrumbs.ts index 1220c99b5ee56..51e0dcba1cad0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/breadcrumbs.js +++ b/src/legacy/core_plugins/kibana/public/discover/breadcrumbs.ts @@ -23,18 +23,18 @@ export function getRootBreadcrumbs() { return [ { text: i18n.translate('kbn.discover.rootBreadcrumb', { - defaultMessage: 'Discover' + defaultMessage: 'Discover', }), - href: '#/discover' - } + href: '#/discover', + }, ]; } -export function getSavedSearchBreadcrumbs($route) { +export function getSavedSearchBreadcrumbs($route: any) { return [ ...getRootBreadcrumbs(), { text: $route.current.locals.savedSearch.id, - } + }, ]; } diff --git a/src/legacy/core_plugins/kibana/public/discover/components/fetch_error/fetch_error.js b/src/legacy/core_plugins/kibana/public/discover/components/fetch_error/fetch_error.js index 670e9446c6e4f..612ca860f8031 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/fetch_error/fetch_error.js +++ b/src/legacy/core_plugins/kibana/public/discover/components/fetch_error/fetch_error.js @@ -16,21 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - -import 'ngreact'; import React, { Fragment } from 'react'; -import { uiModules } from 'ui/modules'; -import { wrapInI18nContext } from 'ui/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { npStart } from 'ui/new_platform'; - -import { - EuiFlexGroup, - EuiFlexItem, - EuiCallOut, - EuiCodeBlock, - EuiSpacer, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiCallOut, EuiCodeBlock, EuiSpacer } from '@elastic/eui'; +import { getServices } from '../../kibana_services'; +const { uiModules, wrapInI18nContext, chrome } = getServices(); const DiscoverFetchError = ({ fetchError }) => { if (!fetchError) { @@ -40,7 +30,7 @@ const DiscoverFetchError = ({ fetchError }) => { let body; if (fetchError.lang === 'painless') { - const managementUrl = npStart.core.chrome.navLinks.get('kibana:management').url; + const managementUrl = chrome.navLinks.get('kibana:management').url; const url = `${managementUrl}/kibana/index_patterns`; body = ( @@ -51,10 +41,12 @@ const DiscoverFetchError = ({ fetchError }) => { in {managementLink}, under the {scriptedFields} tab." values={{ fetchErrorScript: `'${fetchError.script}'`, - scriptedFields: , + scriptedFields: ( + + ), managementLink: ( { defaultMessage="Management > Index Patterns" /> - ) + ), }} />

@@ -75,16 +67,10 @@ const DiscoverFetchError = ({ fetchError }) => { - + {body} - - {fetchError.error} - + {fetchError.error} @@ -96,4 +82,6 @@ const DiscoverFetchError = ({ fetchError }) => { const app = uiModules.get('apps/discover', ['react']); -app.directive('discoverFetchError', reactDirective => reactDirective(wrapInI18nContext(DiscoverFetchError))); +app.directive('discoverFetchError', reactDirective => + reactDirective(wrapInI18nContext(DiscoverFetchError)) +); diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js index f7469d0142d57..cfcb654077152 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field.js @@ -18,15 +18,15 @@ */ import $ from 'jquery'; +import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { getServices } from '../../kibana_services'; import html from './discover_field.html'; -import _ from 'lodash'; import 'ui/directives/css_truncate'; import 'ui/directives/field_name'; import './string_progress_bar'; import detailsHtml from './lib/detail_views/string.html'; -import { capabilities } from 'ui/capabilities'; -import { uiModules } from 'ui/modules'; +const { uiModules, capabilities } = getServices(); const app = uiModules.get('apps/discover'); app.directive('discoverField', function ($compile) { @@ -78,7 +78,7 @@ app.directive('discoverField', function ($compile) { }; - $scope.canVisualize = capabilities.get().visualize.show; + $scope.canVisualize = capabilities.visualize.show; $scope.toggleDisplay = function (field) { if (field.display) { diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search_directive.ts b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search_directive.ts index 8af23caedd78a..2e7dd3e210ef8 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search_directive.ts +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_field_search_directive.ts @@ -17,10 +17,11 @@ * under the License. */ // @ts-ignore -import { uiModules } from 'ui/modules'; -import { wrapInI18nContext } from 'ui/i18n'; +import { getServices } from '../../kibana_services'; import { DiscoverFieldSearch } from './discover_field_search'; +const { wrapInI18nContext, uiModules } = getServices(); + const app = uiModules.get('apps/discover'); app.directive('discoverFieldSearch', function(reactDirective: any) { diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_index_pattern_directive.ts b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_index_pattern_directive.ts index 938d6cc226f2f..5e3f678e388ad 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_index_pattern_directive.ts +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/discover_index_pattern_directive.ts @@ -17,10 +17,11 @@ * under the License. */ // @ts-ignore -import { uiModules } from 'ui/modules'; -import { wrapInI18nContext } from 'ui/i18n'; +import { getServices } from '../../kibana_services'; import { DiscoverIndexPattern } from './discover_index_pattern'; +const { wrapInI18nContext, uiModules } = getServices(); + const app = uiModules.get('apps/discover'); app.directive('discoverIndexPatternSelect', function(reactDirective: any) { diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.js b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.js index 3e0172dec1ff4..99a63efc0e0fc 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.js +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/field_chooser.js @@ -16,20 +16,22 @@ * specific language governing permissions and limitations * under the License. */ - -import 'ui/directives/css_truncate'; +//field_name directive will be replaced very soon import 'ui/directives/field_name'; import './discover_field'; -import 'ui/angular_ui_select'; import './discover_field_search_directive'; import './discover_index_pattern_directive'; import _ from 'lodash'; import $ from 'jquery'; import rison from 'rison-node'; import { fieldCalculator } from './lib/field_calculator'; -import { FieldList } from 'ui/index_patterns'; -import { uiModules } from 'ui/modules'; +import { + getServices, + FieldList +} from '../../kibana_services'; import fieldChooserTemplate from './field_chooser.html'; + +const { uiModules } = getServices(); const app = uiModules.get('apps/discover'); app.directive('discFieldChooser', function ($location, config, $route) { diff --git a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js index ae00df6dfbbf8..ca3a47cad5075 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js +++ b/src/legacy/core_plugins/kibana/public/discover/components/field_chooser/string_progress_bar.js @@ -16,13 +16,8 @@ * specific language governing permissions and limitations * under the License. */ - - -import { wrapInI18nContext } from 'ui/i18n'; -import { uiModules } from 'ui/modules'; - import React from 'react'; - +import { getServices } from '../../kibana_services'; import { EuiFlexGroup, EuiFlexItem, @@ -31,6 +26,7 @@ import { EuiToolTip, } from '@elastic/eui'; +const { wrapInI18nContext, uiModules } = getServices(); const module = uiModules.get('discover/field_chooser'); function StringFieldProgressBar(props) { diff --git a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js b/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js index 95db1b686f7aa..ad68e55e71622 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js +++ b/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu.js @@ -20,7 +20,8 @@ import React, { Fragment, PureComponent } from 'react'; import { EuiButton, EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; +import { getServices } from '../../kibana_services'; +const { docLinks } = getServices(); export class HelpMenu extends PureComponent { render() { @@ -31,7 +32,7 @@ export class HelpMenu extends PureComponent { diff --git a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu_util.js b/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu_util.js index aeabff2d97007..58a92193de63e 100644 --- a/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu_util.js +++ b/src/legacy/core_plugins/kibana/public/discover/components/help_menu/help_menu_util.js @@ -22,7 +22,7 @@ import { render, unmountComponentAtNode } from 'react-dom'; import { HelpMenu } from './help_menu'; export function addHelpMenuToAppChrome(chrome) { - chrome.helpExtension.set(domElement => { + chrome.setHelpExtension(domElement => { render(, domElement); return () => { unmountComponentAtNode(domElement); diff --git a/src/legacy/core_plugins/kibana/public/discover/context/README.md b/src/legacy/core_plugins/kibana/public/discover/context/README.md new file mode 100644 index 0000000000000..18ba118b4da79 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/context/README.md @@ -0,0 +1,4 @@ +# DISCOVER CONTEXT + +Placeholder for Discover's context functionality, that's currently in [../angular/context](../angular/context). +Once fully de-angularized it should be moved to this location \ No newline at end of file diff --git a/src/legacy/core_plugins/kibana/public/discover/doc/doc.test.tsx b/src/legacy/core_plugins/kibana/public/discover/doc/doc.test.tsx index 6612097620b44..b3efd23ea48d0 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc/doc.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/doc/doc.test.tsx @@ -24,6 +24,27 @@ import { ReactWrapper } from 'enzyme'; import { findTestSubject } from '@elastic/eui/lib/test'; import { Doc, DocProps } from './doc'; +jest.mock('../doc_viewer/doc_viewer', () => ({ + DocViewer: 'test', +})); + +jest.mock('../kibana_services', () => { + return { + getServices: () => ({ + metadata: { + branch: 'test', + }, + getDocViewsSorted: () => { + return []; + }, + }), + }; +}); + +beforeEach(() => { + jest.clearAllMocks(); +}); + // Suppress warnings about "act" until we use React 16.9 /* eslint-disable no-console */ const originalError = console.error; @@ -68,30 +89,30 @@ async function mountDoc(search: () => void, update = false, indexPatternGetter: } describe('Test of of Discover', () => { - it('renders loading msg', async () => { + test('renders loading msg', async () => { const comp = await mountDoc(jest.fn()); expect(findTestSubject(comp, 'doc-msg-loading').length).toBe(1); }); - it('renders IndexPattern notFound msg', async () => { + test('renders IndexPattern notFound msg', async () => { const indexPatternGetter = jest.fn(() => Promise.reject({ savedObjectId: '007' })); const comp = await mountDoc(jest.fn(), true, indexPatternGetter); expect(findTestSubject(comp, 'doc-msg-notFoundIndexPattern').length).toBe(1); }); - it('renders notFound msg', async () => { + test('renders notFound msg', async () => { const search = jest.fn(() => Promise.reject({ status: 404 })); const comp = await mountDoc(search, true); expect(findTestSubject(comp, 'doc-msg-notFound').length).toBe(1); }); - it('renders error msg', async () => { + test('renders error msg', async () => { const search = jest.fn(() => Promise.reject('whatever')); const comp = await mountDoc(search, true); expect(findTestSubject(comp, 'doc-msg-error').length).toBe(1); }); - it('renders elasticsearch hit ', async () => { + test('renders elasticsearch hit ', async () => { const hit = { hits: { total: 1, hits: [{ _id: 1, _source: { test: 1 } }] } }; const search = jest.fn(() => Promise.resolve(hit)); const comp = await mountDoc(search, true); diff --git a/src/legacy/core_plugins/kibana/public/discover/doc/doc.tsx b/src/legacy/core_plugins/kibana/public/discover/doc/doc.tsx index 1f2d2fc532b57..0e0e6ed110ca6 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc/doc.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/doc/doc.tsx @@ -19,11 +19,9 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiCallOut, EuiLink, EuiLoadingSpinner, EuiPageContent } from '@elastic/eui'; -import { IndexPatterns } from 'ui/index_patterns'; -import { metadata } from 'ui/metadata'; -import { ElasticSearchHit } from 'ui/registry/doc_views_types'; -import { DocViewer } from '../doc_viewer'; +import { DocViewer } from '../doc_viewer/doc_viewer'; import { ElasticRequestState, useEsDocSearch } from './use_es_doc_search'; +import { IndexPatterns, ElasticSearchHit, getServices } from '../kibana_services'; export interface ElasticSearchResult { hits: { @@ -117,7 +115,9 @@ export function Doc(props: DocProps) { values={{ indexName: props.index }} />{' '} { + return { + getServices: () => ({ + docViewsRegistry: { + getDocViewsSorted: (hit: any) => { + return mockGetDocViewsSorted(hit); + }, + }, + }), + }; +}); beforeEach(() => { emptyDocViews(); + jest.clearAllMocks(); }); test('Render with 3 different tabs', () => { diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer.tsx b/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer.tsx index 1c7aba9bcd7b2..aa737ebd8dcf1 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer.tsx @@ -18,7 +18,7 @@ */ import React from 'react'; import { EuiTabbedContent } from '@elastic/eui'; -import { getDocViewsSorted, DocViewRenderProps } from 'ui/registry/doc_views'; +import { getServices, DocViewRenderProps } from '../kibana_services'; import { DocViewerTab } from './doc_viewer_tab'; /** @@ -28,21 +28,24 @@ import { DocViewerTab } from './doc_viewer_tab'; * a `render` function. */ export function DocViewer(renderProps: DocViewRenderProps) { - const tabs = getDocViewsSorted(renderProps.hit).map(({ title, render, component }, idx) => { - return { - id: title, - name: title, - content: ( - - ), - }; - }); + const { docViewsRegistry } = getServices(); + const tabs = docViewsRegistry + .getDocViewsSorted(renderProps.hit) + .map(({ title, render, component }, idx) => { + return { + id: title, + name: title, + content: ( + + ), + }; + }); if (!tabs.length) { // There there's a minimum of 2 tabs active in Discover. diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_render_tab.test.tsx b/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_render_tab.test.tsx index 3bb59a8dc958c..5fa2d24dfa04c 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_render_tab.test.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_render_tab.test.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { mount } from 'enzyme'; import { DocViewRenderTab } from './doc_viewer_render_tab'; -import { DocViewRenderProps } from 'ui/registry/doc_views'; +import { DocViewRenderProps } from '../kibana_services'; test('Mounting and unmounting DocViewerRenderTab', () => { const unmountFn = jest.fn(); diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_render_tab.tsx b/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_render_tab.tsx index 185ff163dad2a..750ef6b6061e1 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_render_tab.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_render_tab.tsx @@ -17,7 +17,7 @@ * under the License. */ import React, { useRef, useEffect } from 'react'; -import { DocViewRenderFn, DocViewRenderProps } from 'ui/registry/doc_views'; +import { DocViewRenderFn, DocViewRenderProps } from '../kibana_services'; interface Props { render: DocViewRenderFn; diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_tab.tsx b/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_tab.tsx index 0b25421d8aff3..3721ba5818d41 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_tab.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/doc_viewer/doc_viewer_tab.tsx @@ -18,7 +18,7 @@ */ import React from 'react'; import { I18nProvider } from '@kbn/i18n/react'; -import { DocViewRenderProps, DocViewRenderFn } from 'ui/registry/doc_views'; +import { DocViewRenderProps, DocViewRenderFn } from '../kibana_services'; import { DocViewRenderTab } from './doc_viewer_render_tab'; import { DocViewerError } from './doc_viewer_render_error'; diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/index.ts b/src/legacy/core_plugins/kibana/public/discover/embeddable/constants.ts similarity index 92% rename from src/legacy/core_plugins/kibana/public/discover/doc_viewer/index.ts rename to src/legacy/core_plugins/kibana/public/discover/embeddable/constants.ts index 8ce94f24128df..cdb8a6ad3ad46 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_viewer/index.ts +++ b/src/legacy/core_plugins/kibana/public/discover/embeddable/constants.ts @@ -16,7 +16,4 @@ * specific language governing permissions and limitations * under the License. */ - -import './doc_viewer_directive'; - -export * from './doc_viewer'; +export const SEARCH_EMBEDDABLE_TYPE = 'search'; diff --git a/src/legacy/core_plugins/kibana/public/discover/embeddable/index.ts b/src/legacy/core_plugins/kibana/public/discover/embeddable/index.ts index 3138008f3e3a0..beeb6a7338f9d 100644 --- a/src/legacy/core_plugins/kibana/public/discover/embeddable/index.ts +++ b/src/legacy/core_plugins/kibana/public/discover/embeddable/index.ts @@ -20,3 +20,4 @@ export * from './types'; export * from './search_embeddable_factory'; export * from './search_embeddable'; +export { SEARCH_EMBEDDABLE_TYPE } from './constants'; diff --git a/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts b/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts index eaec11ff893ed..5f3ebd6d22e24 100644 --- a/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts +++ b/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable.ts @@ -16,42 +16,38 @@ * specific language governing permissions and limitations * under the License. */ - -// @ts-ignore -import { getFilterGenerator } from 'ui/filter_manager'; -import angular from 'angular'; import _ from 'lodash'; -import { SearchSource } from 'ui/courier'; -import { - getRequestInspectorStats, - getResponseInspectorStats, -} from 'ui/courier/utils/courier_inspector_utils'; -import { IndexPattern } from 'ui/index_patterns'; -import { RequestAdapter } from 'ui/inspector/adapters'; -import { Adapters } from 'ui/inspector/types'; -import { Subscription } from 'rxjs'; import * as Rx from 'rxjs'; +import { Subscription } from 'rxjs'; import { Filter, FilterStateStore } from '@kbn/es-query'; -import chrome from 'ui/chrome'; import { i18n } from '@kbn/i18n'; -import { toastNotifications } from 'ui/notify'; -import { TimeRange } from 'src/plugins/data/public'; import { TExecuteTriggerActions } from 'src/plugins/ui_actions/public'; import { setup as data } from '../../../../data/public/legacy'; -import { Query, onlyDisabledFiltersChanged, getTime } from '../../../../data/public'; +import { getTime, onlyDisabledFiltersChanged, Query } from '../../../../data/public'; import { APPLY_FILTER_TRIGGER, - Embeddable, Container, + Embeddable, } from '../../../../embeddable_api/public/np_ready/public'; -import * as columnActions from '../doc_table/actions/columns'; +import * as columnActions from '../angular/doc_table/actions/columns'; import { SavedSearch } from '../types'; import searchTemplate from './search_template.html'; import { ISearchEmbeddable, SearchInput, SearchOutput } from './types'; -import { SortOrder } from '../doc_table/components/table_header/helpers'; -import { getSortForSearchSource } from '../doc_table/lib/get_sort_for_search_source'; - -const config = chrome.getUiSettingsClient(); +import { SortOrder } from '../angular/doc_table/components/table_header/helpers'; +import { getSortForSearchSource } from '../angular/doc_table/lib/get_sort_for_search_source'; +import { + Adapters, + angular, + getFilterGenerator, + getRequestInspectorStats, + getResponseInspectorStats, + getServices, + IndexPattern, + RequestAdapter, + SearchSource, +} from '../kibana_services'; +import { TimeRange } from '../../../../../../plugins/data/public'; +import { SEARCH_EMBEDDABLE_TYPE } from './constants'; interface SearchScope extends ng.IScope { columns?: string[]; @@ -92,8 +88,6 @@ interface SearchEmbeddableConfig { queryFilter: unknown; } -export const SEARCH_EMBEDDABLE_TYPE = 'search'; - export class SearchEmbeddable extends Embeddable implements ISearchEmbeddable { private readonly savedSearch: SavedSearch; @@ -277,7 +271,7 @@ export class SearchEmbeddable extends Embeddable if (this.abortController) this.abortController.abort(); this.abortController = new AbortController(); - searchSource.setField('size', config.get('discover:sampleSize')); + searchSource.setField('size', getServices().uiSettings.get('discover:sampleSize')); searchSource.setField( 'sort', getSortForSearchSource(this.searchScope.sort, this.searchScope.indexPattern) @@ -319,7 +313,7 @@ export class SearchEmbeddable extends Embeddable // If the fetch was aborted, no need to surface this in the UI if (error.name === 'AbortError') return; - toastNotifications.addError(error, { + getServices().toastNotifications.addError(error, { title: i18n.translate('kbn.embeddable.errorTitle', { defaultMessage: 'Error fetching data', }), diff --git a/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable_factory.ts b/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable_factory.ts index d7b51b39e2a16..1939cc7060621 100644 --- a/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable_factory.ts +++ b/src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable_factory.ts @@ -16,24 +16,21 @@ * specific language governing permissions and limitations * under the License. */ - -import '../doc_table'; -import { capabilities } from 'ui/capabilities'; -import { npStart, npSetup } from 'ui/new_platform'; -import { i18n } from '@kbn/i18n'; -import chrome from 'ui/chrome'; import { IPrivate } from 'ui/private'; -import { TimeRange } from 'src/plugins/data/public'; -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; +import { i18n } from '@kbn/i18n'; import { TExecuteTriggerActions } from 'src/plugins/ui_actions/public'; +import '../angular/doc_table'; +import { getServices } from '../kibana_services'; import { EmbeddableFactory, ErrorEmbeddable, Container, } from '../../../../../../plugins/embeddable/public'; +import { TimeRange } from '../../../../../../plugins/data/public'; import { SavedSearchLoader } from '../types'; -import { SearchEmbeddable, SEARCH_EMBEDDABLE_TYPE } from './search_embeddable'; +import { SearchEmbeddable } from './search_embeddable'; import { SearchInput, SearchOutput } from './types'; +import { SEARCH_EMBEDDABLE_TYPE } from './constants'; export class SearchEmbeddableFactory extends EmbeddableFactory< SearchInput, @@ -55,7 +52,7 @@ export class SearchEmbeddableFactory extends EmbeddableFactory< } public isEditable() { - return capabilities.get().discover.save as boolean; + return getServices().capabilities.discover.save as boolean; } public canCreateNew() { @@ -73,16 +70,18 @@ export class SearchEmbeddableFactory extends EmbeddableFactory< input: Partial & { id: string; timeRange: TimeRange }, parent?: Container ): Promise { - const $injector = await chrome.dangerouslyGetActiveInjector(); + const $injector = await getServices().getInjector(); const $compile = $injector.get('$compile'); const $rootScope = $injector.get('$rootScope'); const searchLoader = $injector.get('savedSearches'); - const editUrl = chrome.addBasePath(`/app/kibana${searchLoader.urlFor(savedObjectId)}`); + const editUrl = await getServices().addBasePath( + `/app/kibana${searchLoader.urlFor(savedObjectId)}` + ); const Private = $injector.get('Private'); - const queryFilter = Private(FilterBarQueryFilterProvider); + const queryFilter = Private(getServices().FilterBarQueryFilterProvider); try { const savedObject = await searchLoader.get(savedObjectId); return new SearchEmbeddable( @@ -92,7 +91,7 @@ export class SearchEmbeddableFactory extends EmbeddableFactory< $compile, editUrl, queryFilter, - editable: capabilities.get().discover.save as boolean, + editable: getServices().capabilities.discover.save as boolean, indexPatterns: _.compact([savedObject.searchSource.getField('index')]), }, input, @@ -110,5 +109,5 @@ export class SearchEmbeddableFactory extends EmbeddableFactory< } } -const factory = new SearchEmbeddableFactory(npStart.plugins.uiActions.executeTriggerActions); -npSetup.plugins.embeddable.registerEmbeddableFactory(factory.type, factory); +const factory = new SearchEmbeddableFactory(getServices().uiActions.executeTriggerActions); +getServices().embeddable.registerEmbeddableFactory(factory.type, factory); diff --git a/src/legacy/core_plugins/kibana/public/discover/embeddable/types.ts b/src/legacy/core_plugins/kibana/public/discover/embeddable/types.ts index bc46cdbe82981..db8d2afc7aff3 100644 --- a/src/legacy/core_plugins/kibana/public/discover/embeddable/types.ts +++ b/src/legacy/core_plugins/kibana/public/discover/embeddable/types.ts @@ -17,13 +17,13 @@ * under the License. */ -import { StaticIndexPattern } from 'ui/index_patterns'; import { TimeRange } from 'src/plugins/data/public'; import { Query } from 'src/legacy/core_plugins/data/public'; import { Filter } from '@kbn/es-query'; import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from 'src/plugins/embeddable/public'; +import { StaticIndexPattern } from '../kibana_services'; import { SavedSearch } from '../types'; -import { SortOrder } from '../doc_table/components/table_header/helpers'; +import { SortOrder } from '../angular/doc_table/components/table_header/helpers'; export interface SearchInput extends EmbeddableInput { timeRange: TimeRange; diff --git a/src/legacy/core_plugins/kibana/public/discover/helpers/register_feature.ts b/src/legacy/core_plugins/kibana/public/discover/helpers/register_feature.ts new file mode 100644 index 0000000000000..eb8c2aec91558 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/helpers/register_feature.ts @@ -0,0 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { i18n } from '@kbn/i18n'; +import { + FeatureCatalogueRegistryProvider, + FeatureCatalogueCategory, +} from 'ui/registry/feature_catalogue'; + +export function registerFeature() { + FeatureCatalogueRegistryProvider.register(() => { + return { + id: 'discover', + title: i18n.translate('kbn.discover.discoverTitle', { + defaultMessage: 'Discover', + }), + description: i18n.translate('kbn.discover.discoverDescription', { + defaultMessage: 'Interactively explore your data by querying and filtering raw documents.', + }), + icon: 'discoverApp', + path: '/app/kibana#/discover', + showOnHomePage: true, + category: FeatureCatalogueCategory.DATA, + }; + }); +} diff --git a/src/legacy/core_plugins/kibana/public/discover/index.js b/src/legacy/core_plugins/kibana/public/discover/index.js deleted file mode 100644 index e509936306275..0000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/index.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import './saved_searches/saved_searches'; -import { i18n } from '@kbn/i18n'; - -import './angular/directives'; -import 'ui/collapsible_sidebar'; -import './components/field_chooser/field_chooser'; -import './angular/discover'; -import './doc_table/components/table_row'; -import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue'; -import './doc'; -import './context'; - -FeatureCatalogueRegistryProvider.register(() => { - return { - id: 'discover', - title: i18n.translate('kbn.discover.discoverTitle', { - defaultMessage: 'Discover', - }), - description: i18n.translate('kbn.discover.discoverDescription', { - defaultMessage: 'Interactively explore your data by querying and filtering raw documents.', - }), - icon: 'discoverApp', - path: '/app/kibana#/discover', - showOnHomePage: true, - category: FeatureCatalogueCategory.DATA - }; -}); diff --git a/src/legacy/core_plugins/kibana/public/discover/index.ts b/src/legacy/core_plugins/kibana/public/discover/index.ts new file mode 100644 index 0000000000000..35e48598f07a8 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/index.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { PluginInitializer, PluginInitializerContext } from 'kibana/public'; +import { npSetup, npStart } from 'ui/new_platform'; +import { DiscoverPlugin, DiscoverSetup, DiscoverStart } from './plugin'; + +// Core will be looking for this when loading our plugin in the new platform +export const plugin: PluginInitializer = ( + initializerContext: PluginInitializerContext +) => { + return new DiscoverPlugin(initializerContext); +}; + +const pluginInstance = plugin({} as PluginInitializerContext); +export const setup = pluginInstance.setup(npSetup.core, npSetup.plugins); +export const start = pluginInstance.start(npStart.core, npStart.plugins); diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts new file mode 100644 index 0000000000000..dd0674073f442 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -0,0 +1,121 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import 'ui/collapsible_sidebar'; +import 'ui/directives/listen'; +import 'ui/fixed_scroll'; +import 'ui/directives/css_truncate'; + +import { npStart } from 'ui/new_platform'; +import chromeLegacy from 'ui/chrome'; +import angular from 'angular'; // just used in embeddables and discover controller +import uiRoutes from 'ui/routes'; +// @ts-ignore +import { uiModules } from 'ui/modules'; +import { SearchSource } from 'ui/courier'; +// @ts-ignore +import { StateProvider } from 'ui/state_management/state'; +// @ts-ignore +import { SavedObjectProvider } from 'ui/saved_objects/saved_object'; +import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; +import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; +import { timefilter } from 'ui/timefilter'; +import { ShareContextMenuExtensionsRegistryProvider } from 'ui/share'; +// @ts-ignore +import { IndexPattern, IndexPatterns } from 'ui/index_patterns'; +import { wrapInI18nContext } from 'ui/i18n'; +// @ts-ignore +import { docTitle } from 'ui/doc_title'; +// @ts-ignore +import * as docViewsRegistry from 'ui/registry/doc_views'; + +const services = { + // new plattform + addBasePath: npStart.core.http.basePath.prepend, + capabilities: npStart.core.application.capabilities, + chrome: npStart.core.chrome, + docLinks: npStart.core.docLinks, + eui_utils: npStart.plugins.eui_utils, + inspector: npStart.plugins.inspector, + metadata: npStart.core.injectedMetadata.getLegacyMetadata(), + toastNotifications: npStart.core.notifications.toasts, + uiSettings: npStart.core.uiSettings, + uiActions: npStart.plugins.uiActions, + embeddable: npStart.plugins.embeddable, + // legacy + docTitle, + docViewsRegistry, + FilterBarQueryFilterProvider, + getInjector: () => { + return chromeLegacy.dangerouslyGetActiveInjector(); + }, + SavedObjectRegistryProvider, + SavedObjectProvider, + SearchSource, + ShareContextMenuExtensionsRegistryProvider, + StateProvider, + timefilter, + uiModules, + uiRoutes, + wrapInI18nContext, +}; +export function getServices() { + return services; +} + +// EXPORT legacy static dependencies +export { angular }; +export { buildVislibDimensions } from 'ui/visualize/loader/pipeline_helpers/build_pipeline'; +// @ts-ignore +export { callAfterBindingsWorkaround } from 'ui/compat'; +// @ts-ignore +export { getFilterGenerator } from 'ui/filter_manager'; +export { + getRequestInspectorStats, + getResponseInspectorStats, +} from 'ui/courier/utils/courier_inspector_utils'; +// @ts-ignore +export { hasSearchStategyForIndexPattern, isDefaultTypeIndexPattern } from 'ui/courier'; +// @ts-ignore +export { intervalOptions } from 'ui/agg_types/buckets/_interval_options'; +// @ts-ignore +export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; +// @ts-ignore +export { RequestAdapter } from 'ui/inspector/adapters'; +export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; +export { FieldList } from 'ui/index_patterns'; +export { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; +export { showShareContextMenu } from 'ui/share'; +export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; +export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; +// @ts-ignore +export { timezoneProvider } from 'ui/vis/lib/timezone'; +// @ts-ignore +export { getUnhashableStatesProvider } from 'ui/state_management/state_hashing'; +// @ts-ignore +export { tabifyAggResponse } from 'ui/agg_response/tabify'; +// @ts-ignore +export { vislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; + +// EXPORT types +export { VisProvider } from 'ui/vis'; +export { StaticIndexPattern, IndexPatterns, IndexPattern, FieldType } from 'ui/index_patterns'; +export { SearchSource } from 'ui/courier'; +export { ElasticSearchHit } from 'ui/registry/doc_views_types'; +export { DocViewRenderProps, DocViewRenderFn } from 'ui/registry/doc_views'; +export { Adapters } from 'ui/inspector/types'; diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts new file mode 100644 index 0000000000000..873c429bf705d --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/public'; +import { IUiActionsStart } from 'src/plugins/ui_actions/public'; +import { registerFeature } from './helpers/register_feature'; +import './kibana_services'; +import { + Start as EmbeddableStart, + Setup as EmbeddableSetup, +} from '../../../../../plugins/embeddable/public'; + +/** + * These are the interfaces with your public contracts. You should export these + * for other plugins to use in _their_ `SetupDeps`/`StartDeps` interfaces. + * @public + */ +export type DiscoverSetup = void; +export type DiscoverStart = void; +interface DiscoverSetupPlugins { + uiActions: IUiActionsStart; + embeddable: EmbeddableSetup; +} +interface DiscoverStartPlugins { + uiActions: IUiActionsStart; + embeddable: EmbeddableStart; +} + +export class DiscoverPlugin implements Plugin { + constructor(initializerContext: PluginInitializerContext) {} + setup(core: CoreSetup, plugins: DiscoverSetupPlugins): DiscoverSetup { + registerFeature(); + require('./angular'); + } + + start(core: CoreStart, plugins: DiscoverStartPlugins): DiscoverStart { + // TODO enable this when possible, seems it broke a functional test: + // dashboard mode Dashboard View Mode Dashboard viewer can paginate on a saved search + // const factory = new SearchEmbeddableFactory(plugins.uiActions.executeTriggerActions); + // plugins.embeddable.registerEmbeddableFactory(factory.type, factory); + } + + stop() {} +} diff --git a/src/legacy/core_plugins/kibana/public/discover/saved_searches/_saved_search.js b/src/legacy/core_plugins/kibana/public/discover/saved_searches/_saved_search.js index 3903dc0845450..9bbc5baf4fc22 100644 --- a/src/legacy/core_plugins/kibana/public/discover/saved_searches/_saved_search.js +++ b/src/legacy/core_plugins/kibana/public/discover/saved_searches/_saved_search.js @@ -17,10 +17,10 @@ * under the License. */ -import 'ui/notify'; -import { uiModules } from 'ui/modules'; import { createLegacyClass } from 'ui/utils/legacy_class'; -import { SavedObjectProvider } from 'ui/saved_objects/saved_object'; +import { getServices } from '../kibana_services'; + +const { uiModules, SavedObjectProvider } = getServices(); const module = uiModules.get('discover/saved_searches', []); @@ -40,7 +40,7 @@ module.factory('SavedSearch', function (Private) { columns: [], hits: 0, sort: [], - version: 1 + version: 1, }, }); @@ -55,7 +55,7 @@ module.factory('SavedSearch', function (Private) { hits: 'integer', columns: 'keyword', sort: 'keyword', - version: 'integer' + version: 'integer', }; // Order these fields to the top, the rest are alphabetical diff --git a/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_search_register.js b/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_search_register.js index 8460ccf923cf3..9554642c225fd 100644 --- a/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_search_register.js +++ b/src/legacy/core_plugins/kibana/public/discover/saved_searches/saved_search_register.js @@ -17,10 +17,10 @@ * under the License. */ -import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry'; +import { getServices } from '../kibana_services'; import './saved_searches'; -SavedObjectRegistryProvider.register((savedSearches) => { +getServices().SavedObjectRegistryProvider.register((savedSearches) => { return savedSearches; }); diff --git a/src/legacy/core_plugins/kibana/public/discover/top_nav/open_search_panel.js b/src/legacy/core_plugins/kibana/public/discover/top_nav/open_search_panel.js index f29ebe6a47141..0c3b52fbf0640 100644 --- a/src/legacy/core_plugins/kibana/public/discover/top_nav/open_search_panel.js +++ b/src/legacy/core_plugins/kibana/public/discover/top_nav/open_search_panel.js @@ -19,11 +19,9 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder'; import rison from 'rison-node'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; - import { EuiButton, EuiFlexGroup, @@ -34,6 +32,7 @@ import { EuiFlyoutBody, EuiTitle, } from '@elastic/eui'; +import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder'; const SEARCH_OBJECT_TYPE = 'search'; diff --git a/src/legacy/core_plugins/kibana/public/discover/top_nav/open_search_panel.test.js b/src/legacy/core_plugins/kibana/public/discover/top_nav/open_search_panel.test.js index 2bec532110379..3531088e3847c 100644 --- a/src/legacy/core_plugins/kibana/public/discover/top_nav/open_search_panel.test.js +++ b/src/legacy/core_plugins/kibana/public/discover/top_nav/open_search_panel.test.js @@ -20,6 +20,14 @@ import React from 'react'; import { shallow } from 'enzyme'; +jest.mock('../kibana_services', () => { + return { + getServices: () => ({ + SavedObjectFinder: jest.fn() + }), + }; +}); + import { OpenSearchPanel, } from './open_search_panel'; diff --git a/src/legacy/core_plugins/kibana/public/discover/types.d.ts b/src/legacy/core_plugins/kibana/public/discover/types.d.ts index f285e94369893..7d8740243ec02 100644 --- a/src/legacy/core_plugins/kibana/public/discover/types.d.ts +++ b/src/legacy/core_plugins/kibana/public/discover/types.d.ts @@ -17,8 +17,8 @@ * under the License. */ -import { SearchSource } from 'ui/courier'; -import { SortOrder } from './doc_table/components/table_header/helpers'; +import { SearchSource } from './kibana_services'; +import { SortOrder } from './angular/doc_table/components/table_header/helpers'; export interface SavedSearch { readonly id: string; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts index c94b0dcd2bd9d..6efe6bc96dbba 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts +++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts @@ -6,8 +6,8 @@ // @ts-ignore import { MAP_SAVED_OBJECT_TYPE } from '../../../maps/common/constants'; -import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable'; import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/visualize/embeddable'; +import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/embeddable/constants'; export const EmbeddableTypes = { map: MAP_SAVED_OBJECT_TYPE, From d1d7d8a86aacdcdb38b27c31e721a8a4b59245a0 Mon Sep 17 00:00:00 2001 From: Chris Davies Date: Fri, 25 Oct 2019 10:19:48 -0400 Subject: [PATCH 146/191] Fix telemetry factory and tests (#49224) --- .../plugins/lens/public/app_plugin/plugin.tsx | 1 - .../lens/public/lens_ui_telemetry/factory.test.ts | 3 +-- .../lens/public/lens_ui_telemetry/factory.ts | 14 ++------------ 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx index 1f8779bb68b81..b7960b23651c6 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx @@ -72,7 +72,6 @@ export class AppPlugin { setReportManager( new LensReportManager({ storage: new Storage(localStorage), - basePath: core.http.basePath.get(), http: core.http, }) ); diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts index 9b65cbefaf799..6e860c594f4a5 100644 --- a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts +++ b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts @@ -45,7 +45,6 @@ describe('Lens UI telemetry', () => { const fakeManager = new LensReportManager({ http, storage, - basePath: '/basepath', }); setReportManager(fakeManager); }); @@ -84,7 +83,7 @@ describe('Lens UI telemetry', () => { jest.runOnlyPendingTimers(); - expect(http.post).toHaveBeenCalledWith(`/basepath/api/lens/telemetry`, { + expect(http.post).toHaveBeenCalledWith(`/api/lens/telemetry`, { body: JSON.stringify({ events: { '2019-10-23': { diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts index d264e9c77c463..673910deae339 100644 --- a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts +++ b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts @@ -45,21 +45,11 @@ export class LensReportManager { private storage: Storage; private http: HttpServiceBase; - private basePath: string; private timer: ReturnType; - constructor({ - storage, - http, - basePath, - }: { - storage: Storage; - http: HttpServiceBase; - basePath: string; - }) { + constructor({ storage, http }: { storage: Storage; http: HttpServiceBase }) { this.storage = storage; this.http = http; - this.basePath = basePath; this.readFromStorage(); @@ -96,7 +86,7 @@ export class LensReportManager { this.readFromStorage(); if (Object.keys(this.events).length || Object.keys(this.suggestionEvents).length) { try { - await this.http.post(`${this.basePath}${BASE_API_URL}/telemetry`, { + await this.http.post(`${BASE_API_URL}/telemetry`, { body: JSON.stringify({ events: this.events, suggestionEvents: this.suggestionEvents, From e16a36df3343cbf653ce01f989d7297a1e98add5 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 25 Oct 2019 10:21:56 -0400 Subject: [PATCH 147/191] Add render for empty donut chart. (#48583) --- .../public/components/functional/charts/donut_chart.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart.tsx index 3ae6f349d3997..76c3bd5d4c50d 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart.tsx @@ -25,6 +25,10 @@ export const DonutChart = ({ height, down, up, width }: DonutChartProps) => { colors: { danger, gray }, } = useContext(UptimeSettingsContext); + let upCount = up; + if (up === 0 && down === 0) { + upCount = 1; + } useEffect(() => { if (chartElement.current !== null) { // we must remove any existing paths before painting @@ -50,7 +54,7 @@ export const DonutChart = ({ height, down, up, width }: DonutChartProps) => { .data( // @ts-ignore pie generator expects param of type number[], but only works with // output of d3.entries, which is like Array<{ key: string, value: number }> - pieGenerator(d3.entries({ up, down })) + pieGenerator(d3.entries({ up: upCount, down })) ) .enter() .append('path') @@ -64,7 +68,7 @@ export const DonutChart = ({ height, down, up, width }: DonutChartProps) => { ) .attr('fill', (d: any) => color(d.data.key)); } - }, [chartElement.current, up, down]); + }, [chartElement.current, upCount, down]); return ( From 7af0c478cb889f9b97baa62c61f8a8d971fb011e Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:35:36 -0700 Subject: [PATCH 148/191] [npm] Removes rsync (#49285) Amungst one of the first dependencies added to X-Pack and does not appear to still be used. Signed-off-by: Tyler Smalley --- x-pack/package.json | 1 - yarn.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index fa439a2087547..6b3156a30e7ae 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -169,7 +169,6 @@ "react-test-renderer": "^16.8.0", "react-testing-library": "^6.0.0", "redux-test-utils": "0.2.2", - "rsync": "0.6.1", "sass-loader": "^7.3.1", "sass-resources-loader": "^2.0.1", "simple-git": "1.116.0", diff --git a/yarn.lock b/yarn.lock index b949aa07608c9..e9b4ef6588daf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24816,11 +24816,6 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== -rsync@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/rsync/-/rsync-0.6.1.tgz#3681a0098bd8750448f8bf9da1fee09f7763742b" - integrity sha1-NoGgCYvYdQRI+L+dof7gn3djdCs= - run-async@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" From 0cd5c49954c6d8ffb34ba4d688957c0679eba136 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:36:34 -0700 Subject: [PATCH 149/191] [npm] Removes react-select (#49284) Added when X-Pack was closed-source and import/no-extraneous-dependencies was implemented. Does not appear to still be used. Signed-off-by: Tyler Smalley --- x-pack/package.json | 1 - yarn.lock | 13 ++----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index 6b3156a30e7ae..2830d2d7e31cf 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -333,7 +333,6 @@ "react-resize-detector": "^4.2.0", "react-reverse-portal": "^1.0.4", "react-router-dom": "^4.3.1", - "react-select": "^1.2.1", "react-shortcuts": "^2.0.0", "react-sticky": "^6.0.3", "react-syntax-highlighter": "^5.7.0", diff --git a/yarn.lock b/yarn.lock index e9b4ef6588daf..68173b3cf941a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7937,7 +7937,7 @@ classnames@2.2.6, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== -classnames@2.x, classnames@^2.2.4: +classnames@2.x: version "2.2.5" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" integrity sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0= @@ -23073,7 +23073,7 @@ react-hotkeys@2.0.0-pre4: dependencies: prop-types "^15.6.1" -react-input-autosize@^2.1.2, react-input-autosize@^2.2.1: +react-input-autosize@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8" integrity sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA== @@ -23391,15 +23391,6 @@ react-router@^4.3.1: prop-types "^15.6.1" warning "^4.0.1" -react-select@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.2.1.tgz#a2fe58a569eb14dcaa6543816260b97e538120d1" - integrity sha512-vaCgT2bEl+uTyE/uKOEgzE5Dc/wLtzhnBvoHCeuLoJWc4WuadN6WQDhoL42DW+TziniZK2Gaqe/wUXydI3NSaQ== - dependencies: - classnames "^2.2.4" - prop-types "^15.5.8" - react-input-autosize "^2.1.2" - react-select@^2.2.0: version "2.4.4" resolved "https://registry.yarnpkg.com/react-select/-/react-select-2.4.4.tgz#ba72468ef1060c7d46fbb862b0748f96491f1f73" From fa169dacebeb4375daafee9ec1abab67fbdbad51 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:37:06 -0700 Subject: [PATCH 150/191] [npm] Removes humps (#49282) Added with the original commit of APM, but is no longer used. Signed-off-by: Tyler Smalley --- package.json | 1 - renovate.json5 | 8 -------- x-pack/package.json | 1 - yarn.lock | 10 ---------- 4 files changed, 20 deletions(-) diff --git a/package.json b/package.json index d64307ade9247..86bf17205a577 100644 --- a/package.json +++ b/package.json @@ -312,7 +312,6 @@ "@types/has-ansi": "^3.0.0", "@types/history": "^4.7.3", "@types/hoek": "^4.1.3", - "@types/humps": "^1.1.2", "@types/jest": "^24.0.18", "@types/joi": "^13.4.2", "@types/jquery": "^3.3.31", diff --git a/renovate.json5 b/renovate.json5 index deb513d57c85e..2d068f55bc61a 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -401,14 +401,6 @@ '@types/history', ], }, - { - groupSlug: 'humps', - groupName: 'humps related packages', - packageNames: [ - 'humps', - '@types/humps', - ], - }, { groupSlug: 'jquery', groupName: 'jquery related packages', diff --git a/x-pack/package.json b/x-pack/package.json index 2830d2d7e31cf..7b685ebd3e0ff 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -266,7 +266,6 @@ "handlebars": "4.3.5", "history": "4.9.0", "history-extra": "^5.0.1", - "humps": "2.0.1", "i18n-iso-countries": "^4.3.1", "icalendar": "0.7.1", "idx": "^2.5.6", diff --git a/yarn.lock b/yarn.lock index 68173b3cf941a..6e1f42218b378 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3451,11 +3451,6 @@ resolved "https://registry.yarnpkg.com/@types/hoek/-/hoek-4.1.3.tgz#d1982d48fb0d2a0e5d7e9d91838264d8e428d337" integrity sha1-0ZgtSPsNKg5dfp2Rg4Jk2OQo0zc= -"@types/humps@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@types/humps/-/humps-1.1.2.tgz#fbcaf596d20ff2ed78f8f511c5d6a943b51101d6" - integrity sha1-+8r1ltIP8u14+PURxdapQ7URAdY= - "@types/indent-string@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/indent-string/-/indent-string-3.0.0.tgz#9ebb391ceda548926f5819ad16405349641b999f" @@ -15155,11 +15150,6 @@ humanize-string@^1.0.2: dependencies: decamelize "^1.0.0" -humps@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/humps/-/humps-2.0.1.tgz#dd02ea6081bd0568dc5d073184463957ba9ef9aa" - integrity sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao= - hyperlinker@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" From 2210c2f50e8b0e212bb1e3b18f1b3282c025698e Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:37:44 -0700 Subject: [PATCH 151/191] [npm] Removes dataloader (#49281) Originally added in https://github.com/elastic/kibana/pull/24068, however, it doesn't appear to have ever been used. Signed-off-by: Tyler Smalley --- x-pack/package.json | 1 - yarn.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index 7b685ebd3e0ff..6fe8d0ddb47e3 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -241,7 +241,6 @@ "cytoscape-dagre": "^2.2.2", "d3": "3.5.17", "d3-scale": "1.0.7", - "dataloader": "^1.4.0", "dedent": "^0.7.0", "del": "^5.1.0", "dragselect": "1.13.1", diff --git a/yarn.lock b/yarn.lock index 6e1f42218b378..b01374a570e3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9691,11 +9691,6 @@ data-urls@^1.0.1: whatwg-mimetype "^2.1.0" whatwg-url "^7.0.0" -dataloader@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-1.4.0.tgz#bca11d867f5d3f1b9ed9f737bd15970c65dff5c8" - integrity sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw== - date-fns@^1.27.2: version "1.29.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" From 1461bc4a7c25e6bd529912af33ed986bda55e73f Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:38:08 -0700 Subject: [PATCH 152/191] [npm] Removes trunc-html and trunc-text (#49278) Originally added in https://github.com/elastic/kibana/pull/6791 as part of custom notification banners, however it's no longer used. Signed-off-by: Tyler Smalley --- package.json | 2 -- yarn.lock | 42 ------------------------------------------ 2 files changed, 44 deletions(-) diff --git a/package.json b/package.json index 86bf17205a577..91af1a017e91a 100644 --- a/package.json +++ b/package.json @@ -247,8 +247,6 @@ "tinygradient": "0.4.3", "tinymath": "1.2.1", "topojson-client": "3.0.0", - "trunc-html": "1.1.2", - "trunc-text": "1.0.2", "tslib": "^1.9.3", "type-detect": "^4.0.8", "ui-select": "0.19.8", diff --git a/yarn.lock b/yarn.lock index b01374a570e3d..444a1eb1a1e15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5665,16 +5665,6 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -assignment@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/assignment/-/assignment-2.0.0.tgz#ffd17b21bf5d6b22e777b989681a815456a3dd3e" - integrity sha1-/9F7Ib9dayLnd7mJaBqBVFaj3T4= - -assignment@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/assignment/-/assignment-2.2.0.tgz#f5b5bc2d160d69986e8700cd38f567c0aabe101e" - integrity sha1-9bW8LRYNaZhuhwDNOPVnwKq+EB4= - ast-module-types@^2.3.1, ast-module-types@^2.3.2, ast-module-types@^2.4.0: version "2.5.0" resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-2.5.0.tgz#44b8bcd51684329a77f2af6b2587df9ea6b4d5ff" @@ -14748,11 +14738,6 @@ hawk@~6.0.2: hoek "4.x.x" sntp "2.x.x" -he@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/he/-/he-0.5.0.tgz#2c05ffaef90b68e860f3fd2b54ef580989277ee2" - integrity sha1-LAX/rvkLaOhg8/0rVO9YCYknfuI= - he@1.2.0, he@1.2.x, he@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -15623,14 +15608,6 @@ inquirer@^7.0.0: strip-ansi "^5.1.0" through "^2.3.6" -insane@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/insane/-/insane-2.6.1.tgz#c7dcae7b51c20346883b71078fad6ce0483c198f" - integrity sha1-x9yue1HCA0aIO3EHj61s4Eg8GY8= - dependencies: - assignment "2.0.0" - he "0.5.0" - insight@0.10.1: version "0.10.1" resolved "https://registry.yarnpkg.com/insight/-/insight-0.10.1.tgz#a0ecf668484a95d66e9be59644964e719cc83380" @@ -27577,25 +27554,6 @@ trough@^1.0.0: dependencies: glob "^6.0.4" -trunc-html@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/trunc-html/-/trunc-html-1.1.2.tgz#1e97d51f67d470b67662b1a670e6d0ea7a8edafe" - integrity sha1-HpfVH2fUcLZ2YrGmcObQ6nqO2v4= - dependencies: - assignment "2.2.0" - insane "2.6.1" - trunc-text "1.0.1" - -trunc-text@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trunc-text/-/trunc-text-1.0.1.tgz#58f876d8ac59b224b79834bb478b8656e69622b5" - integrity sha1-WPh22KxZsiS3mDS7R4uGVuaWIrU= - -trunc-text@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/trunc-text/-/trunc-text-1.0.2.tgz#b582bb3ddea9c9adc25017d737c48ebdd2157406" - integrity sha1-tYK7Pd6pya3CUBfXN8SOvdIVdAY= - ts-debounce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ts-debounce/-/ts-debounce-1.0.0.tgz#e433301744ba75fe25466f7f23e1382c646aae6a" From 9b69d2988ac144b084fcc4458a47bd2bcec2b1bf Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:38:41 -0700 Subject: [PATCH 153/191] [npm] Remove checksum (#49277) Used in Gulp when X-Pack was closed source and no longer used. Signed-off-by: Tyler Smalley --- x-pack/package.json | 1 - yarn.lock | 14 -------------- 2 files changed, 15 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index 6fe8d0ddb47e3..59d546d2833d4 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -122,7 +122,6 @@ "base64url": "^3.0.1", "chalk": "^2.4.2", "chance": "1.0.18", - "checksum": "0.1.1", "cheerio": "0.22.0", "commander": "3.0.0", "copy-webpack-plugin": "^5.0.4", diff --git a/yarn.lock b/yarn.lock index 444a1eb1a1e15..fba1f0ccab548 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7732,13 +7732,6 @@ check-more-types@2.24.0: resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= -checksum@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/checksum/-/checksum-0.1.1.tgz#dc6527d4c90be8560dbd1ed4cecf3297d528e9e9" - integrity sha1-3GUn1MkL6FYNvR7Uzs8yl9Uo6ek= - dependencies: - optimist "~0.3.5" - cheerio@0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" @@ -20781,13 +20774,6 @@ optimist@^0.6.1, optimist@~0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optimist@~0.3.5: - version "0.3.7" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" - integrity sha1-yQlBrVnkJzMokjB00s8ufLxuwNk= - dependencies: - wordwrap "~0.0.2" - optionator@^0.8.1, optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" From cc67942f39583ed934a232821e4ee59281299206 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:39:10 -0700 Subject: [PATCH 154/191] [npm] Remove babel-plugin-mock-imports and gulp-multi-process (#49276) * [npm] Remove babel-plugin-mock-imports Originally added as part of https://github.com/elastic/kibana/pull/22695, however, it doesn't appear to have ever actually been used. * [npm] Removes gulp-multi-process Signed-off-by: Tyler Smalley --- src/dev/license_checker/config.ts | 3 -- x-pack/package.json | 2 - yarn.lock | 61 ------------------------------- 3 files changed, 66 deletions(-) diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index 727c51f704431..fbd16d95ded1c 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -106,8 +106,5 @@ export const LICENSE_OVERRIDES = { // TODO can be removed once we upgrade the use of walk dependency past or equal to v2.3.14 'walk@2.3.9': ['MIT'], - // TODO remove this once we upgrade past or equal to v1.0.2 - 'babel-plugin-mock-imports@1.0.1': ['MIT'], - '@elastic/node-ctags@1.0.2': ['Nuclide software'], }; diff --git a/x-pack/package.json b/x-pack/package.json index 59d546d2833d4..8bb3c683fa290 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -115,7 +115,6 @@ "axios": "^0.19.0", "babel-jest": "^24.9.0", "babel-plugin-inline-react-svg": "^1.1.0", - "babel-plugin-mock-imports": "^1.0.1", "babel-plugin-require-context-hook": "npm:babel-plugin-require-context-hook-babel7@1.0.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "base64-js": "^1.3.1", @@ -142,7 +141,6 @@ "graphql-codegen-typescript-server": "^0.18.2", "gulp": "4.0.2", "gulp-mocha": "^7.0.2", - "gulp-multi-process": "1.3.1", "hapi": "^17.5.3", "jest": "^24.9.0", "jest-cli": "^24.9.0", diff --git a/yarn.lock b/yarn.lock index fba1f0ccab548..5b82466674428 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5748,55 +5748,6 @@ async-settle@^1.0.0: dependencies: async-done "^1.2.2" -async.queue@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.queue/-/async.queue-0.5.2.tgz#8d5d90812e1481066bc0904e8cc1712b17c3bd7c" - integrity sha1-jV2QgS4UgQZrwJBOjMFxKxfDvXw= - dependencies: - async.util.queue "0.5.2" - -async.util.arrayeach@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.arrayeach/-/async.util.arrayeach-0.5.2.tgz#58c4e98028d55d69bfb05aeb3af44e0a555a829c" - integrity sha1-WMTpgCjVXWm/sFrrOvROClVagpw= - -async.util.isarray@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.isarray/-/async.util.isarray-0.5.2.tgz#e62dac8f2636f65875dcf7521c2d24d0dfb2bbdf" - integrity sha1-5i2sjyY29lh13PdSHC0k0N+yu98= - -async.util.map@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.map/-/async.util.map-0.5.2.tgz#e588ef86e0b3ab5f027d97af4d6835d055ca69d6" - integrity sha1-5YjvhuCzq18CfZevTWg10FXKadY= - -async.util.noop@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.noop/-/async.util.noop-0.5.2.tgz#bdd62b97cb0aa3f60b586ad148468698975e58b9" - integrity sha1-vdYrl8sKo/YLWGrRSEaGmJdeWLk= - -async.util.onlyonce@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.onlyonce/-/async.util.onlyonce-0.5.2.tgz#b8e6fc004adc923164d79e32f2813ee465c24ff2" - integrity sha1-uOb8AErckjFk154y8oE+5GXCT/I= - -async.util.queue@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.queue/-/async.util.queue-0.5.2.tgz#57f65abe1a3cdf273d31abd28ab95425f8222ee5" - integrity sha1-V/Zavho83yc9MavSirlUJfgiLuU= - dependencies: - async.util.arrayeach "0.5.2" - async.util.isarray "0.5.2" - async.util.map "0.5.2" - async.util.noop "0.5.2" - async.util.onlyonce "0.5.2" - async.util.setimmediate "0.5.2" - -async.util.setimmediate@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.setimmediate/-/async.util.setimmediate-0.5.2.tgz#2812ebabf2a58027758d4bc7793d1ccfaf10255f" - integrity sha1-KBLrq/KlgCd1jUvHeT0cz68QJV8= - async@1.x, async@^1.4.2, async@^1.5.2, async@~1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -6225,11 +6176,6 @@ babel-plugin-minify-type-constructors@^0.4.3: dependencies: babel-helper-is-void-0 "^0.4.3" -babel-plugin-mock-imports@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-mock-imports/-/babel-plugin-mock-imports-1.0.1.tgz#1476ed4de911347d344fc81caab4beced80804b1" - integrity sha512-Nu4unCGKeqOfLlfnLPnv/pEHancdAGTqFqyArZ27gsKIiKxeZvMr87IHB8BxhMu3Bfc8fA8bx7hWt32aZbEwpQ== - babel-plugin-named-asset-import@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.3.tgz#9ba2f3ac4dc78b042651654f07e847adfe50667c" @@ -14345,13 +14291,6 @@ gulp-mocha@^7.0.2: supports-color "^7.0.0" through2 "^3.0.1" -gulp-multi-process@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/gulp-multi-process/-/gulp-multi-process-1.3.1.tgz#e12aa818e4c234357ad99d5caff8df8a18f46e9e" - integrity sha512-okxYy3mxUkekM0RNjkBg8OPuzpnD2yXMAdnGOaQPSJ2wzBdE9R9pkTV+tzPZ65ORK7b57YUc6s+gROA4+EIOLg== - dependencies: - async.queue "^0.5.2" - gulp-rename@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-1.4.0.tgz#de1c718e7c4095ae861f7296ef4f3248648240bd" From cc0ef60a883416167c6b51d6e57c58dde32bb747 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:39:26 -0700 Subject: [PATCH 155/191] [npm] Removes ansicolors (#49274) Originally used in the functional test runners pro runner, it is no longer used. Signed-off-by: Tyler Smalley --- x-pack/package.json | 1 - yarn.lock | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index 8bb3c683fa290..2e218fbef67a1 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -111,7 +111,6 @@ "@types/xml-crypto": "^1.4.0", "@types/xml2js": "^0.4.5", "abab": "^1.0.4", - "ansicolors": "0.3.2", "axios": "^0.19.0", "babel-jest": "^24.9.0", "babel-plugin-inline-react-svg": "^1.1.0", diff --git a/yarn.lock b/yarn.lock index 5b82466674428..6f1c757e7878d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5077,16 +5077,16 @@ ansi@^0.3.0, ansi@~0.3.1: resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" integrity sha1-DELU+xcWDVqa8eSEus4cZpIsGyE= -ansicolors@0.3.2, ansicolors@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" - integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= - ansicolors@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" integrity sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8= +ansicolors@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" + integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= + any-base@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe" From a56d2d8b8582c207cdea516819c00954c2f638d3 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:39:53 -0700 Subject: [PATCH 156/191] [npm] Removes @slack/client (#49273) Originally added in https://github.com/elastic/kibana/pull/19236 as part of the notification service, however it's no longer used. Signed-off-by: Tyler Smalley --- x-pack/package.json | 1 - yarn.lock | 109 +------------------------------------------- 2 files changed, 1 insertion(+), 109 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index 2e218fbef67a1..c2749dd517a2e 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -206,7 +206,6 @@ "@mapbox/mapbox-gl-draw": "^1.1.1", "@samverschueren/stream-to-observable": "^0.3.0", "@scant/router": "^0.1.0", - "@slack/client": "^4.8.0", "@slack/webhook": "^5.0.0", "@turf/boolean-contains": "6.0.1", "angular-resource": "1.7.8", diff --git a/yarn.lock b/yarn.lock index 6f1c757e7878d..f5a9465bc794d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2418,35 +2418,6 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== -"@slack/client@^4.8.0": - version "4.8.0" - resolved "https://registry.yarnpkg.com/@slack/client/-/client-4.8.0.tgz#265606f1cebae1d72f3fdd2cdf7cf1510783dde4" - integrity sha512-c4PKsRMtTp3QVYg+6cNqqxbU/50gnYfMlZgPCGUuMDMm9mkx50y0PEuERcVyLIe5j61imrhQx9DoNIfybEhTTw== - dependencies: - "@types/form-data" "^2.2.1" - "@types/is-stream" "^1.1.0" - "@types/loglevel" "^1.5.3" - "@types/node" ">=6.0.0" - "@types/p-cancelable" "^0.3.0" - "@types/p-queue" "^2.3.1" - "@types/p-retry" "^1.0.1" - "@types/retry" "^0.10.2" - "@types/ws" "^5.1.1" - axios "^0.18.0" - eventemitter3 "^3.0.0" - finity "^0.5.4" - form-data "^2.3.1" - is-stream "^1.1.0" - loglevel "^1.6.1" - object.entries "^1.0.4" - object.getownpropertydescriptors "^2.0.3" - object.values "^1.0.4" - p-cancelable "^0.3.0" - p-queue "^2.3.0" - p-retry "^2.0.0" - retry "^0.12.0" - ws "^5.2.0" - "@slack/types@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@slack/types/-/types-1.0.0.tgz#1dc7a63b293c4911e474197585c3feda012df17a" @@ -3308,13 +3279,6 @@ resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.0.tgz#cbb49815a5e1129d5f23836a98d65d93822409af" integrity sha512-dxdRrUov2HVTbSRFX+7xwUPlbGYVEZK6PrSqClg2QPos3PNe0bCajkDDkDeeC1znjSH03KOEqVbXpnJuWa2wgQ== -"@types/form-data@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e" - integrity sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ== - dependencies: - "@types/node" "*" - "@types/fs-extra@5.0.4": version "5.0.4" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.4.tgz#b971134d162cc0497d221adde3dbb67502225599" @@ -3473,13 +3437,6 @@ resolved "https://registry.yarnpkg.com/@types/is-glob/-/is-glob-4.0.0.tgz#fb8a2bff539025d4dcd6d5efe7689e03341b876d" integrity sha512-zC/2EmD8scdsGIeE+Xg7kP7oi9VP90zgMQtm9Cr25av4V+a+k8slQyiT60qSw8KORYrOKlPXfHwoa1bQbRzskQ== -"@types/is-stream@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@types/is-stream/-/is-stream-1.1.0.tgz#b84d7bb207a210f2af9bed431dc0fbe9c4143be1" - integrity sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg== - dependencies: - "@types/node" "*" - "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -3617,11 +3574,6 @@ resolved "https://registry.yarnpkg.com/@types/log-symbols/-/log-symbols-2.0.0.tgz#7919e2ec3c8d13879bfdcab310dd7a3f7fc9466d" integrity sha512-YJhbp0sz3egFFKl3BcCNPQKzuGFOP4PACcsifhK6ROGnJUW9ViYLuLybQ9GQZm7Zejy3tkGuiXYMq3GiyGkU4g== -"@types/loglevel@^1.5.3": - version "1.5.3" - resolved "https://registry.yarnpkg.com/@types/loglevel/-/loglevel-1.5.3.tgz#adfce55383edc5998a2170ad581b3e23d6adb5b8" - integrity sha512-TzzIZihV+y9kxSg5xJMkyIkaoGkXi50isZTtGHObNHRqAAwjGNjSCNPI7AUAv0tZUKTq9f2cdkCUd/2JVZUTrA== - "@types/lru-cache@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03" @@ -3718,7 +3670,7 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@10.12.27", "@types/node@8.5.8", "@types/node@>=6.0.0", "@types/node@>=8.9.0", "@types/node@^10.12.27", "@types/node@^12.0.2": +"@types/node@*", "@types/node@10.12.27", "@types/node@8.5.8", "@types/node@>=8.9.0", "@types/node@^10.12.27", "@types/node@^12.0.2": version "10.12.27" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.27.tgz#eb3843f15d0ba0986cc7e4d734d2ee8b50709ef8" integrity sha512-e9wgeY6gaY21on3ve0xAjgBVjGDWq/xUteK0ujsE53bUoxycMkqfnkUgMt6ffZtykZ5X12Mg3T7Pw4TRCObDKg== @@ -3761,23 +3713,6 @@ dependencies: "@types/node" "*" -"@types/p-cancelable@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@types/p-cancelable/-/p-cancelable-0.3.0.tgz#3e4fcc54a3dfd81d0f5b93546bb68d0df50553bb" - integrity sha512-sP+9Ivnpil7cdmvr5O+145aXm65YX8Y+Lrul1ojdYz6yaE05Dqonn6Z9v5eqJCQ0UeSGcTRtepMlZDh9ywdKgw== - -"@types/p-queue@^2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@types/p-queue/-/p-queue-2.3.1.tgz#2fb251e46e884e31c4bd1bf58f0e188972353ff4" - integrity sha512-JyO7uMAtkcMMULmsTQ4t/lCC8nxirTtweGG1xAFNNIAoC1RemmeIxq8PiKghuEy99XdbS6Lwx4zpbXUjfeSSAA== - -"@types/p-retry@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/p-retry/-/p-retry-1.0.1.tgz#2302bc3da425014208c8a9b68293d37325124785" - integrity sha512-HgQPG9kkUb4EpTeUv2taH2nBZsVUb5aOTSw3X2YozcTG1ttmGcLaLKx1MbAz1evVfUEDTCAPmdz2HiFztIyWrw== - dependencies: - "@types/retry" "*" - "@types/papaparse@^4.5.11": version "4.5.11" resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-4.5.11.tgz#dcd4f64da55f768c2e2cf92ccac1973c67a73890" @@ -3977,11 +3912,6 @@ "@types/tough-cookie" "*" form-data "^2.5.0" -"@types/retry@*", "@types/retry@^0.10.2": - version "0.10.2" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.10.2.tgz#bd1740c4ad51966609b058803ee6874577848b37" - integrity sha512-LqJkY4VQ7S09XhI7kA3ON71AxauROhSv74639VsNXC9ish4IWHnIi98if+nP1MxQV3RMPqXSCYgpPsDHjlg9UQ== - "@types/selenium-webdriver@^4.0.3": version "4.0.3" resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-4.0.3.tgz#388f12c464cc1fff5d4c84cb372f19b9ab9b5c81" @@ -4202,14 +4132,6 @@ resolved "https://registry.yarnpkg.com/@types/write-pkg/-/write-pkg-3.1.0.tgz#f58767f4fb9a6a3ad8e95d3e9cd1f2d026ceab26" integrity sha512-JRGsPEPCrYqTXU0Cr+Yu7esPBE2yvH7ucOHr+JuBy0F59kglPvO5gkmtyEvf3P6dASSkScvy/XQ6SC1QEBFDuA== -"@types/ws@^5.1.1": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-5.1.2.tgz#f02d3b1cd46db7686734f3ce83bdf46c49decd64" - integrity sha512-NkTXUKTYdXdnPE2aUUbGOXE1XfMK527SCvU/9bj86kyFF6kZ9ZnOQ3mK5jADn98Y2vEUD/7wKDgZa7Qst2wYOg== - dependencies: - "@types/events" "*" - "@types/node" "*" - "@types/xml-crypto@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@types/xml-crypto/-/xml-crypto-1.4.0.tgz#b586e4819f6bdd0571a3faa9a8098049d5c3cc5a" @@ -12599,11 +12521,6 @@ fined@^1.0.1: object.pick "^1.2.0" parse-filepath "^1.0.1" -finity@^0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/finity/-/finity-0.5.4.tgz#f2a8a9198e8286467328ec32c8bfcc19a2229c11" - integrity sha512-3l+5/1tuw616Lgb0QBimxfdd2TqaDGpfCBpfX6EqtFmqUV3FtQnVEX4Aa62DagYEqnsTIjZcTfbq9msDbXYgyA== - first-chunk-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70" @@ -18471,11 +18388,6 @@ logform@^2.1.1: ms "^2.1.1" triple-beam "^1.3.0" -loglevel@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" - integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= - loglevel@^1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.4.tgz#f408f4f006db8354d0577dcf6d33485b3cb90d56" @@ -20974,23 +20886,11 @@ p-map@^3.0.0: dependencies: aggregate-error "^3.0.0" -p-queue@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-2.4.2.tgz#03609826682b743be9a22dba25051bd46724fc34" - integrity sha512-n8/y+yDJwBjoLQe1GSJbbaYQLTI7QHNZI2+rpmCDbe++WLf9HC3gf6iqj5yfPAV71W4UF3ql5W1+UBPXoXTxng== - p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= -p-retry@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-2.0.0.tgz#b97f1f4d6d81a3c065b2b40107b811e995c1bfba" - integrity sha512-ZbCuzAmiwJ45q4evp/IG9D+5MUllGSUeCWwPt3j/tdYSi1KPkSD+46uqmAA1LhccDhOXv8kYZKNb8x78VflzfA== - dependencies: - retry "^0.12.0" - p-retry@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" @@ -30108,13 +30008,6 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" - integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== - dependencies: - async-limiter "~1.0.0" - ws@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.0.tgz#13806d9913b2a5f3cbb9ba47b563c002cbc7c526" From 7ecf5ac9357f26abc6e51e6baac52e0fbe35234b Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 07:40:27 -0700 Subject: [PATCH 157/191] [npm] Removes stream-to-observable (#49272) Added in https://github.com/elastic/kibana/pull/18885 as part of the RxJS 6 upgrade and used in the screenshot stictcher, however it is not longer used. Signed-off-by: Tyler Smalley --- x-pack/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/package.json b/x-pack/package.json index c2749dd517a2e..79796cd9be30e 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -204,7 +204,6 @@ "@kbn/interpreter": "1.0.0", "@kbn/ui-framework": "1.0.0", "@mapbox/mapbox-gl-draw": "^1.1.1", - "@samverschueren/stream-to-observable": "^0.3.0", "@scant/router": "^0.1.0", "@slack/webhook": "^5.0.0", "@turf/boolean-contains": "6.0.1", From 909d28fe386a71506bcfa1d9c14799ba7be956e1 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 25 Oct 2019 15:59:31 +0100 Subject: [PATCH 158/191] [ML] Fixing edit buttons in advanced wizard summary (#49324) --- .../components/advanced_view/detector_list.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx index b82cc9b9c24bc..d11ef8164169a 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx @@ -108,9 +108,11 @@ export const DetectorList: FC = ({ isActive, onEditJob, onDeleteJob }) => detectorToString(d) )} - - - + {isActive && ( + + + + )} {d.detector_description !== undefined && ( From 9acc18095bde9d4e4159cff156003ff1d275ff98 Mon Sep 17 00:00:00 2001 From: Brandon Kobel Date: Fri, 25 Oct 2019 08:23:09 -0700 Subject: [PATCH 159/191] Fixing kibana.yml doc comments for elasticsearch.ssl.certificate/key (#49262) --- config/kibana.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/kibana.yml b/config/kibana.yml index 9525a6423d90a..47482f9e6d59f 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -50,7 +50,8 @@ #server.ssl.key: /path/to/your/server.key # Optional settings that provide the paths to the PEM-format SSL certificate and key files. -# These files validate that your Elasticsearch backend uses the same key files. +# These files are used to verify the identity of Kibana to Elasticsearch and are required when +# xpack.ssl.verification_mode in Elasticsearch is set to either certificate or full. #elasticsearch.ssl.certificate: /path/to/your/client.crt #elasticsearch.ssl.key: /path/to/your/client.key From 8499cfd0f900d57b1ba6ee6ed43698f8e43239ff Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 25 Oct 2019 17:53:45 +0200 Subject: [PATCH 160/191] ensure loading order (#49316) --- src/legacy/core_plugins/kibana/public/home/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/home/index.js b/src/legacy/core_plugins/kibana/public/home/index.js index 829d1ef8f0ba4..8a8680eeba47c 100644 --- a/src/legacy/core_plugins/kibana/public/home/index.js +++ b/src/legacy/core_plugins/kibana/public/home/index.js @@ -36,12 +36,12 @@ const homeTitle = i18n.translate('kbn.home.breadcrumbs.homeTitle', { defaultMess function getRoute() { return { template, - controller($scope) { - const { chrome, addBasePath, getFeatureCatalogueRegistryProvider } = getServices(); - getFeatureCatalogueRegistryProvider().then(catalogue => { - $scope.directories = catalogue.inTitleOrder; - $scope.$digest(); - }); + resolve: { + directories: () => getServices().getFeatureCatalogueRegistryProvider().then(catalogue => catalogue.inTitleOrder) + }, + controller($scope, $route) { + const { chrome, addBasePath } = getServices(); + $scope.directories = $route.current.locals.directories; $scope.recentlyAccessed = chrome.recentlyAccessed.get().map(item => { item.link = addBasePath(item.link); return item; From 91a5664b4f591c5244fe6b04c47809f62959e347 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Fri, 25 Oct 2019 12:09:41 -0400 Subject: [PATCH 161/191] [Lens] Text updates (#48964) * [Lens] Text updates * Update per comments * Update text for datapanel * Fix tests --- .../editor_frame/chart_switch.tsx | 8 +-- .../editor_frame/suggestion_panel.tsx | 33 +++++---- .../change_indexpattern.tsx | 14 +++- .../public/indexpattern_plugin/datapanel.tsx | 26 ++++--- .../public/indexpattern_plugin/field_item.tsx | 14 ++-- .../indexpattern_plugin/indexpattern.test.ts | 4 +- .../operations/definitions/count.tsx | 2 +- .../operations/definitions/date_histogram.tsx | 2 +- .../metric_expression.tsx | 4 +- .../public/xy_visualization_plugin/types.ts | 8 +-- .../xy_config_panel.tsx | 68 +++++++++++-------- .../xy_visualization_plugin/xy_expression.tsx | 6 +- .../xy_visualization.test.ts | 18 ++--- .../xy_visualization.tsx | 6 +- 14 files changed, 122 insertions(+), 91 deletions(-) diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx index 26db1224eb352..2e95aa10bf4db 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx @@ -52,8 +52,8 @@ function VisualizationSummary(props: Props) { if (!visualization) { return ( <> - {i18n.translate('xpack.lens.configPanel.chooseVisualization', { - defaultMessage: 'Choose a visualization', + {i18n.translate('xpack.lens.configPanel.selectVisualization', { + defaultMessage: 'Select a visualization', })} ); @@ -201,8 +201,8 @@ export function ChartSwitch(props: Props) { anchorPosition="downLeft" > - {i18n.translate('xpack.lens.configPanel.chooseVisualization', { - defaultMessage: 'Choose a visualization', + {i18n.translate('xpack.lens.configPanel.selectVisualization', { + defaultMessage: 'Select a visualization', })} diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx index 7d1f400f484e1..e2f9bd84560de 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx @@ -259,20 +259,27 @@ export function SuggestionPanel({ {stagedPreview && ( - { - trackUiEvent('suggestion_confirmed'); - dispatch({ - type: 'SUBMIT_SUGGESTION', - }); - }} - > - {i18n.translate('xpack.lens.sugegstion.confirmSuggestionLabel', { - defaultMessage: 'Reload suggestions', + + > + { + trackUiEvent('suggestion_confirmed'); + dispatch({ + type: 'SUBMIT_SUGGESTION', + }); + }} + > + {i18n.translate('xpack.lens.sugegstion.refreshSuggestionLabel', { + defaultMessage: 'Refresh', + })} + + )} diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/change_indexpattern.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/change_indexpattern.tsx index dc42b97cce08d..4d9bc6276d52a 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/change_indexpattern.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/change_indexpattern.tsx @@ -5,8 +5,15 @@ */ import _ from 'lodash'; +import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; -import { EuiButtonEmpty, EuiPopover, EuiSelectable, EuiButtonEmptyProps } from '@elastic/eui'; +import { + EuiButtonEmpty, + EuiPopover, + EuiPopoverTitle, + EuiSelectable, + EuiButtonEmptyProps, +} from '@elastic/eui'; import { EuiSelectableProps } from '@elastic/eui/src/components/selectable/selectable'; import { IndexPatternRef } from './types'; import { trackUiEvent } from '../lens_ui_telemetry'; @@ -62,6 +69,11 @@ export function ChangeIndexPattern({ ownFocus >
+ + {i18n.translate('xpack.lens.indexPattern.changeIndexPatternTitle', { + defaultMessage: 'Change index pattern', + })} + } @@ -441,31 +441,35 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ {paginatedFields.length === 0 && (

- - {showEmptyFields - ? i18n.translate('xpack.lens.indexPatterns.hiddenFieldsLabel', { + {showEmptyFields + ? localState.typeFilter.length || localState.nameFilter.length + ? i18n.translate('xpack.lens.indexPatterns.noFilteredFieldsLabel', { defaultMessage: - 'No fields have data with the current filters. You can show fields without data using the filters above.', + 'No fields match the current filters. Try changing your filters or time range.', }) : i18n.translate('xpack.lens.indexPatterns.noFieldsLabel', { - defaultMessage: 'No fields in {title} can be visualized.', - values: { title: currentIndexPattern.title }, - })} - + defaultMessage: 'No fields exist in this index pattern.', + }) + : i18n.translate('xpack.lens.indexPatterns.emptyFieldsWithDataLabel', { + defaultMessage: + 'No fields have data with the current filters and time range. Try changing your filters or time range.', + })}

+ {(!showEmptyFields || localState.typeFilter.length || localState.nameFilter.length) && ( { - trackUiEvent('show_empty_fields_clicked'); + trackUiEvent('indexpattern_show_all_fields_clicked'); clearLocalState(); onToggleEmptyFields(true); }} > {i18n.translate('xpack.lens.indexPatterns.showAllFields.buttonText', { - defaultMessage: 'Show All Fields', + defaultMessage: 'Show all fields', })} )} diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx index 41a4bd3549dc1..79a3ac4137f88 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_item.tsx @@ -174,10 +174,8 @@ export function FieldItem(props: FieldItemProps) { togglePopover(); } }} - aria-label={i18n.translate('xpack.lens.indexPattern.fieldStatsButtonAriaLabel', { - defaultMessage: - 'Click or press Enter for information about {fieldName}. Or, drag field into visualization.', - values: { fieldName: field.name }, + aria-label={i18n.translate('xpack.lens.indexPattern.fieldStatsButtonLabel', { + defaultMessage: 'Click for a field preview. Or, drag and drop to visualize.', })} > @@ -188,10 +186,8 @@ export function FieldItem(props: FieldItemProps) { {i18n.translate('xpack.lens.indexPattern.fieldStatsNoData', { - defaultMessage: 'No data to display', + defaultMessage: 'No data to display.', })}
); diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts index 845cfa29d5724..b4f01078f1f78 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts @@ -240,7 +240,7 @@ describe('IndexPattern Data Source', () => { columnOrder: ['col1', 'col2'], columns: { col1: { - label: 'Count of Documents', + label: 'Count of records', dataType: 'number', isBucketed: false, @@ -272,7 +272,7 @@ describe('IndexPattern Data Source', () => { metricsAtAllLevels=false partialRows=false includeFormatHints=true - aggConfigs={lens_auto_date aggConfigs='[{\\"id\\":\\"col1\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}},{\\"id\\":\\"col2\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"timestamp\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"1d\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}}]'} | lens_rename_columns idMap='{\\"col-0-col1\\":{\\"label\\":\\"Count of Documents\\",\\"dataType\\":\\"number\\",\\"isBucketed\\":false,\\"operationType\\":\\"count\\",\\"id\\":\\"col1\\"},\\"col-1-col2\\":{\\"label\\":\\"Date\\",\\"dataType\\":\\"date\\",\\"isBucketed\\":true,\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"timestamp\\",\\"params\\":{\\"interval\\":\\"1d\\"},\\"id\\":\\"col2\\"}}'" + aggConfigs={lens_auto_date aggConfigs='[{\\"id\\":\\"col1\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}},{\\"id\\":\\"col2\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"timestamp\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"1d\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}}]'} | lens_rename_columns idMap='{\\"col-0-col1\\":{\\"label\\":\\"Count of records\\",\\"dataType\\":\\"number\\",\\"isBucketed\\":false,\\"operationType\\":\\"count\\",\\"id\\":\\"col1\\"},\\"col-1-col2\\":{\\"label\\":\\"Date\\",\\"dataType\\":\\"date\\",\\"isBucketed\\":true,\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"timestamp\\",\\"params\\":{\\"interval\\":\\"1d\\"},\\"id\\":\\"col2\\"}}'" `); }); }); diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/count.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/count.tsx index 68a36787ec189..94cb17b340c36 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/count.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/count.tsx @@ -9,7 +9,7 @@ import { OperationDefinition } from '.'; import { ParameterlessIndexPatternColumn, BaseIndexPatternColumn } from './column_types'; const countLabel = i18n.translate('xpack.lens.indexPattern.countOf', { - defaultMessage: 'Count of documents', + defaultMessage: 'Count of records', }); export type CountIndexPatternColumn = ParameterlessIndexPatternColumn< diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx index 89c4899bb8e56..e5c00542df7d3 100644 --- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx +++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx @@ -16,7 +16,7 @@ import { IndexPattern } from '../../types'; type PropType = C extends React.ComponentType ? P : unknown; const autoInterval = 'auto'; -const supportedIntervals = ['M', 'w', 'd', 'h']; +const supportedIntervals = ['M', 'w', 'd', 'h', 'm']; const defaultCustomInterval = supportedIntervals[2]; // Add ticks to EuiRange component props diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.tsx index 68de585771a79..407c754284671 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.tsx +++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.tsx @@ -76,8 +76,8 @@ export const getMetricChartRenderer = ( formatFactory: FormatFactory ): IInterpreterRenderFunction => ({ name: 'lens_metric_chart_renderer', - displayName: 'Metric Chart', - help: 'Metric Chart Renderer', + displayName: 'Metric chart', + help: 'Metric chart renderer', validate: () => {}, reuseDomNode: true, render: async (domNode: Element, config: MetricChartProps, _handlers: unknown) => { diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/types.ts b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/types.ts index de81cc208070a..f81eb9d72d6ae 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/types.ts +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/types.ts @@ -241,7 +241,7 @@ export const visualizationTypes: VisualizationType[] = [ icon: 'visBarHorizontal', largeIcon: chartBarHorizontalSVG, label: i18n.translate('xpack.lens.xyVisualization.barHorizontalLabel', { - defaultMessage: 'Horizontal Bar', + defaultMessage: 'Horizontal bar', }), }, { @@ -249,7 +249,7 @@ export const visualizationTypes: VisualizationType[] = [ icon: 'visBarVerticalStacked', largeIcon: chartBarStackedSVG, label: i18n.translate('xpack.lens.xyVisualization.stackedBarLabel', { - defaultMessage: 'Stacked Bar', + defaultMessage: 'Stacked bar', }), }, { @@ -257,7 +257,7 @@ export const visualizationTypes: VisualizationType[] = [ icon: 'visBarHorizontalStacked', largeIcon: chartBarHorizontalStackedSVG, label: i18n.translate('xpack.lens.xyVisualization.stackedBarHorizontalLabel', { - defaultMessage: 'Stacked Horizontal Bar', + defaultMessage: 'Stacked horizontal bar', }), }, { @@ -281,7 +281,7 @@ export const visualizationTypes: VisualizationType[] = [ icon: 'visAreaStacked', largeIcon: chartAreaStackedSVG, label: i18n.translate('xpack.lens.xyVisualization.stackedAreaLabel', { - defaultMessage: 'Stacked Area', + defaultMessage: 'Stacked area', }), }, ]; diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx index f285cb90f225a..f59b1520dbbb4 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx @@ -20,6 +20,7 @@ import { EuiSpacer, EuiButtonEmpty, EuiPopoverFooter, + EuiToolTip, } from '@elastic/eui'; import { State, SeriesType, LayerConfig, visualizationTypes } from './types'; import { VisualizationProps, OperationMetadata } from '../types'; @@ -235,7 +236,7 @@ export function XYConfigPanel(props: VisualizationProps) { ) { ))} - { - trackUiEvent('xy_layer_added'); - const usedSeriesTypes = _.uniq(state.layers.map(layer => layer.seriesType)); - setState({ - ...state, - layers: [ - ...state.layers, - newLayerState( - usedSeriesTypes.length === 1 ? usedSeriesTypes[0] : state.preferredSeriesType, - frame.addNewLayer() - ), - ], - }); - }} - iconType="plusInCircleFilled" - /> + + + { + trackUiEvent('xy_layer_added'); + const usedSeriesTypes = _.uniq(state.layers.map(layer => layer.seriesType)); + setState({ + ...state, + layers: [ + ...state.layers, + newLayerState( + usedSeriesTypes.length === 1 ? usedSeriesTypes[0] : state.preferredSeriesType, + frame.addNewLayer() + ), + ], + }); + }} + iconType="plusInCircleFilled" + /> + + ); } diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx index 4529179debd26..3871abcd53c1e 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx @@ -98,9 +98,9 @@ export const getXyChartRenderer = (dependencies: { timeZone: string; }): IInterpreterRenderFunction => ({ name: 'lens_xy_chart_renderer', - displayName: 'XY Chart', + displayName: 'XY chart', help: i18n.translate('xpack.lens.xyChart.renderer.help', { - defaultMessage: 'X/Y Chart Renderer', + defaultMessage: 'X/Y chart renderer', }), validate: () => {}, reuseDomNode: true, @@ -238,7 +238,7 @@ export function XYChart({ data, args, formatFactory, timeZone }: XYChartRenderPr const rows = data.tables[layerId].rows.map(row => { const newRow: typeof row = {}; - // Remap data to { 'Count of documents': 5 } + // Remap data to { 'Count of records': 5 } Object.keys(row).forEach(key => { if (columnToLabelMap[key]) { newRow[columnToLabelMap[key]] = row[key]; diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts index 4b03c6c346ce5..db28e76f82946 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts @@ -47,7 +47,7 @@ describe('xy_visualization', () => { it('should show mixed xy chart when multilple series types', () => { const desc = xyVisualization.getDescription(mixedState('bar', 'line')); - expect(desc.label).toEqual('Mixed XY Chart'); + expect(desc.label).toEqual('Mixed XY chart'); }); it('should show the preferredSeriesType if there are no layers', () => { @@ -56,7 +56,7 @@ describe('xy_visualization', () => { // 'test-file-stub' is a hack, but it at least means we aren't using // a standard icon here. expect(desc.icon).toEqual('test-file-stub'); - expect(desc.label).toEqual('Bar Chart'); + expect(desc.label).toEqual('Bar chart'); }); it('should show mixed horizontal bar chart when multiple horizontal bar types', () => { @@ -64,23 +64,23 @@ describe('xy_visualization', () => { mixedState('bar_horizontal', 'bar_horizontal_stacked') ); - expect(desc.label).toEqual('Mixed Horizontal Bar Chart'); + expect(desc.label).toEqual('Mixed horizontal bar chart'); }); it('should show bar chart when bar only', () => { const desc = xyVisualization.getDescription(mixedState('bar_horizontal', 'bar_horizontal')); - expect(desc.label).toEqual('Horizontal Bar Chart'); + expect(desc.label).toEqual('Horizontal bar chart'); }); it('should show the chart description if not mixed', () => { - expect(xyVisualization.getDescription(mixedState('area')).label).toEqual('Area Chart'); - expect(xyVisualization.getDescription(mixedState('line')).label).toEqual('Line Chart'); + expect(xyVisualization.getDescription(mixedState('area')).label).toEqual('Area chart'); + expect(xyVisualization.getDescription(mixedState('line')).label).toEqual('Line chart'); expect(xyVisualization.getDescription(mixedState('area_stacked')).label).toEqual( - 'Stacked Area Chart' + 'Stacked area chart' ); expect(xyVisualization.getDescription(mixedState('bar_horizontal_stacked')).label).toEqual( - 'Stacked Horizontal Bar Chart' + 'Stacked horizontal bar chart' ); }); }); @@ -119,7 +119,7 @@ describe('xy_visualization', () => { "position": "right", }, "preferredSeriesType": "bar_stacked", - "title": "Empty XY Chart", + "title": "Empty XY chart", } `); }); diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx index b56e0d9deb55e..5ba77cb39d5f8 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx @@ -54,7 +54,7 @@ function getDescription(state?: State) { ? visualizationType.label : isHorizontalChart(state.layers) ? i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', { - defaultMessage: 'Mixed Horizontal Bar', + defaultMessage: 'Mixed horizontal bar', }) : i18n.translate('xpack.lens.xyVisualization.mixedLabel', { defaultMessage: 'Mixed XY', @@ -70,7 +70,7 @@ export const xyVisualization: Visualization = { getDescription(state) { const { icon, label } = getDescription(state); const chartLabel = i18n.translate('xpack.lens.xyVisualization.chartLabel', { - defaultMessage: '{label} Chart', + defaultMessage: '{label} chart', values: { label }, }); @@ -93,7 +93,7 @@ export const xyVisualization: Visualization = { initialize(frame, state) { return ( state || { - title: 'Empty XY Chart', + title: 'Empty XY chart', legend: { isVisible: true, position: Position.Right }, preferredSeriesType: defaultSeriesType, layers: [ From fcc9ea369a09949af28ef0e4863ec0ed2ba87816 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 09:22:14 -0700 Subject: [PATCH 162/191] [npm] Removes unused dependencies (#49287) * [npm] Remove mochawesome-report-generator * [npm] Remove babel-plugin-transform-react-remove-prop-types * [npm] Removing popper.js * [npm] Remove stream-stream * [npm] Remove react-redux-request Signed-off-by: Tyler Smalley --- package.json | 1 - x-pack/package.json | 4 ---- yarn.lock | 20 +++----------------- 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 91af1a017e91a..04ce14a9f3692 100644 --- a/package.json +++ b/package.json @@ -237,7 +237,6 @@ "rxjs": "^6.2.1", "script-loader": "0.7.2", "semver": "^5.5.0", - "stream-stream": "^1.2.6", "style-it": "^2.1.3", "style-loader": "0.23.1", "symbol-observable": "^1.2.0", diff --git a/x-pack/package.json b/x-pack/package.json index 79796cd9be30e..09511d88f073b 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -115,7 +115,6 @@ "babel-jest": "^24.9.0", "babel-plugin-inline-react-svg": "^1.1.0", "babel-plugin-require-context-hook": "npm:babel-plugin-require-context-hook-babel7@1.0.0", - "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "base64-js": "^1.3.1", "base64url": "^3.0.1", "chalk": "^2.4.2", @@ -151,7 +150,6 @@ "mocha-multi-reporters": "^1.1.7", "mochawesome": "^4.1.0", "mochawesome-merge": "^2.0.1", - "mochawesome-report-generator": "^4.0.1", "mustache": "^2.3.0", "mutation-observer": "^1.0.3", "node-fetch": "^2.6.0", @@ -301,7 +299,6 @@ "pluralize": "3.1.0", "pngjs": "3.4.0", "polished": "^1.9.2", - "popper.js": "^1.14.3", "postcss-prefix-selector": "^1.7.2", "prop-types": "^15.6.0", "proper-lockfile": "^3.2.0", @@ -321,7 +318,6 @@ "react-monaco-editor": "~0.27.0", "react-portal": "^3.2.0", "react-redux": "^5.1.1", - "react-redux-request": "^1.5.6", "react-resize-detector": "^4.2.0", "react-reverse-portal": "^1.0.4", "react-router-dom": "^4.3.1", diff --git a/yarn.lock b/yarn.lock index f5a9465bc794d..8d57c549c96d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6157,7 +6157,7 @@ babel-plugin-transform-property-literals@^6.9.4: dependencies: esutils "^2.0.2" -babel-plugin-transform-react-remove-prop-types@0.4.24, babel-plugin-transform-react-remove-prop-types@^0.4.24: +babel-plugin-transform-react-remove-prop-types@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== @@ -19372,7 +19372,7 @@ mochawesome-merge@^2.0.1: uuid "^3.3.2" yargs "^12.0.5" -mochawesome-report-generator@^4.0.0, mochawesome-report-generator@^4.0.1: +mochawesome-report-generator@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/mochawesome-report-generator/-/mochawesome-report-generator-4.0.1.tgz#0a010d1ecf379eb26ba05300feb59e2665076080" integrity sha512-hQbmQt8/yCT68GjrQFat+Diqeuka3haNllexYfja1+y0hpwi3yCJwFpQCdWK9ezzcXL3Nu80f2I6SZeyspwsqg== @@ -21655,7 +21655,7 @@ polished@^3.3.1: dependencies: "@babel/runtime" "^7.4.5" -popper.js@^1.14.1, popper.js@^1.14.3, popper.js@^1.14.7: +popper.js@^1.14.1, popper.js@^1.14.7: version "1.15.0" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2" integrity sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA== @@ -23052,15 +23052,6 @@ react-reconciler@^0.20.1: prop-types "^15.6.2" scheduler "^0.13.6" -react-redux-request@^1.5.6: - version "1.5.6" - resolved "https://registry.yarnpkg.com/react-redux-request/-/react-redux-request-1.5.6.tgz#8c514dc88264d225e113b4b54a265064e8020651" - integrity sha512-mzdG41GSLwynFI7DII3XNJxkABLD++I3Q1zlZWpcqycWSzWSYkjPUEz7M8r6aIIMzruANHQZX+asulvoaiwFRg== - dependencies: - lodash.get "^4.4.2" - lodash.isequal "^4.5.0" - prop-types "^15.6.1" - react-redux@^5.0.6, react-redux@^5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" @@ -26030,11 +26021,6 @@ stream-spigot@~2.1.2: dependencies: readable-stream "~1.1.0" -stream-stream@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/stream-stream/-/stream-stream-1.2.6.tgz#a9ae071c64c11b8584f52973f7715e37e5144c43" - integrity sha1-qa4HHGTBG4WE9Slz93FeN+UUTEM= - stream-to-observable@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" From b24e44c5b8d32deeb32a53e0e09d5bb0b695be66 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 09:23:04 -0700 Subject: [PATCH 163/191] Removes unused babel-plugin-inline-react-svg package (#49271) Signed-off-by: Tyler Smalley --- package.json | 1 - x-pack/package.json | 1 - yarn.lock | 55 ++------------------------------------------- 3 files changed, 2 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index 04ce14a9f3692..d5d4799d48c9f 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,6 @@ "**/typescript": "3.5.3", "**/graphql-toolkit/lodash": "^4.17.13", "**/isomorphic-git/**/base64-js": "^1.2.1", - "**/babel-plugin-inline-react-svg/svgo/js-yaml": "^3.13.1", "**/image-diff/gm/debug": "^2.6.9" }, "workspaces": { diff --git a/x-pack/package.json b/x-pack/package.json index 09511d88f073b..34cda1640f8df 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -113,7 +113,6 @@ "abab": "^1.0.4", "axios": "^0.19.0", "babel-jest": "^24.9.0", - "babel-plugin-inline-react-svg": "^1.1.0", "babel-plugin-require-context-hook": "npm:babel-plugin-require-context-hook-babel7@1.0.0", "base64-js": "^1.3.1", "base64url": "^3.0.1", diff --git a/yarn.lock b/yarn.lock index 8d57c549c96d3..da1f7c38b75f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5970,17 +5970,6 @@ babel-plugin-emotion@^9.2.11: source-map "^0.5.7" touch "^2.0.1" -babel-plugin-inline-react-svg@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-inline-react-svg/-/babel-plugin-inline-react-svg-1.1.0.tgz#b39519c78249b3fcf895b541c38b485a2b11b0be" - integrity sha512-Y/tBMi7Jh7Jh+DGcSNsY9/RW33nvcR067HFK0Dp+03jpidil1sJAffBdajK72xn3tbwMsgFLJubxW5xpQLJytA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/parser" "^7.0.0" - lodash.isplainobject "^4.0.6" - resolve "^1.10.0" - svgo "^0.7.2" - babel-plugin-istanbul@^5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.1.tgz#7981590f1956d75d67630ba46f0c22493588c893" @@ -7753,13 +7742,6 @@ circular-json@^0.5.5: resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.9.tgz#932763ae88f4f7dead7a0d09c8a51a4743a53b1d" integrity sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ== -clap@^1.0.9: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" - integrity sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA== - dependencies: - chalk "^1.1.3" - class-extend@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/class-extend/-/class-extend-0.1.2.tgz#8057a82b00f53f82a5d62c50ef8cffdec6fabc34" @@ -8063,13 +8045,6 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -coa@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" - integrity sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0= - dependencies: - q "^1.1.2" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -9121,14 +9096,6 @@ csso@^3.5.1: dependencies: css-tree "1.0.0-alpha.29" -csso@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" - integrity sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U= - dependencies: - clap "^1.0.9" - source-map "^0.5.3" - cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" @@ -16972,7 +16939,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@3.x, js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4, js-yaml@^3.9.0, js-yaml@~3.13.0, js-yaml@~3.13.1, js-yaml@~3.7.0: +js-yaml@3.13.1, js-yaml@3.x, js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4, js-yaml@^3.9.0, js-yaml@~3.13.0, js-yaml@~3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -24820,7 +24787,7 @@ sass-resources-loader@^2.0.1: glob "^7.1.1" loader-utils "^1.0.4" -sax@>=0.6.0, sax@^1.2.1, sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: +sax@>=0.6.0, sax@^1.2.1, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -26529,19 +26496,6 @@ svg-to-pdfkit@^0.1.7: dependencies: pdfkit ">=0.8.1" -svgo@^0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" - integrity sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U= - dependencies: - coa "~1.0.1" - colors "~1.1.2" - csso "~2.3.1" - js-yaml "~3.7.0" - mkdirp "~0.5.1" - sax "~1.2.1" - whet.extend "~0.9.9" - svgo@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.2.tgz#0253d34eccf2aed4ad4f283e11ee75198f9d7316" @@ -29694,11 +29648,6 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" -whet.extend@~0.9.9: - version "0.9.9" - resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" - integrity sha1-+HfVv2SMl+WqVC+twW1qJZucEaE= - which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" From 373320a3a0603a901e61803d5899c2395432701a Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Fri, 25 Oct 2019 09:38:13 -0700 Subject: [PATCH 164/191] [npm] Removes react-clipboard.js and redux-test-utils (#49283) * [npm] Removes react-clipboard.js Added in the original commit of APM, but does not appear to still be used. * [npm] Remove redux-test-utils Signed-off-by: Tyler Smalley --- x-pack/package.json | 2 -- yarn.lock | 24 +----------------------- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index 34cda1640f8df..089ce24b9a4ff 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -161,7 +161,6 @@ "react-hooks-testing-library": "^0.3.8", "react-test-renderer": "^16.8.0", "react-testing-library": "^6.0.0", - "redux-test-utils": "0.2.2", "sass-loader": "^7.3.1", "sass-resources-loader": "^2.0.1", "simple-git": "1.116.0", @@ -307,7 +306,6 @@ "react": "^16.8.0", "react-apollo": "^2.1.4", "react-beautiful-dnd": "^8.0.7", - "react-clipboard.js": "^1.1.2", "react-datetime": "^2.14.0", "react-dom": "^16.8.0", "react-dropzone": "^4.2.9", diff --git a/yarn.lock b/yarn.lock index da1f7c38b75f0..7de969ffae168 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7895,15 +7895,6 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= -clipboard@^1.6.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.7.1.tgz#360d6d6946e99a7a1fef395e42ba92b5e9b5a16b" - integrity sha1-Ng1taUbpmnof7zleQrqStem1oWs= - dependencies: - good-listener "^1.2.2" - select "^1.1.2" - tiny-emitter "^2.0.0" - clipboard@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d" @@ -21962,7 +21953,7 @@ prop-types@15.6.1: loose-envify "^1.3.1" object-assign "^4.1.1" -prop-types@15.7.2, prop-types@15.x, prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@15.7.2, prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -22592,14 +22583,6 @@ react-clientside-effect@^1.2.0: "@babel/runtime" "^7.0.0" shallowequal "^1.1.0" -react-clipboard.js@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/react-clipboard.js/-/react-clipboard.js-1.1.3.tgz#86feeb49364553ecd15aea91c75aa142532a60e0" - integrity sha512-97IKPinjiuFIBrCXqhNvKCBJFrSS1mmV5LVALE9djkweau26UWpR5VueYB3Eo3b2vfPtbyt0QUw06YOGdC0rpw== - dependencies: - clipboard "^1.6.1" - prop-types "^15.5.0" - react-color@^2.13.8: version "2.14.1" resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.14.1.tgz#db8ad4f45d81e74896fc2e1c99508927c6d084e0" @@ -23670,11 +23653,6 @@ redux-saga@^0.16.0: resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-0.16.2.tgz#993662e86bc945d8509ac2b8daba3a8c615cc971" integrity sha512-iIjKnRThI5sKPEASpUvySemjzwqwI13e3qP7oLub+FycCRDysLSAOwt958niZW6LhxfmS6Qm1BzbU70w/Koc4w== -redux-test-utils@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/redux-test-utils/-/redux-test-utils-0.2.2.tgz#593213f30173c5908f72315f08b705e1606094fe" - integrity sha512-+YsUHpzZJ7G85wYgllmGLJ75opIlWrCuKThaVTsHW5xLOrzaLE4abQ3AbYcHkx/vFOReG2D8XUwMfGnFKH8hGw== - redux-thunk@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" From c7a1c895b4b08a472f48e20aaac9bac95f8861c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2019 09:41:21 -0700 Subject: [PATCH 165/191] Update dependency @elastic/charts to ^13.5.8 (#49327) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d5d4799d48c9f..7aaf2573cc8de 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "dependencies": { "@babel/core": "^7.5.5", "@babel/register": "^7.5.5", - "@elastic/charts": "^13.5.7", + "@elastic/charts": "^13.5.8", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", "@elastic/eui": "14.7.0", diff --git a/yarn.lock b/yarn.lock index 7de969ffae168..a3752df9b024c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1064,10 +1064,10 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@elastic/charts@^13.5.7": - version "13.5.7" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-13.5.7.tgz#97ba458059613efd542ae68d7d2da059aac38484" - integrity sha512-8ibgrEJD3fpoLurB/DnNaWRmMGxAPHdtvCiPl1saPIjvlmGlrUNlXMneVgsPLqerNT0vuJDgqfQHHQcef/S2Hw== +"@elastic/charts@^13.5.8": + version "13.5.8" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-13.5.8.tgz#ae26371e373d79cb7fe5e7394711013e1416cb81" + integrity sha512-wXz5vVKwdbOhNZwRyd1py9YdVOGHmMJ4K+PERMIJ4VwAfjHimN1qieIVAKun9vfomt/j25tDhF3Kxq3XA9W0+g== dependencies: "@types/d3-shape" "^1.3.1" classnames "^2.2.6" From 58dbb130dc3e3b1971837a6587ea538596824a67 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Fri, 25 Oct 2019 12:42:31 -0400 Subject: [PATCH 166/191] [task manager] Kibana should start without task manager (#48568) * [task manager] Kibana should not fail to start without task manager * Check for task manager in maps * Lower log level * Update task registration --- x-pack/legacy/plugins/lens/index.ts | 1 + .../plugins/lens/server/usage/collectors.ts | 6 +++++- x-pack/legacy/plugins/lens/server/usage/task.ts | 17 ++++++++++++++--- x-pack/legacy/plugins/maps/index.js | 3 ++- .../maps_telemetry/maps_usage_collector.js | 7 ++++++- .../server/maps_telemetry/telemetry_task.js | 15 ++++++++++++++- x-pack/legacy/plugins/oss_telemetry/index.js | 2 +- .../visualizations/get_usage_collector.ts | 6 +++++- .../oss_telemetry/server/lib/tasks/index.ts | 7 ++++++- 9 files changed, 54 insertions(+), 10 deletions(-) diff --git a/x-pack/legacy/plugins/lens/index.ts b/x-pack/legacy/plugins/lens/index.ts index a8984bd80fb1c..20f92ebbe0654 100644 --- a/x-pack/legacy/plugins/lens/index.ts +++ b/x-pack/legacy/plugins/lens/index.ts @@ -18,6 +18,7 @@ export const lens: LegacyPluginInitializer = kibana => { return new kibana.Plugin({ id: PLUGIN_ID, configPrefix: `xpack.${PLUGIN_ID}`, + // task_manager could be required, but is only used for telemetry require: ['kibana', 'elasticsearch', 'xpack_main', 'interpreter', 'data'], publicDir: resolve(__dirname, 'public'), diff --git a/x-pack/legacy/plugins/lens/server/usage/collectors.ts b/x-pack/legacy/plugins/lens/server/usage/collectors.ts index 9a58026002ade..94a7c8e0d85c1 100644 --- a/x-pack/legacy/plugins/lens/server/usage/collectors.ts +++ b/x-pack/legacy/plugins/lens/server/usage/collectors.ts @@ -89,7 +89,11 @@ async function isTaskManagerReady(server: Server) { } async function getLatestTaskState(server: Server) { - const taskManager = server.plugins.task_manager!; + const taskManager = server.plugins.task_manager; + + if (!taskManager) { + return null; + } try { const result = await taskManager.fetch({ diff --git a/x-pack/legacy/plugins/lens/server/usage/task.ts b/x-pack/legacy/plugins/lens/server/usage/task.ts index 8fc6c8cbefe8a..3cb857a453e1d 100644 --- a/x-pack/legacy/plugins/lens/server/usage/task.ts +++ b/x-pack/legacy/plugins/lens/server/usage/task.ts @@ -45,7 +45,13 @@ export function initializeLensTelemetry(core: CoreSetup, { server }: { server: S } function registerLensTelemetryTask(core: CoreSetup, { server }: { server: Server }) { - const taskManager = server.plugins.task_manager!; + const taskManager = server.plugins.task_manager; + + if (!taskManager) { + server.log(['debug', 'telemetry'], `Task manager is not available`); + return; + } + taskManager.registerTaskDefinitions({ [TELEMETRY_TASK_TYPE]: { title: 'Lens telemetry fetch task', @@ -62,6 +68,11 @@ function scheduleTasks(server: Server) { status: { plugin: { kbnServer: KbnServer } }; }).status.plugin; + if (!taskManager) { + server.log(['debug', 'telemetry'], `Task manager is not available`); + return; + } + kbnServer.afterPluginsInit(() => { // The code block below can't await directly within "afterPluginsInit" // callback due to circular dependency The server isn't "ready" until @@ -71,14 +82,14 @@ function scheduleTasks(server: Server) { // function block. (async () => { try { - await taskManager!.schedule({ + await taskManager.schedule({ id: TASK_ID, taskType: TELEMETRY_TASK_TYPE, state: { byDate: {}, suggestionsByDate: {}, saved: {}, runs: 0 }, params: {}, }); } catch (e) { - server.log(['warning', 'telemetry'], `Error scheduling task, received ${e.message}`); + server.log(['debug', 'telemetry'], `Error scheduling task, received ${e.message}`); } })(); }); diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js index 076fae1bb5882..3bb9d48741ab9 100644 --- a/x-pack/legacy/plugins/maps/index.js +++ b/x-pack/legacy/plugins/maps/index.js @@ -23,7 +23,8 @@ import _ from 'lodash'; export function maps(kibana) { return new kibana.Plugin({ - require: ['kibana', 'elasticsearch', 'xpack_main', 'tile_map', 'task_manager'], + // task_manager could be required, but is only used for telemetry + require: ['kibana', 'elasticsearch', 'xpack_main', 'tile_map'], id: APP_ID, configPrefix: 'xpack.maps', publicDir: resolve(__dirname, 'public'), diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_usage_collector.js b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_usage_collector.js index 5f6361a16aa00..c0ac5a781b796 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_usage_collector.js +++ b/x-pack/legacy/plugins/maps/server/maps_telemetry/maps_usage_collector.js @@ -9,7 +9,7 @@ import { TASK_ID, scheduleTask, registerMapsTelemetryTask } from './telemetry_ta export function initTelemetryCollection(server) { registerMapsTelemetryTask(server); - scheduleTask(server, server.plugins.task_manager); + scheduleTask(server); registerMapsUsageCollector(server); } @@ -21,6 +21,11 @@ async function isTaskManagerReady(server) { async function fetch(server) { let docs; const taskManager = server.plugins.task_manager; + + if (!taskManager) { + return null; + } + try { ({ docs } = await taskManager.fetch({ query: { diff --git a/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.js b/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.js index 521c5ae71e14b..3702bc8e29539 100644 --- a/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.js +++ b/x-pack/legacy/plugins/maps/server/maps_telemetry/telemetry_task.js @@ -10,7 +10,14 @@ const TELEMETRY_TASK_TYPE = 'maps_telemetry'; export const TASK_ID = `Maps-${TELEMETRY_TASK_TYPE}`; -export function scheduleTask(server, taskManager) { +export function scheduleTask(server) { + const taskManager = server.plugins.task_manager; + + if (!taskManager) { + server.log(['debug', 'telemetry'], `Task manager is not available`); + return; + } + const { kbnServer } = server.plugins.xpack_main.status.plugin; kbnServer.afterPluginsInit(() => { @@ -36,6 +43,12 @@ export function scheduleTask(server, taskManager) { export function registerMapsTelemetryTask(server) { const taskManager = server.plugins.task_manager; + + if (!taskManager) { + server.log(['debug', 'telemetry'], `Task manager is not available`); + return; + } + taskManager.registerTaskDefinitions({ [TELEMETRY_TASK_TYPE]: { title: 'Maps telemetry fetch task', diff --git a/x-pack/legacy/plugins/oss_telemetry/index.js b/x-pack/legacy/plugins/oss_telemetry/index.js index 01bbd9359783a..eeee9e18f9112 100644 --- a/x-pack/legacy/plugins/oss_telemetry/index.js +++ b/x-pack/legacy/plugins/oss_telemetry/index.js @@ -11,7 +11,7 @@ import { PLUGIN_ID } from './constants'; export const ossTelemetry = (kibana) => { return new kibana.Plugin({ id: PLUGIN_ID, - require: ['elasticsearch', 'xpack_main', 'task_manager'], + require: ['elasticsearch', 'xpack_main'], configPrefix: 'xpack.oss_telemetry', init(server) { diff --git a/x-pack/legacy/plugins/oss_telemetry/server/lib/collectors/visualizations/get_usage_collector.ts b/x-pack/legacy/plugins/oss_telemetry/server/lib/collectors/visualizations/get_usage_collector.ts index 2bbecf99b97c3..63640c87f80a6 100644 --- a/x-pack/legacy/plugins/oss_telemetry/server/lib/collectors/visualizations/get_usage_collector.ts +++ b/x-pack/legacy/plugins/oss_telemetry/server/lib/collectors/visualizations/get_usage_collector.ts @@ -14,7 +14,11 @@ async function isTaskManagerReady(server: HapiServer) { } async function fetch(server: HapiServer) { - const taskManager = server.plugins.task_manager!; + const taskManager = server.plugins.task_manager; + + if (!taskManager) { + return null; + } let docs; try { diff --git a/x-pack/legacy/plugins/oss_telemetry/server/lib/tasks/index.ts b/x-pack/legacy/plugins/oss_telemetry/server/lib/tasks/index.ts index de3a17a79afb6..eaa8cc7405821 100644 --- a/x-pack/legacy/plugins/oss_telemetry/server/lib/tasks/index.ts +++ b/x-pack/legacy/plugins/oss_telemetry/server/lib/tasks/index.ts @@ -11,6 +11,11 @@ import { visualizationsTaskRunner } from './visualizations/task_runner'; export function registerTasks(server: HapiServer) { const taskManager = server.plugins.task_manager; + if (!taskManager) { + server.log(['debug', 'telemetry'], `Task manager is not available`); + return; + } + taskManager.registerTaskDefinitions({ [VIS_TELEMETRY_TASK]: { title: 'X-Pack telemetry calculator for Visualizations', @@ -43,7 +48,7 @@ export function scheduleTasks(server: HapiServer) { state: { stats: {}, runs: 0 }, }); } catch (e) { - server.log(['warning', 'telemetry'], `Error scheduling task, received ${e.message}`); + server.log(['debug', 'telemetry'], `Error scheduling task, received ${e.message}`); } })(); }); From 9da6c0705985a79b4c04aea501a8429da21841bc Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Fri, 25 Oct 2019 12:57:46 -0400 Subject: [PATCH 167/191] Re-add pipeline for flaky test runner job (#48781) * Revert "Revert "Add pipeline for flaky test runner job (#46740)"" This reverts commit 7d96a13fad5337f262743b51d5bdd6103d2c51a4. Also reconcile changes to Jenkinsfile since original revert happened * Fix param parsing and add missed change * Add missing variable --- .ci/Jenkinsfile_flaky | 113 ++++++ Jenkinsfile | 322 ++---------------- src/dev/ci_setup/setup_env.sh | 6 + src/dev/precommit_hook/casing_check_config.js | 3 +- ...enkins_build_kbn_tp_sample_panel_action.sh | 9 + test/scripts/jenkins_ci_group.sh | 5 +- vars/kibanaPipeline.groovy | 251 ++++++++++++++ vars/runbld.groovy | 11 + 8 files changed, 425 insertions(+), 295 deletions(-) create mode 100644 .ci/Jenkinsfile_flaky create mode 100755 test/scripts/jenkins_build_kbn_tp_sample_panel_action.sh create mode 100644 vars/kibanaPipeline.groovy create mode 100644 vars/runbld.groovy diff --git a/.ci/Jenkinsfile_flaky b/.ci/Jenkinsfile_flaky new file mode 100644 index 0000000000000..3f77243da2c1b --- /dev/null +++ b/.ci/Jenkinsfile_flaky @@ -0,0 +1,113 @@ +#!/bin/groovy + +library 'kibana-pipeline-library' +kibanaLibrary.load() + +// Looks like 'oss:ciGroup:1' or 'oss:firefoxSmoke' +def JOB_PARTS = params.CI_GROUP.split(':') +def IS_XPACK = JOB_PARTS[0] == 'xpack' +def JOB = JOB_PARTS[1] +def CI_GROUP = JOB_PARTS.size() > 2 ? JOB_PARTS[2] : '' + +def worker = getWorkerFromParams(IS_XPACK, JOB, CI_GROUP) + +def workerFailures = [] + +currentBuild.displayName += trunc(" ${params.GITHUB_OWNER}:${params.branch_specifier}", 24) +currentBuild.description = "${params.CI_GROUP}
Executions: ${params.NUMBER_EXECUTIONS}" + +// Note: If you increase agent count, it will execute NUMBER_EXECUTIONS per agent. It will not divide them up amongst the agents +// e.g. NUMBER_EXECUTIONS = 25, agentCount = 4 results in 100 total executions +def agentCount = 1 + +stage("Kibana Pipeline") { + timeout(time: 180, unit: 'MINUTES') { + timestamps { + ansiColor('xterm') { + def agents = [:] + for(def agentNumber = 1; agentNumber <= agentCount; agentNumber++) { + agents["agent-${agentNumber}"] = { + catchError { + kibanaPipeline.withWorkers('flaky-test-runner', { + if (!IS_XPACK) { + kibanaPipeline.buildOss() + if (CI_GROUP == '1') { + runbld "./test/scripts/jenkins_build_kbn_tp_sample_panel_action.sh" + } + } else { + kibanaPipeline.buildXpack() + } + }, getWorkerMap(agentNumber, params.NUMBER_EXECUTIONS.toInteger(), worker, workerFailures))() + } + } + } + + parallel(agents) + + currentBuild.description += ", Failures: ${workerFailures.size()}" + + if (workerFailures.size() > 0) { + print "There were ${workerFailures.size()} test suite failures." + print "The executions that failed were:" + print workerFailures.join("\n") + print "Please check 'Test Result' and 'Pipeline Steps' pages for more info" + } + } + } + } +} + +def getWorkerFromParams(isXpack, job, ciGroup) { + if (!isXpack) { + if (job == 'firefoxSmoke') { + return kibanaPipeline.getPostBuildWorker('firefoxSmoke', { runbld './test/scripts/jenkins_firefox_smoke.sh' }) + } else if(job == 'visualRegression') { + return kibanaPipeline.getPostBuildWorker('visualRegression', { runbld './test/scripts/jenkins_visual_regression.sh' }) + } else { + return kibanaPipeline.getOssCiGroupWorker(ciGroup) + } + } + + if (job == 'firefoxSmoke') { + return kibanaPipeline.getPostBuildWorker('xpack-firefoxSmoke', { runbld './test/scripts/jenkins_xpack_firefox_smoke.sh' }) + } else if(job == 'visualRegression') { + return kibanaPipeline.getPostBuildWorker('xpack-visualRegression', { runbld './test/scripts/jenkins_xpack_visual_regression.sh' }) + } else { + return kibanaPipeline.getXpackCiGroupWorker(ciGroup) + } +} + +def getWorkerMap(agentNumber, numberOfExecutions, worker, workerFailures, maxWorkers = 14) { + def workerMap = [:] + def numberOfWorkers = Math.min(numberOfExecutions, maxWorkers) + + for(def i = 1; i <= numberOfWorkers; i++) { + def workerExecutions = numberOfExecutions/numberOfWorkers + (i <= numberOfExecutions%numberOfWorkers ? 1 : 0) + + workerMap["agent-${agentNumber}-worker-${i}"] = { workerNumber -> + for(def j = 0; j < workerExecutions; j++) { + print "Execute agent-${agentNumber} worker-${workerNumber}: ${j}" + withEnv(["JOB=agent-${agentNumber}-worker-${workerNumber}-${j}"]) { + catchError { + try { + worker(workerNumber) + } catch (ex) { + workerFailures << "agent-${agentNumber} worker-${workerNumber}-${j}" + throw ex + } + } + } + } + } + } + + return workerMap +} + +def trunc(str, length) { + if (str.size() >= length) { + return str.take(length) + "..." + } + + return str; +} diff --git a/Jenkinsfile b/Jenkinsfile index fca814b265295..4820de9876737 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,7 @@ #!/bin/groovy library 'kibana-pipeline-library' +kibanaLibrary.load() stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a little bit timeout(time: 180, unit: 'MINUTES') { @@ -8,301 +9,42 @@ stage("Kibana Pipeline") { // This stage is just here to help the BlueOcean UI a ansiColor('xterm') { catchError { parallel([ - 'kibana-intake-agent': legacyJobRunner('kibana-intake'), - 'x-pack-intake-agent': legacyJobRunner('x-pack-intake'), - 'kibana-oss-agent': withWorkers('kibana-oss-tests', { buildOss() }, [ - 'oss-ciGroup1': getOssCiGroupWorker(1), - 'oss-ciGroup2': getOssCiGroupWorker(2), - 'oss-ciGroup3': getOssCiGroupWorker(3), - 'oss-ciGroup4': getOssCiGroupWorker(4), - 'oss-ciGroup5': getOssCiGroupWorker(5), - 'oss-ciGroup6': getOssCiGroupWorker(6), - 'oss-ciGroup7': getOssCiGroupWorker(7), - 'oss-ciGroup8': getOssCiGroupWorker(8), - 'oss-ciGroup9': getOssCiGroupWorker(9), - 'oss-ciGroup10': getOssCiGroupWorker(10), - 'oss-ciGroup11': getOssCiGroupWorker(11), - 'oss-ciGroup12': getOssCiGroupWorker(12), - 'oss-firefoxSmoke': getPostBuildWorker('firefoxSmoke', { runbld './test/scripts/jenkins_firefox_smoke.sh' }), - // 'oss-visualRegression': getPostBuildWorker('visualRegression', { runbld './test/scripts/jenkins_visual_regression.sh' }), + 'kibana-intake-agent': kibanaPipeline.legacyJobRunner('kibana-intake'), + 'x-pack-intake-agent': kibanaPipeline.legacyJobRunner('x-pack-intake'), + 'kibana-oss-agent': kibanaPipeline.withWorkers('kibana-oss-tests', { kibanaPipeline.buildOss() }, [ + 'oss-ciGroup1': kibanaPipeline.getOssCiGroupWorker(1), + 'oss-ciGroup2': kibanaPipeline.getOssCiGroupWorker(2), + 'oss-ciGroup3': kibanaPipeline.getOssCiGroupWorker(3), + 'oss-ciGroup4': kibanaPipeline.getOssCiGroupWorker(4), + 'oss-ciGroup5': kibanaPipeline.getOssCiGroupWorker(5), + 'oss-ciGroup6': kibanaPipeline.getOssCiGroupWorker(6), + 'oss-ciGroup7': kibanaPipeline.getOssCiGroupWorker(7), + 'oss-ciGroup8': kibanaPipeline.getOssCiGroupWorker(8), + 'oss-ciGroup9': kibanaPipeline.getOssCiGroupWorker(9), + 'oss-ciGroup10': kibanaPipeline.getOssCiGroupWorker(10), + 'oss-ciGroup11': kibanaPipeline.getOssCiGroupWorker(11), + 'oss-ciGroup12': kibanaPipeline.getOssCiGroupWorker(12), + 'oss-firefoxSmoke': kibanaPipeline.getPostBuildWorker('firefoxSmoke', { runbld './test/scripts/jenkins_firefox_smoke.sh' }), + // 'oss-visualRegression': kibanaPipeline.getPostBuildWorker('visualRegression', { runbld './test/scripts/jenkins_visual_regression.sh' }), ]), - 'kibana-xpack-agent': withWorkers('kibana-xpack-tests', { buildXpack() }, [ - 'xpack-ciGroup1': getXpackCiGroupWorker(1), - 'xpack-ciGroup2': getXpackCiGroupWorker(2), - 'xpack-ciGroup3': getXpackCiGroupWorker(3), - 'xpack-ciGroup4': getXpackCiGroupWorker(4), - 'xpack-ciGroup5': getXpackCiGroupWorker(5), - 'xpack-ciGroup6': getXpackCiGroupWorker(6), - 'xpack-ciGroup7': getXpackCiGroupWorker(7), - 'xpack-ciGroup8': getXpackCiGroupWorker(8), - 'xpack-ciGroup9': getXpackCiGroupWorker(9), - 'xpack-ciGroup10': getXpackCiGroupWorker(10), - 'xpack-firefoxSmoke': getPostBuildWorker('xpack-firefoxSmoke', { runbld './test/scripts/jenkins_xpack_firefox_smoke.sh' }), - // 'xpack-visualRegression': getPostBuildWorker('xpack-visualRegression', { runbld './test/scripts/jenkins_xpack_visual_regression.sh' }), + 'kibana-xpack-agent': kibanaPipeline.withWorkers('kibana-xpack-tests', { kibanaPipeline.buildXpack() }, [ + 'xpack-ciGroup1': kibanaPipeline.getXpackCiGroupWorker(1), + 'xpack-ciGroup2': kibanaPipeline.getXpackCiGroupWorker(2), + 'xpack-ciGroup3': kibanaPipeline.getXpackCiGroupWorker(3), + 'xpack-ciGroup4': kibanaPipeline.getXpackCiGroupWorker(4), + 'xpack-ciGroup5': kibanaPipeline.getXpackCiGroupWorker(5), + 'xpack-ciGroup6': kibanaPipeline.getXpackCiGroupWorker(6), + 'xpack-ciGroup7': kibanaPipeline.getXpackCiGroupWorker(7), + 'xpack-ciGroup8': kibanaPipeline.getXpackCiGroupWorker(8), + 'xpack-ciGroup9': kibanaPipeline.getXpackCiGroupWorker(9), + 'xpack-ciGroup10': kibanaPipeline.getXpackCiGroupWorker(10), + 'xpack-firefoxSmoke': kibanaPipeline.getPostBuildWorker('xpack-firefoxSmoke', { runbld './test/scripts/jenkins_xpack_firefox_smoke.sh' }), + // 'xpack-visualRegression': kibanaPipeline.getPostBuildWorker('xpack-visualRegression', { runbld './test/scripts/jenkins_xpack_visual_regression.sh' }), ]), ]) } - node('flyweight') { - // If the build doesn't have a result set by this point, there haven't been any errors and it can be marked as a success - // The e-mail plugin for the infra e-mail depends upon this being set - currentBuild.result = currentBuild.result ?: 'SUCCESS' - - sendMail() - } + kibanaPipeline.sendMail() } } } } - -def withWorkers(name, preWorkerClosure = {}, workerClosures = [:]) { - return { - jobRunner('tests-xl', true) { - try { - doSetup() - preWorkerClosure() - - def nextWorker = 1 - def worker = { workerClosure -> - def workerNumber = nextWorker - nextWorker++ - - return { - workerClosure(workerNumber) - } - } - - def workers = [:] - workerClosures.each { workerName, workerClosure -> - workers[workerName] = worker(workerClosure) - } - - parallel(workers) - } finally { - catchError { - uploadAllGcsArtifacts(name) - } - - catchError { - runbldJunit() - } - - catchError { - publishJunit() - } - - catchError { - runErrorReporter() - } - } - } - } -} - -def getPostBuildWorker(name, closure) { - return { workerNumber -> - def kibanaPort = "61${workerNumber}1" - def esPort = "61${workerNumber}2" - def esTransportPort = "61${workerNumber}3" - - withEnv([ - "CI_WORKER_NUMBER=${workerNumber}", - "TEST_KIBANA_HOST=localhost", - "TEST_KIBANA_PORT=${kibanaPort}", - "TEST_KIBANA_URL=http://elastic:changeme@localhost:${kibanaPort}", - "TEST_ES_URL=http://elastic:changeme@localhost:${esPort}", - "TEST_ES_TRANSPORT_PORT=${esTransportPort}", - "IS_PIPELINE_JOB=1", - ]) { - closure() - } - } -} - -def getOssCiGroupWorker(ciGroup) { - return getPostBuildWorker("ciGroup" + ciGroup, { - withEnv([ - "CI_GROUP=${ciGroup}", - "JOB=kibana-ciGroup${ciGroup}", - ]) { - runbld "./test/scripts/jenkins_ci_group.sh" - } - }) -} - -def getXpackCiGroupWorker(ciGroup) { - return getPostBuildWorker("xpack-ciGroup" + ciGroup, { - withEnv([ - "CI_GROUP=${ciGroup}", - "JOB=xpack-kibana-ciGroup${ciGroup}", - ]) { - runbld "./test/scripts/jenkins_xpack_ci_group.sh" - } - }) -} - -def legacyJobRunner(name) { - return { - parallel([ - "${name}": { - withEnv([ - "JOB=${name}", - ]) { - jobRunner('linux && immutable', false) { - try { - runbld('.ci/run.sh', true) - } finally { - catchError { - uploadAllGcsArtifacts(name) - } - catchError { - publishJunit() - } - catchError { - runErrorReporter() - } - } - } - } - } - ]) - } -} - -def jobRunner(label, useRamDisk, closure) { - node(label) { - if (useRamDisk) { - // Move to a temporary workspace, so that we can symlink the real workspace into /dev/shm - def originalWorkspace = env.WORKSPACE - ws('/tmp/workspace') { - sh """ - mkdir -p /dev/shm/workspace - mkdir -p '${originalWorkspace}' # create all of the directories leading up to the workspace, if they don't exist - rm --preserve-root -rf '${originalWorkspace}' # then remove just the workspace, just in case there's stuff in it - ln -s /dev/shm/workspace '${originalWorkspace}' - """ - } - } - - def scmVars = checkout scm - - withEnv([ - "CI=true", - "HOME=${env.JENKINS_HOME}", - "PR_SOURCE_BRANCH=${env.ghprbSourceBranch ?: ''}", - "PR_TARGET_BRANCH=${env.ghprbTargetBranch ?: ''}", - "PR_AUTHOR=${env.ghprbPullAuthorLogin ?: ''}", - "TEST_BROWSER_HEADLESS=1", - "GIT_BRANCH=${scmVars.GIT_BRANCH}", - ]) { - withCredentials([ - string(credentialsId: 'vault-addr', variable: 'VAULT_ADDR'), - string(credentialsId: 'vault-role-id', variable: 'VAULT_ROLE_ID'), - string(credentialsId: 'vault-secret-id', variable: 'VAULT_SECRET_ID'), - ]) { - // scm is configured to check out to the ./kibana directory - dir('kibana') { - closure() - } - } - } - } -} - -// TODO what should happen if GCS, Junit, or email publishing fails? Unstable build? Failed build? - -def uploadGcsArtifact(workerName, pattern) { - def storageLocation = "gs://kibana-ci-artifacts/jobs/${env.JOB_NAME}/${BUILD_NUMBER}/${workerName}" // TODO - // def storageLocation = "gs://kibana-pipeline-testing/jobs/pipeline-test/${BUILD_NUMBER}/${workerName}" - - googleStorageUpload( - credentialsId: 'kibana-ci-gcs-plugin', - bucket: storageLocation, - pattern: pattern, - sharedPublicly: true, - showInline: true, - ) -} - -def uploadAllGcsArtifacts(workerName) { - def ARTIFACT_PATTERNS = [ - 'target/kibana-*', - 'target/junit/**/*', - 'test/**/screenshots/**/*.png', - 'test/functional/failure_debug/html/*.html', - 'x-pack/test/**/screenshots/**/*.png', - 'x-pack/test/functional/failure_debug/html/*.html', - 'x-pack/test/functional/apps/reporting/reports/session/*.pdf', - ] - - ARTIFACT_PATTERNS.each { pattern -> - uploadGcsArtifact(workerName, pattern) - } -} - -def publishJunit() { - junit(testResults: 'target/junit/**/*.xml', allowEmptyResults: true, keepLongStdio: true) -} - -def sendMail() { - sendInfraMail() - sendKibanaMail() -} - -def sendInfraMail() { - catchError { - step([ - $class: 'Mailer', - notifyEveryUnstableBuild: true, - recipients: 'infra-root+build@elastic.co', - sendToIndividuals: false - ]) - } -} - -def sendKibanaMail() { - catchError { - def buildStatus = buildUtils.getBuildStatus() - - if(params.NOTIFY_ON_FAILURE && buildStatus != 'SUCCESS' && buildStatus != 'ABORTED') { - emailext( - to: 'build-kibana@elastic.co', - subject: "${env.JOB_NAME} - Build # ${env.BUILD_NUMBER} - ${buildStatus}", - body: '${SCRIPT,template="groovy-html.template"}', - mimeType: 'text/html', - ) - } - } -} - -def runbld(script, enableJunitProcessing = false) { - def extraConfig = enableJunitProcessing ? "" : "--config ${env.WORKSPACE}/kibana/.ci/runbld_no_junit.yml" - - sh "/usr/local/bin/runbld -d '${pwd()}' ${extraConfig} ${script}" -} - -def runbldJunit() { - sh "/usr/local/bin/runbld -d '${pwd()}' ${env.WORKSPACE}/kibana/test/scripts/jenkins_runbld_junit.sh" -} - -def bash(script) { - sh "#!/bin/bash\n${script}" -} - -def doSetup() { - runbld "./test/scripts/jenkins_setup.sh" -} - -def buildOss() { - runbld "./test/scripts/jenkins_build_kibana.sh" -} - -def buildXpack() { - runbld "./test/scripts/jenkins_xpack_build_kibana.sh" -} - -def runErrorReporter() { - bash """ - source src/dev/ci_setup/setup_env.sh - node scripts/report_failed_tests - """ -} diff --git a/src/dev/ci_setup/setup_env.sh b/src/dev/ci_setup/setup_env.sh index 3b239bd3ff731..805b77365e624 100644 --- a/src/dev/ci_setup/setup_env.sh +++ b/src/dev/ci_setup/setup_env.sh @@ -2,6 +2,10 @@ set -e +if [[ "$CI_ENV_SETUP" ]]; then + return 0 +fi + installNode=$1 dir="$(pwd)" @@ -152,3 +156,5 @@ if [[ -d "$ES_DIR" && -f "$ES_JAVA_PROP_PATH" ]]; then echo "Setting JAVA_HOME=$HOME/.java/$ES_BUILD_JAVA" export JAVA_HOME=$HOME/.java/$ES_BUILD_JAVA fi + +export CI_ENV_SETUP=true diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index 9829de2fd3920..edd818e1b42de 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -43,8 +43,9 @@ export const IGNORE_FILE_GLOBS = [ 'x-pack/docs/**/*', 'src/legacy/ui/public/assets/fonts/**/*', 'packages/kbn-utility-types/test-d/**/*', - 'Jenkinsfile', + '**/Jenkinsfile*', 'Dockerfile*', + 'vars/*', // Files in this directory must match a pre-determined name in some cases. 'x-pack/legacy/plugins/canvas/.storybook/*', diff --git a/test/scripts/jenkins_build_kbn_tp_sample_panel_action.sh b/test/scripts/jenkins_build_kbn_tp_sample_panel_action.sh new file mode 100755 index 0000000000000..4b16e3b32fefd --- /dev/null +++ b/test/scripts/jenkins_build_kbn_tp_sample_panel_action.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +source src/dev/ci_setup/setup_env.sh + +cd test/plugin_functional/plugins/kbn_tp_sample_panel_action; +if [[ ! -d "target" ]]; then + checks-reporter-with-killswitch "Build kbn_tp_sample_panel_action" yarn build; +fi +cd -; diff --git a/test/scripts/jenkins_ci_group.sh b/test/scripts/jenkins_ci_group.sh index 6deddd5a59152..274cca695b535 100755 --- a/test/scripts/jenkins_ci_group.sh +++ b/test/scripts/jenkins_ci_group.sh @@ -22,10 +22,7 @@ fi checks-reporter-with-killswitch "Functional tests / Group ${CI_GROUP}" yarn run grunt "run:functionalTests_ciGroup${CI_GROUP}"; if [ "$CI_GROUP" == "1" ]; then - # build kbn_tp_sample_panel_action - cd test/plugin_functional/plugins/kbn_tp_sample_panel_action; - checks-reporter-with-killswitch "Build kbn_tp_sample_panel_action" yarn build; - cd -; + source test/scripts/jenkins_build_kbn_tp_sample_panel_action.sh yarn run grunt run:pluginFunctionalTestsRelease --from=source; yarn run grunt run:interpreterFunctionalTestsRelease; fi diff --git a/vars/kibanaPipeline.groovy b/vars/kibanaPipeline.groovy new file mode 100644 index 0000000000000..e8d7cc03edad0 --- /dev/null +++ b/vars/kibanaPipeline.groovy @@ -0,0 +1,251 @@ +def withWorkers(name, preWorkerClosure = {}, workerClosures = [:]) { + return { + jobRunner('tests-xl', true) { + try { + doSetup() + preWorkerClosure() + + def nextWorker = 1 + def worker = { workerClosure -> + def workerNumber = nextWorker + nextWorker++ + + return { + workerClosure(workerNumber) + } + } + + def workers = [:] + workerClosures.each { workerName, workerClosure -> + workers[workerName] = worker(workerClosure) + } + + parallel(workers) + } finally { + catchError { + uploadAllGcsArtifacts(name) + } + + catchError { + runbld.junit() + } + + catchError { + publishJunit() + } + + catchError { + runErrorReporter() + } + } + } + } +} + +def getPostBuildWorker(name, closure) { + return { workerNumber -> + def kibanaPort = "61${workerNumber}1" + def esPort = "61${workerNumber}2" + def esTransportPort = "61${workerNumber}3" + + withEnv([ + "CI_WORKER_NUMBER=${workerNumber}", + "TEST_KIBANA_HOST=localhost", + "TEST_KIBANA_PORT=${kibanaPort}", + "TEST_KIBANA_URL=http://elastic:changeme@localhost:${kibanaPort}", + "TEST_ES_URL=http://elastic:changeme@localhost:${esPort}", + "TEST_ES_TRANSPORT_PORT=${esTransportPort}", + "IS_PIPELINE_JOB=1", + ]) { + closure() + } + } +} + +def getOssCiGroupWorker(ciGroup) { + return getPostBuildWorker("ciGroup" + ciGroup, { + withEnv([ + "CI_GROUP=${ciGroup}", + "JOB=kibana-ciGroup${ciGroup}", + ]) { + runbld "./test/scripts/jenkins_ci_group.sh" + } + }) +} + +def getXpackCiGroupWorker(ciGroup) { + return getPostBuildWorker("xpack-ciGroup" + ciGroup, { + withEnv([ + "CI_GROUP=${ciGroup}", + "JOB=xpack-kibana-ciGroup${ciGroup}", + ]) { + runbld "./test/scripts/jenkins_xpack_ci_group.sh" + } + }) +} + +def legacyJobRunner(name) { + return { + parallel([ + "${name}": { + withEnv([ + "JOB=${name}", + ]) { + jobRunner('linux && immutable', false) { + try { + runbld('.ci/run.sh', true) + } finally { + catchError { + uploadAllGcsArtifacts(name) + } + catchError { + publishJunit() + } + catchError { + runErrorReporter() + } + } + } + } + } + ]) + } +} + +def jobRunner(label, useRamDisk, closure) { + node(label) { + if (useRamDisk) { + // Move to a temporary workspace, so that we can symlink the real workspace into /dev/shm + def originalWorkspace = env.WORKSPACE + ws('/tmp/workspace') { + sh """ + mkdir -p /dev/shm/workspace + mkdir -p '${originalWorkspace}' # create all of the directories leading up to the workspace, if they don't exist + rm --preserve-root -rf '${originalWorkspace}' # then remove just the workspace, just in case there's stuff in it + ln -s /dev/shm/workspace '${originalWorkspace}' + """ + } + } + + def scmVars = checkout scm + + withEnv([ + "CI=true", + "HOME=${env.JENKINS_HOME}", + "PR_SOURCE_BRANCH=${env.ghprbSourceBranch ?: ''}", + "PR_TARGET_BRANCH=${env.ghprbTargetBranch ?: ''}", + "PR_AUTHOR=${env.ghprbPullAuthorLogin ?: ''}", + "TEST_BROWSER_HEADLESS=1", + "GIT_BRANCH=${scmVars.GIT_BRANCH}", + ]) { + withCredentials([ + string(credentialsId: 'vault-addr', variable: 'VAULT_ADDR'), + string(credentialsId: 'vault-role-id', variable: 'VAULT_ROLE_ID'), + string(credentialsId: 'vault-secret-id', variable: 'VAULT_SECRET_ID'), + ]) { + // scm is configured to check out to the ./kibana directory + dir('kibana') { + closure() + } + } + } + } +} + +// TODO what should happen if GCS, Junit, or email publishing fails? Unstable build? Failed build? + +def uploadGcsArtifact(workerName, pattern) { + def storageLocation = "gs://kibana-ci-artifacts/jobs/${env.JOB_NAME}/${BUILD_NUMBER}/${workerName}" // TODO + + googleStorageUpload( + credentialsId: 'kibana-ci-gcs-plugin', + bucket: storageLocation, + pattern: pattern, + sharedPublicly: true, + showInline: true, + ) +} + +def uploadAllGcsArtifacts(workerName) { + def ARTIFACT_PATTERNS = [ + 'target/kibana-*', + 'target/junit/**/*', + 'test/**/screenshots/**/*.png', + 'test/functional/failure_debug/html/*.html', + 'x-pack/test/**/screenshots/**/*.png', + 'x-pack/test/functional/failure_debug/html/*.html', + 'x-pack/test/functional/apps/reporting/reports/session/*.pdf', + ] + + ARTIFACT_PATTERNS.each { pattern -> + uploadGcsArtifact(workerName, pattern) + } +} + +def publishJunit() { + junit(testResults: 'target/junit/**/*.xml', allowEmptyResults: true, keepLongStdio: true) +} + +def sendMail() { + // If the build doesn't have a result set by this point, there haven't been any errors and it can be marked as a success + // The e-mail plugin for the infra e-mail depends upon this being set + currentBuild.result = currentBuild.result ?: 'SUCCESS' + + def buildStatus = buildUtils.getBuildStatus() + if (buildStatus != 'SUCCESS' && buildStatus != 'ABORTED') { + node('flyweight') { + sendInfraMail() + sendKibanaMail() + } + } +} + +def sendInfraMail() { + catchError { + step([ + $class: 'Mailer', + notifyEveryUnstableBuild: true, + recipients: 'infra-root+build@elastic.co', + sendToIndividuals: false + ]) + } +} + +def sendKibanaMail() { + catchError { + def buildStatus = buildUtils.getBuildStatus() + if(params.NOTIFY_ON_FAILURE && buildStatus != 'SUCCESS' && buildStatus != 'ABORTED') { + emailext( + to: 'build-kibana@elastic.co', + subject: "${env.JOB_NAME} - Build # ${env.BUILD_NUMBER} - ${buildStatus}", + body: '${SCRIPT,template="groovy-html.template"}', + mimeType: 'text/html', + ) + } + } +} + +def bash(script) { + sh "#!/bin/bash\n${script}" +} + +def doSetup() { + runbld "./test/scripts/jenkins_setup.sh" +} + +def buildOss() { + runbld "./test/scripts/jenkins_build_kibana.sh" +} + +def buildXpack() { + runbld "./test/scripts/jenkins_xpack_build_kibana.sh" +} + +def runErrorReporter() { + bash """ + source src/dev/ci_setup/setup_env.sh + node scripts/report_failed_tests + """ +} + +return this diff --git a/vars/runbld.groovy b/vars/runbld.groovy new file mode 100644 index 0000000000000..501e2421ca65b --- /dev/null +++ b/vars/runbld.groovy @@ -0,0 +1,11 @@ +def call(script, enableJunitProcessing = false) { + def extraConfig = enableJunitProcessing ? "" : "--config ${env.WORKSPACE}/kibana/.ci/runbld_no_junit.yml" + + sh "/usr/local/bin/runbld -d '${pwd()}' ${extraConfig} ${script}" +} + +def junit() { + sh "/usr/local/bin/runbld -d '${pwd()}' ${env.WORKSPACE}/kibana/test/scripts/jenkins_runbld_junit.sh" +} + +return this From a4d2638d48e72b17443d96827b9e69664ce2e16e Mon Sep 17 00:00:00 2001 From: Tim Schnell Date: Fri, 25 Oct 2019 12:27:11 -0500 Subject: [PATCH 168/191] [skip ci] Function Reference Docs Update (#48791) * setting up function reference pattern * adding functions A-F * grammar fixes * Apply suggestions from code review Co-Authored-By: Catherine Liu * more review updates --- .../canvas/canvas-function-reference.asciidoc | 568 ++++++++++++++++++ 1 file changed, 568 insertions(+) diff --git a/docs/canvas/canvas-function-reference.asciidoc b/docs/canvas/canvas-function-reference.asciidoc index df4b17e905772..2b437728b2d01 100644 --- a/docs/canvas/canvas-function-reference.asciidoc +++ b/docs/canvas/canvas-function-reference.asciidoc @@ -25,6 +25,32 @@ A † denotes an argument can be passed multiple times. Returns `true` if all of the conditions are met. See also <>. +*Expression syntax* +[source,js] +---- +all {neq “foo”} {neq “bar”} {neq “fizz”} +all condition={gt 10} condition={lt 20} +---- + +*Code example* +[source,text] +---- +filters +| demodata +| math "mean(percent_uptime)" +| formatnumber "0.0%" +| metric "Average uptime" + metricFont={ + font size=48 family="'Open Sans', Helvetica, Arial, sans-serif" + color={ + if {all {gte 0} {lt 0.8}} then="red" else="green" + } + align="center" lHeight=48 + } +| render +---- +This sets the color of the metric text to `”red”` if the context passed into `metric` is greater than or equal to 0 and less than 0.8. Otherwise, the color is set to `"green"`. + *Accepts:* `null` [cols="3*^<"] @@ -47,6 +73,24 @@ Alias: `condition` Converts between core types, including `string`, `number`, `null`, `boolean`, and `date`, and renames columns. See also <> and <>. +*Expression syntax* +[source,js] +---- +alterColumn “cost” type=”string” +alterColumn column=”@timestamp” name=”foo” +---- + +*Code example* +[source,text] +---- +filters +| demodata +| alterColumn “time” name=”time_in_ms” type=”number” +| table +| render +---- +This renames the `time` column to `time_in_ms` and converts the type of the column’s values from `date` to `number`. + *Accepts:* `datatable` [cols="3*^<"] @@ -77,6 +121,27 @@ Alias: `column` Returns `true` if at least one of the conditions is met. See also <>. +*Expression syntax* +[source,js] +---- +any {eq “foo”} {eq “bar”} {eq “fizz”} +any condition={lte 10} condition={gt 30} +---- + +*Code example* +[source,text] +---- +filters +| demodata +| filterrows { + getCell "project" | any {eq "elasticsearch"} {eq "kibana"} {eq "x-pack"} + } +| pointseries color="project" size="max(price)" +| pie +| render +---- +This filters out any rows that don’t contain `“elasticsearch”`, `“kibana”` or `“x-pack”` in the `project` field. + *Accepts:* `null` [cols="3*^<"] @@ -99,6 +164,28 @@ Alias: `condition` Creates a `datatable` with a single value. See also <>. +*Expression syntax* +[source,js] +---- +as +as “foo” +as name=”bar” +---- + +*Code example* +[source,text] +---- +filters +| demodata +| ply by="project" fn={math "count(username)" | as "num_users"} fn={math "mean(price)" | as "price"} +| pointseries x="project" y="num_users" size="price" color="project" +| plot +| render +---- +`as` casts any primitive value (`string`, `number`, `date`, `null`) into a `datatable` with a single row and a single column with the given name (or defaults to `"value"` if no name is provided). This is useful when piping a primitive value into a function that only takes `datatable` as an input. + +In the example above, `ply` expects each `fn` subexpression to return a `datatable` in order to merge the results of each `fn` back into a `datatable`, but using a `math` aggregation in the subexpressions returns a single `math` value, which is then cast into a `datatable` using `as`. + *Accepts:* `string`, `boolean`, `number`, `null` [cols="3*^<"] @@ -123,6 +210,21 @@ Default: `"value"` Retrieves Canvas workpad asset objects to provide as argument values. Usually images. +*Expression syntax* +[source,js] +---- +asset "asset-52f14f2b-fee6-4072-92e8-cd2642665d02" +asset id="asset-498f7429-4d56-42a2-a7e4-8bf08d98d114" +---- + +*Code example* +[source,text] +---- +image dataurl={asset "asset-c661a7cc-11be-45a1-a401-d7592ea7917a"} mode="contain" +| render +---- +The image asset stored with the ID `“asset-c661a7cc-11be-45a1-a401-d7592ea7917a”` is passed into the `dataurl` argument of the `image` function to display the stored asset. + *Accepts:* `null` [cols="3*^<"] @@ -145,6 +247,27 @@ Alias: `id` Configures the axis of a visualization. Only used with <>. +*Expression syntax* +[source,js] +---- +axisConfig show=false +axisConfig position=”right” min=0 max=10 tickSize=1 +---- + +*Code example* +[source,text] +---- +filters +| demodata +| pointseries x="size(cost)" y="project" color="project" +| plot defaultStyle={seriesStyle bars=0.75 horizontalBars=true} + legend=false + xaxis={axisConfig position="top" min=0 max=400 tickSize=100} + yaxis={axisConfig position="right"} +| render +---- +This sets the `x-axis` to display on the top of the chart and sets the range of values to `0-400` with ticks displayed at `100` intervals. The `y-axis` is configured to display on the `right`. + *Accepts:* `null` [cols="3*^<"] @@ -188,6 +311,34 @@ Default: `true` Builds a `case` (including a condition/result) to pass to the <> function. +*Expression syntax* +[source,js] +---- +case 0 then=”red” +case when=5 then=”yellow” +case if={lte 50} then=”green” +---- + +*Code example* +[source,text] +---- +math "random()" +| progress shape="gauge" label={formatnumber "0%"} + font={font size=24 family="'Open Sans', Helvetica, Arial, sans-serif" align="center" + color={ + switch {case if={lte 0.5} then="green"} + {case if={all {gt 0.5} {lte 0.75}} then="orange"} + default="red" + }} + valueColor={ + switch {case if={lte 0.5} then="green"} + {case if={all {gt 0.5} {lte 0.75}} then="orange"} + default="red" + } +| render +---- +This sets the color of the progress indicator and the color of the label to `"green"` if the value is less than or equal to `0.5`, `"orange"` if the value is greater than `0.5` and less than or equal to `0.75`, and `"red"` if `none` of the case conditions are met. + *Accepts:* `any` [cols="3*^<"] @@ -229,6 +380,24 @@ Clears the _context_, and returns `null`. Includes or excludes columns from a data table. If you specify both, this will exclude first. +*Expression syntax* +[source,js] +---- +columns include=”@timestamp, projects, cost” +columns exclude=”username, country, age” +---- + +*Code example* +[source,text] +---- +filters +| demodata +| columns include="price, cost, state, project" +| table +| render +---- +This only keeps the `price`, `cost`, `state`, and `project` columns from the `demodata` data source and removes all other columns. + *Accepts:* `datatable` [cols="3*^<"] @@ -257,6 +426,31 @@ Compares the _context_ to specified value to determine `true` or `false`. Usually used in combination with <> or <>. This only works with primitive types, such as `number`, `string`, and `boolean`. See also <>, <>, <>, <>, <>, and <>. +*Expression syntax* +[source,js] +---- +compare “neq” to=”elasticsearch” +compare op=”lte” to=100 +---- + +*Code example* +[source,text] +---- +filters +| demodata +| mapColumn project + fn=${getCell project | + switch + {case if={compare eq to=kibana} then=kibana} + {case if={compare eq to=elasticsearch} then=elasticsearch} + default="other" + } +| pointseries size="size(cost)" color="project" +| pie +| render +---- +This maps all `project` values that aren’t `“kibana”` and `“elasticsearch”` to `“other”`. Alternatively, you can use the individual comparator functions instead of compare. See <>, <>, <>, <>, <>, and <>. + *Accepts:* `string`, `number`, `boolean`, `null` [cols="3*^<"] @@ -287,6 +481,35 @@ Alias: `this`, `b` Creates an object used for styling an element's container, including background, border, and opacity. +*Expression syntax* +[source,js] +---- +containerStyle backgroundColor=”red”’ +containerStyle borderRadius=”50px” +containerStyle border=”1px solid black” +containerStyle padding=”5px” +containerStyle opacity=”0.5” +containerStyle overflow=”hidden” +containerStyle backgroundImage={asset id=asset-f40d2292-cf9e-4f2c-8c6f-a504a25e949c} + backgroundRepeat="no-repeat" + backgroundSize="cover" +---- + +*Code example* +[source,text] +---- +shape "star" fill="#E61D35" maintainAspect=true +| render + containerStyle={ + containerStyle backgroundColor="#F8D546" + borderRadius="200px" + border="4px solid #05509F" + padding="0px" + opacity="0.9" + overflow="hidden" + } +---- + *Accepts:* `null` [cols="3*^<"] @@ -346,6 +569,22 @@ Default: `"hidden"` Returns whatever you pass into it. This can be useful when you need to use the _context_ as an argument to a function as a sub-expression. +*Expression syntax* +[source,js] +---- +context +---- + +*Code example* +[source,text] +---- +date +| formatdate "LLLL" +| markdown "Last updated: " {context} +| render +---- +Using the `context` function allows us to pass the output, or _context_, of the previous function as a value to an argument in the next function. Here we get the formatted date string from the previous function and pass it as `content` for the markdown element. + *Accepts:* `any` *Returns:* Original _context_ @@ -356,6 +595,26 @@ _context_ as an argument to a function as a sub-expression. Creates a `datatable` from CSV input. +*Expression syntax* +[source,js] +---- +csv “fruit, stock + kiwi, 10 + Banana, 5” +---- + +*Code example* +[source,text] +---- +csv "fruit,stock + kiwi,10 + banana,5" +| pointseries color=fruit size=stock +| pie +| render +---- +This is useful for quickly mocking data. + *Accepts:* `null` [cols="3*^<"] @@ -390,6 +649,30 @@ Alias: `data` Returns the current time, or a time parsed from a `string`, as milliseconds since epoch. +*Expression syntax* +[source,js] +---- +date +date value=1558735195 +date “2019-05-24T21:59:55+0000” +date “01/31/2019” format=”MM/DD/YYYY” +---- + +*Code example* +[source,text] +---- +date +| formatdate "LLL" +| markdown {context} + font={font family="Arial, sans-serif" size=30 align="left" + color="#000000" + weight="normal" + underline=false + italic=false} +| render +---- +Using `date` without passing any arguments will return the current date and time. + *Accepts:* `null` [cols="3*^<"] @@ -418,6 +701,24 @@ using the `format` argument. Must be an ISO8601 string or you must provide the f A mock data set that includes project CI times with usernames, countries, and run phases. +*Expression syntax* +[source,js] +---- +demodata +demodata “ci” +demodata type=”shirts” +---- + +*Code example* +[source,text] +---- +filters +| demodata +| table +| render +---- +`demodata` is a mock data set that you can use to start playing around in Canvas. + *Accepts:* `filter` [cols="3*^<"] @@ -442,6 +743,23 @@ Default: `"ci"` Executes multiple sub-expressions, then returns the original _context_. Use for running functions that produce an action or side effect without changing the original _context_. +*Expression syntax* +[source,js] +---- +do fn={something cool} +---- + +*Code example* +[source,text] +---- +filters +| demodata +| do fn={something cool} +| table +| render +---- +`do` should be used to invoke a function that produces as a side effect without changing the `context`. + *Accepts:* `any` [cols="3*^<"] @@ -464,6 +782,22 @@ Aliases: `expression`, `exp`, `fn`, `function` Configures a dropdown filter control element. +*Expression syntax* +[source,js] +---- +dropdownControl valueColumn=project filterColumn=project +dropdownControl valueColumn=agent filterColumn=agent.keyword filterGroup=group1 +---- + +*Code example* +[source,text] +---- +demodata +| dropdownControl valueColumn=project filterColumn=project +| render +---- +This creates a dropdown filter element. It requires a data source and uses the unique values from the given `valueColumn` (i.e. `project`) and applies the filter to the `project` column. Note: `filterColumn` should point to a keyword type field for Elasticsearch data sources. + *Accepts:* `datatable` [cols="3*^<"] @@ -496,6 +830,33 @@ Configures a dropdown filter control element. Returns whether the _context_ is equal to the argument. +*Expression syntax* +[source,js] +---- +eq true +eq null +eq 10 +eq “foo” +---- + +*Code example* +[source,text] +---- +filters +| demodata +| mapColumn project + fn=${getCell project | + switch + {case if={eq kibana} then=kibana} + {case if={eq elasticsearch} then=elasticsearch} + default="other" + } +| pointseries size="size(cost)" color="project" +| pie +| render +---- +This changes all values in the project column that don’t equal `“kibana”` or `“elasticsearch”` to `“other”`. + *Accepts:* `boolean`, `number`, `string`, `null` [cols="3*^<"] @@ -518,6 +879,28 @@ Alias: `value` Queries {es} for the number of hits matching the specified query. +*Expression syntax* +[source,js] +---- +escount index=”logstash-*” +escount "currency:\"EUR\"" index=”kibana_sample_data_ecommerce” +escount query="response:404" index=”kibana_sample_data_logs” +---- + +*Code example* +[source,text] +---- +filters +| escount "Cancelled:true" index="kibana_sample_data_flights" +| math "value" +| progress shape="semicircle" + label={formatnumber 0,0} + font={font size=24 family="'Open Sans', Helvetica, Arial, sans-serif" color="#000000" align=center} + max={filters | escount index="kibana_sample_data_flights"} +| render +---- +The first `escount` expression retrieves the number of flights that were cancelled. The second `escount` expression retrieves the total number of flights. + *Accepts:* `filter` [cols="3*^<"] @@ -549,6 +932,34 @@ Default: `_all` Queries {es} for raw documents. Specify the fields you want to retrieve, especially if you are asking for a lot of rows. +*Expression syntax* +[source,js] +---- +esdocs index=”logstash-*” +esdocs "currency:\"EUR\"" index=”kibana_sample_data_ecommerce” +esdocs query="response:404" index=”kibana_sample_data_logs” +esdocs index=”kibana_sample_data_flights” count=100 +esdocs index="kibana_sample_data_flights" sort="AvgTicketPrice, asc" +---- + +*Code example* +[source,text] +---- +filters +| esdocs index="kibana_sample_data_ecommerce" + fields="customer_gender, taxful_total_price, order_date" + sort="order_date, asc" + count=10000 +| mapColumn "order_date" + fn={getCell "order_date" | date {context} | rounddate "YYYY-MM-DD"} +| alterColumn "order_date" type="date" +| pointseries x="order_date" y="sum(taxful_total_price)" color="customer_gender" +| plot defaultStyle={seriesStyle lines=3} + palette={palette "#7ECAE3" "#003A4D" gradient=true} +| render +---- +This retrieves the latest 10000 documents data from the `kibana_sample_data_ecommerce` index sorted by `order_date` in ascending order and only requests the `customer_gender`, `taxful_total_price`, and `order_date` fields. + *Accepts:* `filter` [cols="3*^<"] @@ -593,6 +1004,21 @@ Default: `"_all"` Queries {es} using {es} SQL. +*Expression syntax* +[source,js] +---- +essql query=”SELECT * FROM \”logstash*\”” +essql “SELECT * FROM \”apm*\”” count=10000 +---- + +*Code example* +[source,text] +---- +filters +| essql query="SELECT Carrier, FlightDelayMin, AvgTicketPrice FROM \"kibana_sample_data_flights\"" +---- +This retrieves the `Carrier`, `FlightDelayMin`, and `AvgTicketPrice` fields from the “kibana_sample_data_flights” index. + *Accepts:* `filter` [cols="3*^<"] @@ -627,6 +1053,26 @@ Default: `UTC` Creates a filter that matches a given column to an exact value. +*Expression syntax* +[source,js] +---- +exactly “state” value=”running” +exactly “age” value=50 filterGroup=”group2” +exactly column=“project” value=”beats” +---- + +*Code example* +[source,text] +---- +filters +| exactly column=project value=elasticsearch +| demodata +| pointseries x=project y="mean(age)" +| plot defaultStyle={seriesStyle bars=1} +| render +---- +The `exactly` filter here is added to existing filters retrieved by the `filters` function and further filters down the data to only have `”elasticsearch”` data. The `exactly` filter only applies to this one specific element and will not affect other elements in the workpad. + *Accepts:* `filter` [cols="3*^<"] @@ -664,6 +1110,29 @@ capitalization. Filters rows in a `datatable` based on the return value of a sub-expression. +*Expression syntax* +[source,js] +---- +filterrows {getCell “project” | eq “kibana”} +filterrows fn={getCell “age” | gt 50} +---- + +*Code example* +[source,text] +---- +filters +| demodata +| filterrows {getCell "country" | any {eq "IN"} {eq "US"} {eq "CN"}} +| mapColumn "@timestamp" + fn={getCell "@timestamp" | rounddate "YYYY-MM"} +| alterColumn "@timestamp" type="date" +| pointseries x="@timestamp" y="mean(cost)" color="country" +| plot defaultStyle={seriesStyle points="2" lines="1"} + palette={palette "#01A4A4" "#CC6666" "#D0D102" "#616161" "#00A1CB" "#32742C" "#F18D05" "#113F8C" "#61AE24" "#D70060" gradient=false} +| render +---- +This uses `filterrows` to only keep data from India (`IN`), the United States (`US`), and China (`CN`). + *Accepts:* `datatable` [cols="3*^<"] @@ -688,6 +1157,34 @@ and a `false` value removes it. Aggregates element filters from the workpad for use elsewhere, usually a data source. +*Expression syntax* +[source,js] +---- +filters +filters group=”timefilter1” +filters group=”timefilter2” group=”dropdownfilter1” ungrouped=true +---- + +*Code example* +[source,text] +---- +filters group=group2 ungrouped=true +| demodata +| pointseries x="project" y="size(cost)" color="project" +| plot defaultStyle={seriesStyle bars=0.75} legend=false + font={ + font size=14 + family="'Open Sans', Helvetica, Arial, sans-serif" + align="left" + color="#FFFFFF" + weight="lighter" + underline=true + italic=true + } +| render +---- +`filters` sets the existing filters as context and accepts `group` parameter to create filter groups. + *Accepts:* `null` [cols="3*^<"] @@ -718,6 +1215,38 @@ Default: `false` Creates a font style. +*Expression syntax* +[source,js] +---- +font size=12 +font family=Arial +font align=middle +font color=pink +font weight=lighter +font underline=true +font italic=false +font lHeight=32 +---- + +*Code example* +[source,text] +---- +filters +| demodata +| pointseries x="project" y="size(cost)" color="project" +| plot defaultStyle={seriesStyle bars=0.75} legend=false + font={ + font size=14 + family="'Open Sans', Helvetica, Arial, sans-serif" + align="left" + color="#FFFFFF" + weight="lighter" + underline=true + italic=true + } +| render +---- + *Accepts:* `null` [cols="3*^<"] @@ -781,6 +1310,25 @@ Default: `"normal"` Formats an ISO8601 date string or a date in milliseconds since epoch using MomentJS. See https://momentjs.com/docs/#/displaying/. +*Expression syntax* +[source,js] +---- +formatdate format=”YYYY-MM-DD” +formatdate “MM/DD/YYYY” +---- + +*Code example* +[source,text] +---- +filters +| demodata +| mapColumn "time" fn={getCell time | formatdate "MMM 'YY"} +| pointseries x="time" y="sum(price)" color="state" +| plot defaultStyle={seriesStyle points=5} +| render +---- +This transforms the dates in the `time` field into strings that look like `“Jan ‘19”`, `“Feb ‘19”`, etc. using a MomentJS format. + *Accepts:* `number`, `string` [cols="3*^<"] @@ -803,6 +1351,26 @@ Alias: `format` Formats a `number` into a formatted `string` using NumeralJS. See http://numeraljs.com/#format. +*Expression syntax* +[source,js] +---- +formatnumber format=”$0,0.00” +fortmatnumber “0.0a” +---- + +*Code example* +[source,text] +---- +filters +| demodata +| math "mean(percent_uptime)" +| progress shape="gauge" + label={formatnumber "0%"} + font={font size=24 family="'Open Sans', Helvetica, Arial, sans-serif" color="#000000" align="center"} +| render +---- +The `formatnumber` subexpression receives the same `context` as the `progress` function, which is the output of the `math` function. It formats the value into a percentage. + *Accepts:* `number` [cols="3*^<"] From 467dfcc577a8c1d71f690748df19a65fe888232c Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Fri, 25 Oct 2019 18:37:34 +0100 Subject: [PATCH 169/191] [ML] Fixing advanced detector field selects enablement (#49348) --- .../advanced_detector_modal.tsx | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx index 6ddfdb22feda8..b9e9df77d35e3 100644 --- a/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx +++ b/x-pack/legacy/plugins/ml/public/jobs/new_job_new/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx @@ -83,7 +83,7 @@ export const AdvancedDetectorModal: FC = ({ createExcludeFrequentOption(detector.excludeFrequent) ); const [descriptionOption, setDescriptionOption] = useState(detector.description || ''); - const [fieldsEnabled, setFieldsEnabled] = useState(true); + const [splitFieldsEnabled, setSplitFieldsEnabled] = useState(true); const [excludeFrequentEnabled, setExcludeFrequentEnabled] = useState(true); const [fieldOptionEnabled, setFieldOptionEnabled] = useState(true); const { descriptionPlaceholder, setDescriptionPlaceholder } = useDetectorPlaceholder(detector); @@ -139,20 +139,22 @@ export const AdvancedDetectorModal: FC = ({ const partitionField = getField(partitionFieldOption.label); if (agg !== null) { - setFieldsEnabled(true); setCurrentFieldOptions(agg); if (isFieldlessAgg(agg) && eventRateField !== undefined) { + setSplitFieldsEnabled(true); setFieldOption(emptyOption); setFieldOptionEnabled(false); field = eventRateField; } else { + setSplitFieldsEnabled(field !== null); setFieldOptionEnabled(true); - // only enable exclude frequent if there is a by or over selected - setExcludeFrequentEnabled(byField !== null || overField !== null); } + // only enable exclude frequent if there is a by or over selected + setExcludeFrequentEnabled(byField !== null || overField !== null); } else { - setFieldsEnabled(false); + setSplitFieldsEnabled(false); + setFieldOptionEnabled(false); } const dtr: RichDetector = { @@ -179,7 +181,7 @@ export const AdvancedDetectorModal: FC = ({ useEffect(() => { const agg = getAgg(aggOption.label); - setFieldsEnabled(aggOption.label !== ''); + setSplitFieldsEnabled(aggOption.label !== ''); if (agg !== null) { setFieldOptionEnabled(isFieldlessAgg(agg) === false); @@ -202,7 +204,7 @@ export const AdvancedDetectorModal: FC = ({ function saveEnabled() { return ( - fieldsEnabled && + splitFieldsEnabled && (fieldOptionEnabled === false || (fieldOptionEnabled === true && fieldOption.label !== '')) ); } @@ -216,7 +218,7 @@ export const AdvancedDetectorModal: FC = ({ @@ -230,7 +232,7 @@ export const AdvancedDetectorModal: FC = ({ selectedOptions={createSelectedOptions(fieldOption, currentFieldOptions)} onChange={onOptionChange(setFieldOption)} isClearable={true} - isDisabled={fieldsEnabled === false || fieldOptionEnabled === false} + isDisabled={fieldOptionEnabled === false} /> @@ -245,7 +247,7 @@ export const AdvancedDetectorModal: FC = ({ selectedOptions={createSelectedOptions(byFieldOption, splitFieldOptions)} onChange={onOptionChange(setByFieldOption)} isClearable={true} - isDisabled={fieldsEnabled === false} + isDisabled={splitFieldsEnabled === false} /> @@ -257,7 +259,7 @@ export const AdvancedDetectorModal: FC = ({ selectedOptions={createSelectedOptions(overFieldOption, splitFieldOptions)} onChange={onOptionChange(setOverFieldOption)} isClearable={true} - isDisabled={fieldsEnabled === false} + isDisabled={splitFieldsEnabled === false} /> @@ -269,7 +271,7 @@ export const AdvancedDetectorModal: FC = ({ selectedOptions={createSelectedOptions(partitionFieldOption, splitFieldOptions)} onChange={onOptionChange(setPartitionFieldOption)} isClearable={true} - isDisabled={fieldsEnabled === false} + isDisabled={splitFieldsEnabled === false} /> @@ -278,10 +280,13 @@ export const AdvancedDetectorModal: FC = ({ @@ -393,10 +398,13 @@ function createDefaultDescription(dtr: RichDetector) { // if the options list only contains one option and nothing has been selected, set // selectedOptions list to be an empty array function createSelectedOptions( - option: EuiComboBoxOptionProps, + selectedOption: EuiComboBoxOptionProps, options: EuiComboBoxOptionProps[] ): EuiComboBoxOptionProps[] { - return options.length === 1 && options[0].label !== option.label ? [] : [option]; + return (options.length === 1 && options[0].label !== selectedOption.label) || + selectedOption.label === '' + ? [] + : [selectedOption]; } function comboBoxOptionsSort(a: EuiComboBoxOptionProps, b: EuiComboBoxOptionProps) { From 4e8878d5dab3be10af6273280831c563f1232489 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Fri, 25 Oct 2019 13:55:30 -0500 Subject: [PATCH 170/191] [SIEM] N-flow ecs bug fix (#49266) --- .../elastic_adapter.test.ts.snap | 1366 +++++++++++++++++ .../lib/network/elastic_adapter.test.ts | 30 + .../lib/network/elasticsearch_adapter.ts | 7 +- 3 files changed, 1400 insertions(+), 3 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/server/lib/network/__snapshots__/elastic_adapter.test.ts.snap diff --git a/x-pack/legacy/plugins/siem/server/lib/network/__snapshots__/elastic_adapter.test.ts.snap b/x-pack/legacy/plugins/siem/server/lib/network/__snapshots__/elastic_adapter.test.ts.snap new file mode 100644 index 0000000000000..50454fcb6b351 --- /dev/null +++ b/x-pack/legacy/plugins/siem/server/lib/network/__snapshots__/elastic_adapter.test.ts.snap @@ -0,0 +1,1366 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Network Top N flow elasticsearch_adapter with FlowTarget=source Unhappy Path - No geo data getNetworkTopNFlow 1`] = ` +Object { + "edges": Array [ + Object { + "cursor": Object { + "tiebreaker": null, + "value": "1.1.1.1", + }, + "node": Object { + "_id": "1.1.1.1", + "network": Object { + "bytes_in": 11276023407, + "bytes_out": 1025631, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.1.net", + ], + "flows": 1234567, + "ip": "1.1.1.1", + "location": null, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "2.2.2.2", + }, + "node": Object { + "_id": "2.2.2.2", + "network": Object { + "bytes_in": 5469323342, + "bytes_out": 2811441, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.2.net", + ], + "flows": 1234567, + "ip": "2.2.2.2", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "3.3.3.3", + }, + "node": Object { + "_id": "3.3.3.3", + "network": Object { + "bytes_in": 3807671322, + "bytes_out": 4494034, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.3.com", + "test.3-duplicate.com", + ], + "flows": 1234567, + "ip": "3.3.3.3", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "4.4.4.4", + }, + "node": Object { + "_id": "4.4.4.4", + "network": Object { + "bytes_in": 166517626, + "bytes_out": 3194782, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.4.com", + ], + "flows": 1234567, + "ip": "4.4.4.4", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "5.5.5.5", + }, + "node": Object { + "_id": "5.5.5.5", + "network": Object { + "bytes_in": 104785026, + "bytes_out": 1838597, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.5.com", + ], + "flows": 1234567, + "ip": "5.5.5.5", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "6.6.6.6", + }, + "node": Object { + "_id": "6.6.6.6", + "network": Object { + "bytes_in": 28804250, + "bytes_out": 482982, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.6.com", + ], + "flows": 1234567, + "ip": "6.6.6.6", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "7.7.7.7", + }, + "node": Object { + "_id": "7.7.7.7", + "network": Object { + "bytes_in": 23032363, + "bytes_out": 400623, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.7.com", + ], + "flows": 1234567, + "ip": "7.7.7.7", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "8.8.8.8", + }, + "node": Object { + "_id": "8.8.8.8", + "network": Object { + "bytes_in": 21424889, + "bytes_out": 344357, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.8.com", + ], + "flows": 1234567, + "ip": "8.8.8.8", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "9.9.9.9", + }, + "node": Object { + "_id": "9.9.9.9", + "network": Object { + "bytes_in": 19205000, + "bytes_out": 355663, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.9.com", + ], + "flows": 1234567, + "ip": "9.9.9.9", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + Object { + "cursor": Object { + "tiebreaker": null, + "value": "10.10.10.10", + }, + "node": Object { + "_id": "10.10.10.10", + "network": Object { + "bytes_in": 11407633, + "bytes_out": 199360, + }, + "source": Object { + "autonomous_system": Object { + "name": "Level 3 Parent, LLC", + "number": 3356, + }, + "destination_ips": 345345, + "domain": Array [ + "test.10.com", + ], + "flows": 1234567, + "ip": "10.10.10.10", + "location": Object { + "flowTarget": "source", + "geo": Object { + "city_name": "Philadelphia", + "continent_name": "North America", + "country_iso_code": "US", + "location": Object { + "lat": 39.9359, + "lon": -75.1534, + }, + "region_iso_code": "US-PA", + "region_name": "Pennsylvania", + }, + }, + }, + }, + }, + ], + "inspect": Object { + "dsl": Array [ + "{ + \\"mockTopNFlowQueryDsl\\": \\"mockTopNFlowQueryDsl\\" +}", + ], + "response": Array [ + "{ + \\"took\\": 122, + \\"timed_out\\": false, + \\"_shards\\": { + \\"total\\": 11, + \\"successful\\": 11, + \\"skipped\\": 0, + \\"failed\\": 0 + }, + \\"hits\\": { + \\"max_score\\": null, + \\"hits\\": [] + }, + \\"aggregations\\": { + \\"top_n_flow_count\\": { + \\"value\\": 545 + }, + \\"source\\": { + \\"buckets\\": [ + { + \\"key\\": \\"1.1.1.1\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 11276023407 + }, + \\"bytes_out\\": { + \\"value\\": 1025631 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.1.net\\" + } + ] + } + }, + { + \\"key\\": \\"2.2.2.2\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 5469323342 + }, + \\"bytes_out\\": { + \\"value\\": 2811441 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.2.net\\" + } + ] + } + }, + { + \\"key\\": \\"3.3.3.3\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 3807671322 + }, + \\"bytes_out\\": { + \\"value\\": 4494034 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.3.com\\" + }, + { + \\"key\\": \\"test.3-duplicate.com\\" + } + ] + } + }, + { + \\"key\\": \\"4.4.4.4\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 166517626 + }, + \\"bytes_out\\": { + \\"value\\": 3194782 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.4.com\\" + } + ] + } + }, + { + \\"key\\": \\"5.5.5.5\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 104785026 + }, + \\"bytes_out\\": { + \\"value\\": 1838597 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.5.com\\" + } + ] + } + }, + { + \\"key\\": \\"6.6.6.6\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 28804250 + }, + \\"bytes_out\\": { + \\"value\\": 482982 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"doc_count_error_upper_bound\\": 0, + \\"sum_other_doc_count\\": 31, + \\"buckets\\": [ + { + \\"key\\": \\"test.6.com\\" + } + ] + } + }, + { + \\"key\\": \\"7.7.7.7\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 23032363 + }, + \\"bytes_out\\": { + \\"value\\": 400623 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"doc_count_error_upper_bound\\": 0, + \\"sum_other_doc_count\\": 0, + \\"buckets\\": [ + { + \\"key\\": \\"test.7.com\\" + } + ] + } + }, + { + \\"key\\": \\"8.8.8.8\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 21424889 + }, + \\"bytes_out\\": { + \\"value\\": 344357 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.8.com\\" + } + ] + } + }, + { + \\"key\\": \\"9.9.9.9\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 19205000 + }, + \\"bytes_out\\": { + \\"value\\": 355663 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.9.com\\" + } + ] + } + }, + { + \\"key\\": \\"10.10.10.10\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 11407633 + }, + \\"bytes_out\\": { + \\"value\\": 199360 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.10.com\\" + } + ] + } + }, + { + \\"key\\": \\"11.11.11.11\\", + \\"flows\\": { + \\"value\\": 1234567 + }, + \\"destination_ips\\": { + \\"value\\": 345345 + }, + \\"bytes_in\\": { + \\"value\\": 11393327 + }, + \\"bytes_out\\": { + \\"value\\": 195914 + }, + \\"location\\": { + \\"doc_count\\": 14, + \\"top_geo\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"geo\\": { + \\"continent_name\\": \\"North America\\", + \\"region_iso_code\\": \\"US-PA\\", + \\"city_name\\": \\"Philadelphia\\", + \\"country_iso_code\\": \\"US\\", + \\"region_name\\": \\"Pennsylvania\\", + \\"location\\": { + \\"lon\\": -75.1534, + \\"lat\\": 39.9359 + } + } + } + } + } + ] + } + } + }, + \\"autonomous_system\\": { + \\"doc_count\\": 14, + \\"top_as\\": { + \\"hits\\": { + \\"total\\": { + \\"value\\": 14, + \\"relation\\": \\"eq\\" + }, + \\"max_score\\": 1, + \\"hits\\": [ + { + \\"_index\\": \\"filebeat-8.0.0-2019.06.19-000005\\", + \\"_type\\": \\"_doc\\", + \\"_id\\": \\"dd4fa2d4bd-692279846149410\\", + \\"_score\\": 1, + \\"_source\\": { + \\"source\\": { + \\"as\\": { + \\"number\\": 3356, + \\"organization\\": { + \\"name\\": \\"Level 3 Parent, LLC\\" + } + } + } + } + } + ] + } + } + }, + \\"domain\\": { + \\"buckets\\": [ + { + \\"key\\": \\"test.11.com\\" + } + ] + } + } + ] + } + } +}", + ], + }, + "pageInfo": Object { + "activePage": 0, + "fakeTotalCount": 50, + "showMorePagesIndicator": true, + }, + "totalCount": 545, +} +`; diff --git a/x-pack/legacy/plugins/siem/server/lib/network/elastic_adapter.test.ts b/x-pack/legacy/plugins/siem/server/lib/network/elastic_adapter.test.ts index c3bcfafac8757..542a2a0108a9a 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/elastic_adapter.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/elastic_adapter.test.ts @@ -96,6 +96,36 @@ describe('Network Top N flow elasticsearch_adapter with FlowTarget=source', () = }); }); + describe('Unhappy Path - No geo data', () => { + const mockCallWithRequest = jest.fn(); + const mockNoGeoDataResponse = cloneDeep(mockResponse); + // sometimes bad things happen to good ecs + mockNoGeoDataResponse.aggregations[ + FlowTargetSourceDest.source + ].buckets[0].location.top_geo.hits.hits = []; + mockCallWithRequest.mockResolvedValue(mockNoGeoDataResponse); + const mockFramework: FrameworkAdapter = { + version: 'mock', + callWithRequest: mockCallWithRequest, + exposeStaticDir: jest.fn(), + getIndexPatternsService: jest.fn(), + getSavedObjectsService: jest.fn(), + registerGraphQLEndpoint: jest.fn(), + }; + jest.doMock('../framework', () => ({ + callWithRequest: mockCallWithRequest, + })); + + test('getNetworkTopNFlow', async () => { + const EsNetworkTopNFlow = new ElasticsearchNetworkAdapter(mockFramework); + const data: NetworkTopNFlowData = await EsNetworkTopNFlow.getNetworkTopNFlow( + mockRequest as FrameworkRequest, + mockOptions + ); + expect(data).toMatchSnapshot(); + }); + }); + describe('No pagination', () => { const mockNoPaginationResponse = cloneDeep(mockResponse); mockNoPaginationResponse.aggregations.top_n_flow_count.value = 10; diff --git a/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts b/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts index 5a871a3f9c9b4..eff5fba0c54d5 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts @@ -193,19 +193,20 @@ const getGeoItem = (result: NetworkTopNFlowBuckets): GeoItem | null => : null; const getAsItem = (result: NetworkTopNFlowBuckets): AutonomousSystemItem | null => - result.autonomous_system.top_as.hits.hits.length > 0 + result.autonomous_system.top_as.hits.hits.length > 0 && + result.autonomous_system.top_as.hits.hits[0]._source ? { number: getOr( null, `autonomous_system.top_as.hits.hits[0]._source.${ - Object.keys(result.location.top_geo.hits.hits[0]._source)[0] + Object.keys(result.autonomous_system.top_as.hits.hits[0]._source)[0] }.as.number`, result ), name: getOr( '', `autonomous_system.top_as.hits.hits[0]._source.${ - Object.keys(result.location.top_geo.hits.hits[0]._source)[0] + Object.keys(result.autonomous_system.top_as.hits.hits[0]._source)[0] }.as.organization.name`, result ), From 243a9815e3685631f85c27c5c8ea1524c883cc30 Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Fri, 25 Oct 2019 11:59:01 -0700 Subject: [PATCH 171/191] [DOCS] Adds docs for API Keys UI (#49135) * [DOCS] Adds docs for API Keys UI * [DOCS] Incorporates review comments into API keys doc * [DOCS] Fixes typo --- .../api-keys/images/api-key-invalidate.png | Bin 0 -> 129223 bytes .../security/api-keys/images/api-keys.png | Bin 0 -> 111824 bytes docs/user/security/api-keys/index.asciidoc | 86 ++++++++++++++++++ docs/user/security/index.asciidoc | 2 + 4 files changed, 88 insertions(+) create mode 100755 docs/user/security/api-keys/images/api-key-invalidate.png create mode 100755 docs/user/security/api-keys/images/api-keys.png create mode 100644 docs/user/security/api-keys/index.asciidoc diff --git a/docs/user/security/api-keys/images/api-key-invalidate.png b/docs/user/security/api-keys/images/api-key-invalidate.png new file mode 100755 index 0000000000000000000000000000000000000000..c925679ab24bc64565b780203a05bf0d1183ee24 GIT binary patch literal 129223 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 $&blZvHHdhp|(U$!7gmduOC7f`) zoW$UKixsSe80u#ra*EiwI&?tYTz)=2H2!P7=y3ffdU@I-Jsm@XoTOa ztV5~QPh<6UK-iWlIe}e5Mh()Eu422V3};@t3xH#XntQKKv*pIYUZZV5nz{OmfcjO` zxP)%g8&HKgvRCW*!W}~|=IU}>{dTLu#0M(NTb##C7AFmzLTdloziFaX@s_@|vchg) zg}y(8da0}xgXmw=G#A`9i&&cz^O!_ve!?Ioa-%$1l{ZFrtVH<0ciii(yR|fJ&lIH^ zo!O~CWpQMVySnE$4JCC&nv|EGcvQ1RE#K$BfGMcvT~mo~0o5Bh*xeVP*Ciey#Guvap3bI>C{Fl=(>~bC6vxSR-;E=QY%>miBR$g$NK3XIQX`4 zOH5jWnJ=aT*h7x)uch|SNZ#rGcH)G#T|0h@c><|8)qHMg=6xn1-D4Tj^@no?VmW=O zE`RwC4S}>`VI=i^8w8>9$rbyB@5?@>!|W+8jin24eeCHW3MXRz-O>M=;ZET$vWpe< zzU=3wJ6JR*%Zw@^eMQY#p~?L2*xSN!k=Q2|nzaUBKN*A2hFhhaL3vaQ zIal30N%CHRxg}Br*71E=?(|^#qG!#8!?rvU#u4B_xu;=syKp=09p?AyEZ+c5uC?32 zcQ+kFwr~>c$jxio1sbC`pqRQS0C>E;qFpX}u!|K&C>^2FM9Q+;!=mZ~CSEwK+}S@s z^IQ;FbTcdgmW+{X+ZY?uuNl+m%k)nwfPhs27`-(Dle0MKqTNa=M5Tn0gQ`^qr!Bx4 zWf%JWxE1vu24$SE&-j{XcMcP#_j3shDjrHu9R3b02LtKSv7`6U?&N}}Yy z{;KMhWb2(ZeY;$Dacm_0d>#hSe`0(Gq9QPR_S1rvc&^5z(n_fqVHoi3w`i{bdcNFg zv5x#!$WrVWt2?8epQR)2Agu-HRD#~X2D<Q zY-2}?*xDS)>`Xzm6}U%*eKT}~kb>sil*?5sU==e(wR09JI?)Hmfmjfc_|{lfbJ~Hp z<}{1xE`%Ha_HWp==(N$=wGA(^uLWks&p4bAi&0`5F6AK%!9hxnn`NPjjPI(;YmzQz z3mngC2z_3`&xup~g7Pa@u4$u67r)r3sXwPg6a`|9QY1T5eHyiBSMOdsRC@zH;3QuC zDB1R5KB4tM;-v|rllQd%D|>pqoJnWU@);kepC{G}+_t4nThc%X@tnOFKz^se>eeLq zs%C~98w~}hjnc69Xebzn?6&r$@iVd61qK#AP-i{-#U|wG%bh4%DRDUjTeKtE&c7`y zaoiJ`w88cu9}Q($^!W{YZ@m#kvOkaJ%;%#6meeCg!FOP*rHh{ho#}5TU@~yQ?Zksb zklkI8gG18CiNjf|PTq%(S{Iejd!f!J5YK?7Zi7%2r&FY7$zbwlnKtNuLoLJ=ph9q3 z;16qjWE&pDxT+0b@om87T<^k&YlYIvBDGtq+Mo$u3I)I3iL^+yq4um)fc4|7al5@Ol@zwFDg8{+rhWp8BjiV^R$32sK=EW zBmdI29{utrKpgzV0QEm2cbx$FYdg7_I)qChB)yG81v7U-R}QuwZI;5s^4qIri79Kk zQVBar`=j*hq*oQAIKAtE=sRc^7y6o$QTVPb{&u2V_>hg@`Cc=gub1}!YW-cHaph{D zb=w~j94Nr1uT#WO;mpg6Z`3+}OD6-qz{#iATko*H!0y!*V)J-v^=XQ#6)^^Wc``Ml z9Ru93NdKku<(k@JASBd24;26Ld7bh7f&bd|6eoQFh&z4o?b{e@+n5~)c?UWi4&}~@ z$sdup>AVtW#rHNO;p;Nm5oB53 z^9YrHK#KUW4hK?9xe3x9Pa%?qI>i6m6cEUoA7T`aa#^ZX(-2w^${h1W51sKTR-lc5$ z6sy1kyP9Z@!{X!?2H-->k$or--+`eIVl)^Sg~8Ww)Thw=MPE({4+Iky4d`+N-oE+W5wU5qb^ z>|F%O?}oystI~7*B*$)1Uuy$EJqqs!b)3hY;7KI-YU}sBD;7hh**6X*B}X=S9JxrS zaA`oKX$XN=A$=RhJ4u`%A9m)iiqVhBX#+ER`#PlOaQO@jWZahT-9wu|cEx3zaIO<} zCUmA+-x#2Ldi2VbWI&-%ADHjWTnE)?lLD`Q4S9nNgavk#xwoX9Z)wrBV=R3aW4?-&$vv{H3{3SJRYL$haoTWVit^E& z7w%(1CsRY2S2@P8yMDR#wMk=ldqTI_?oKSXpWN#UnTjiWQ;C^ke#5di@eD+nl6YAmCuh$sk17m*qQ(gGnQQBhDS zQ4x@qs0c`nv`|8bh=587J&+J0y(A$(AOTXihnaU~ocDhB{&&~<-L<}R)^f4TIs5GW z>}Nl{IIefxtSNn}jfNSC{OFnKdK&?pwx^qk3ws{b8??ol&L78(mVq?3Kt~%d8-Vft zB`KUal^c7vOA@uyoSJg**PqO)nM%%wjgup*Y z6dK;v*jGK}4{iMbnJLe+-f&kW$e3)Ixi(YVB(z(U+gBRFP$&6SPzwb$cF5cZ_3ks& z01E$?&{mOW%WU6IFMyP+pTkZyt!WL;_|Rn1c(+oMJB~*wjOSe1Osob9m;v~I0RwI{ zkQk}^)+0%!J%b2oMvx8A>rcy&1?BP5ZMx8nF94gRo8^}-Bl`!ArJAHYx*sKURGbR# zI+mWc#ygcNjnGb){!WTXs_hNxxw^Wiy?JnI@T>DoAGLO`$q5@D{lwXt??PFU(q?(- zJ4o&K6&h#6xaW}~=&nZ9;96`6o612n94TBZ+tgvVP{?)*y|TGx*Y{eARtYv$mI@x) ztJKyzSep##xlcrrf`uv+Vb7N{NO&r-fK8%S#Tj>H+hrz0DAld5?PqfAx|l5a%`PNa zt>e3e;0&JWNu%UcSbBMg)$#70efPJ2o;iB_@%kj6W^xpd4;UyrsQuGN0++tI_goH+ zhW55Bw4-zg2#DkQM>o2!_$c63@;zPy@v?0xMHzfREx0A@ncVkusf6vyTej`c?cz#* zT5UGwG!I1zKWqw{Zs-;^;ON7N@ZK(j5Q-Fs3#{M4#~)e>Lfv=AlafW(XbVTv8y^- zmPL!7pn;-){{>p;j>B8KEJZBcyJ_f^8?&UcG33!i_2IKh*OX*gGyWlJ$L{|lK>jJ` z$Nh#;{nfIs&<-UZKdN)F35$mjMQ_aDX;mRXo%eFy+&D^z;HWEAAAN24#j49q`nXT8 zpP=At@oNp|)|a;LUmc(9DfkwfV&(QGNlMcY&(kurHW8M(imU)n&gNrZIL~ylzVU>t zAwOAUc7=z$>cQ35F6i(_6Z?-_pMF38b-!;sKT>QQ@gb-GZEjidgY${Tlmfx_j~k@F zx3$r4`vK2HYkH&d}Q~Y{Jkrgav0O1daYhcdB2&0!}5J; z1xJ(>AvYt?k<`P2t#5rYVKs3&ap&1rX)O%|=;v<`=3LIS-EIfL>u0ulWPwEy-KwPJ}4{*IR;dK=Og!@XpP(<74A}E6OkvZ51=kAiakRO>Hli16x#i9K1Um zx(yyy-n%dEIhk0Yr7MO$$xU@ zcFD+%Tz7WYTRIH_gg@wlnI0gxgTNkW#C$_5Q+g0*T*;7#*GdNjNA}05+e#7MHXJC) zCCl1_#SDGo4miSpzkA3MIl#{B6%~P>JyOhfql_@+Ue7XPd$)+^Xmpc@x?L>;j(kIQ zkhkOn0sr$J!P^OYLBi$44UgjAp!S9cuF-;m+q#{@eIxGWb8|(uBLI%smD>sn67(Ugu z?+-lOpjt3c(G)!je|l9|ZOnHh+6+D7mSa>QE)y3-=lQM~rFUDbsfS#RdGlUIH( z+Y|e3tCp9zZ&yuNGuP$Od*^Abflb+hsiaI(q5h?sq($y?FM*H46SjjQTQIFOy{aR5 z;>>>&_roc$qIO{w6tvu*n@ShFHeup3QxeKse?`4oktIqeBlhK>nwfJ0njrb5z({rs zKIgB|MEeV2IMTa}el%aWeFdWZ5uHKag-zBEjWVWJr;uu;k~5Is zMYF)b4&*usL8|Xm(&wB@c!|ViZ z<=f$5?-$A>9r0gq>lJ(3dc!G(o40r={R4>K|1^-BeqOjM8j9piJwx(*Y2zl^D4eZK z8Xjg0iTsCL{>T3H_?5}b@#7!vH}AI3>F*Me0MqLN*s@FahX?=E%>Nw~_rL%5`0@W~ zFc6=Lnn=|1?;99Me-(ZCDSIV@_QNg$f1=CKJAZ6|ycQk(j0g0k{#TgvY3jKjdnT{_ z<}LL@y!#&yzXR+@|9b0x2m1dBjL<)WR)sN6wSnvY=D>5c!m<4kIJ@hx1ib0z3#A8q z#(L7Ai`3R=%$Oqq*2TjdFSDcRu6f5GA4|?Z_Rd-n0VZMyny{^iUVRCO5*iE}2x$tc zW@-LSw1yGO%^K$NSmxN}W>qhE!R<}Am2V<>Pc!swy-C9P*}(J{F*3fhPY?0Fe)yRe zt*F56k4@syc%c2+iPQY))#_~<)LeXXG}6~Re*OcqLe`^vC|yC~?+@HoNy6s)&d&;g zyxP^_dhUz)=5&b#=b8w*M22*to{+!zSaK{SXur|w*qa;uN2`K6s4cI2H9Ya9=xC`A zo8)`#+lrO(74O@5`?H@+a{!|XWH`!K@YzX%6iPYAluckQG;r5s$~YN}OJ#8D%%DK_ zZ-|{dM8=>t0*!st)XvLpBCDQ~nzZ&RniWzPX=M_+?>Dz)%@~?HxsQB{W3C1IId;fFJ`5PGgJ6P>CrhHu_}o>I@>X-ex- zu6mOTn zMkA`Jsp|w6&3^vvX3$+Mky4RX9zglZCWQVOF8L22h@ZGFw}+OE|C$y@XR3OlVrHN? zG~AP#Q!hd7S53Zj`RCtGSq1c)DCvJ04556Db3j|Dn*po*XMGPRB(<4Fmfx0U=x~!$ zM~qBA1^MOy6&@Ans8pZ%~6Bql(07{kspt>GS0G&yJRHKVJMx=m@KjhWDe}iBXSzqd6SUg|`EQ0%t zwK4(1cr0qdw#WrsLI$cldT+-t4*xUuXNiquj!r-ra$?(%{%;t!uBeG>j`sPmqSM#* ze@~RB0Es=8Tgj?L=Ra|qTzP8&o$;u{lPUn`DtzM zQ1hR-hM^ogUbT5I9w8$b<)UbY9KkNf1ogy60mV5 zexGjSS6Y6R*Zq5&*6`(zt@`OtVRJ+pqq++eJo;WVrJ>Z{MJC>cP(zEKs@hs1YdR0iGnp~*m}! z7C&WDSggd&s)UHI@a*9dCn$*!Ai#@&5Jz!0jv!?sZ-Smtoq-Hlc5JdKii@W8 zx|y=@hEY)-P5`ycxAk1LSEd|C71VPfP4l9Fnr^_Gc2hKqegvFsVKH#}aLyItb=v@Zn0~@vTdLezjN)bzsMC?clcHi8m=#?lt7`qx?Uvn$xYO?(q*JA12i8uRG zxX|3Unl=x_m-xeDs?h3%*u*64*tuPQZPC!On>+@*>Fdr%IjlP!Q!i`lyFX(-B{bLs z=RI^kjBN+{AXL6vh~>yUnI1?^#D?HtJ${TT!I!eSM={AlabhAC{*DKb^RGaSW?Z74 zU*Gc=UAjR`53oMuEwL*<#yFv)Qz8`ySo}Cg;_*O~hcD&H2z1UT3tW#)(>6lAu>uQ% zR%dt}?Z}g>Co6HHkkc0MQqPH-kHyJizz-yc5I*`w>ba0f_s^aqtq`W9-1_uqRn zava=tn}$v17zi?sh|kpzkM;Kw$=8^mJA0Mh{$&T)L{_5B8ifkf1@kCUssAeN)BLtE z%JS0N;ok()t732~%EuGvUi(JF=>E|1lTQbjgQX+@X)1bz6cXygHU+{8C(pLP9t>=S z(ZUCN{f3tQEkd!RoY9Lci%n#Cg-74ldp1KBQl(8EBZ=@Rgl5D&1SlZ3Jmq9R)x*5l zBcXAHLF~zoA+lM7JGIi)6WZ=!Vh|7t1!SYJ7aF#lv`9A|sTWpN>GNsbxzkW7g2 zKzvf-pM(;q=muo%uvg6GO#;)gAs8L-;5xE_6y~@JUPH`xP_er7eBdBiUI2vbFHpq2hchcg{G6*|zC!gvsSXq0S1zxIos^QyY$VS@X5E-Y5s%OQ zheiSC(YK!4U}j6TBG>q8kXDKyjABAtlhRj^9|^X?=Zzbp%7Grr?J}5;vk?rjkwDn& zFN7h*4SK9{J+Uv2Bs&M3G#)9L1fMcz_T>^343WccHcYO}gnxWJgv27f1{=v|b6mD# z^u|pTPg&nl%Ql~VQ`M`6Epshos~Nb;sNgy1>SsZz4Bj!1=x%MUDc5hvDkde%0hkJjt0I5K14} zOvV&v!J*VwENk664Zo#Tx)usx$qFDV-p8TkatA#~)0~^GvS)&%Q&l&o>DLNTxdh*C zdCV*%YH?c6Q$+=UYNRftd4qhdPYR=PDFiIMx4!Vai|vPquEjZGQK84EZ`n|Oa{qfB zRbO#D1o_j$Z~bfbf}I%9YoI#s2PyGfl{=IPcK2-4nZ#2H87$M4a-Xi^ON@g@u4IhV z4+DwOC29_#%R2OtRivmFtil&J0Up~bz8wvJ zP?8SBHHFmbEWM_@t>Tg2h*&*-3PLw*Z#X-H)+Z3bZ^q>AJZ{LjN3RJYG=4|)h>d$Y z6}XHI3njJ#Rj}-HF<*RFt`>?o1}&-6=+f-F%fmhSy`FOsg5b}mNmBL|V!MenW5a&W znNYxg>)Z9*=sy@4(D1FCN0mpF6p!TG9P5dq^X}IuizBC+up*ZP;+g51P^PiAeG(Dp zf->$OxsmEQUX#_E)pU#5gLl?NH^BX^yRG2XemgEJ=NFXgQ*?lhNi< z>6?aUeSpQ-^mP}k*Yy-@Hq(nKDn&Q^M}T5#zLY^DhgzRVY3bzttf!Z0r5fat@#Don zLp^GCdWN;hg0}#mc`Glt_5>%tzI5>VM-7)K$!IC^;s8)*#eSxZ=*O_3`c}9wb^U@? z*M-bIQ9S)ubj+Fs1H(FbC~FMwSMLF|+>DY`G@xc*N%J-gWtZnuiYRjT6hQ%<;~I`W z^%r8xU6q@bSKC10MpGlrT8^^JSertyYhlSfHcrr$QG7EIn))aeC+P8R8`Y&DuMZ{QIg z%r{xBtT|^oK#uVpo!o?v7?UG;!2A5wNO^9ySUK%GFBud-(9-p}v@*9d$6gRmFIWnm zTIZi%#){?Stdoe_XXJk{+t1#U9O?rp^t@6QLn-RTfapXw#BOq_|B=|dahc2wf?E~K zqs3CjMhxe>-D1txIj9H<5PLqg{824*s~e?oo(Z%JJF|Y+C%TVpY)Jd)9wWTM1F}w2 zd+06Ybz3s1pYe-VaaRQ3RZKBkb>nIfX$J4hxk?yYaUE`1_T|d~VI$M)INSZeg?uR> zwejZ~Bp;ArYUxtDWvpq@-_rD0(U+*vF6fD#A_W$G&`G4rRgblof zAlwQ{-oU75D~CV0+K$uddbz6AUQXE#=*r#MX@*TYxFKZLe4gNSct=|XX_Tfnw+{Ua zC$jvT*QXBc*G&C%QOvNIX#G0A z{3IcVoi-g3LD~>!|9QRB6v5?#S1#h(+!hyACsGbFO^=~I%0F9wSPjAes17FdYe}Nb zRB0a1Pdr>Fu8tlor95zx{*WDudqS$Cw{U%QrdN#LZj#MxyfVu%u^9YRw>ZjWuAHch zwkcZCKQ&&^Q$+hbFQeiPdjRe(pRVj2GvNgw;~<{rjpwb$>e7o8*mXW} zL-!cjUS9SF;R1u~1gh@gzP~QdI~f{%bEeH#c>6ecUgdI+Ns4Mmntc1-ER^G5nF-?CHmp8GUW!$kz0=f`VpDDAKtnD)dsOjSY;F)R z@GX?H$LSpLWWCYi%5yDGBf22|7RvluyDkyk$pW7}eZ0Cz#wsq^w$nP_*OB(L2{*HXV`Z^-eu;L)(I{Nfy6B<$~(oz%MZ4(I7yenC0yl)Fci zWcF6i_`ynVEo7=EAfVmd>HH#vUS=($_hvD)CpFGE&!{8arPe1SZEPsuDbKIJh|uHT zX<}g0xCr#R&vfG{oVuexker184UM@>o@lzFgfm^i+cSjQ~PCG|fWP#fht+}KSJF5px9azNNx#m>_697`zm_Yy6XkM=ZjrqhW$sYG5-6FHa<4Ei zW32;53~E4k3b01f*xQJa>_VHomS~>ibU?L4@W6x%Ql75N8P{-)NiLi{IRQ_Zz#`|& zgGt}sC7CQua=$AI+FdBiD#-bA#BViC&A9PJ#&|POsdd)AQWS}<{h$NZyK~97#GQFn z)#hytN=eG+H8b?RHQ^0P7omRswHpQ$?g4QG8sF-AR1~utju`1`w~3I`kRi|i;o`~wmbk=N{33WWK;`J>1g)-g_%A^-Zlf@ z_bYScvP7q)x*&$aGq}dHQ0N98%h0QQI_uRZ%?<}V$2%W2c*nC1!kMvuHYxb;8SBiBhPuKKZu4?oFfqq8Bq|{L`YiZV}uT7*VjUbW^?j!mz}LDHFDZd z4_jc_cGsZ%r~T)}`;@#{=X9@{`wYA^8PqHX5zI_B`TH8$@ubh3a&sm?itthVG<& z@TtN{D9TOP6CymX{7&S}l}$;KN;#&In`SD~rdB=f*P0XhYom#<|ZUWf!iE?9LEX?pHpN4aP8QBwnDi^=%IGAD^^}z(%zi zQh6Eh-{h1k)Vx>sgQ+DkJ&^8RkCt>Lo%yp|$7}&>*{m~NaBCJ>NL^eA;!o>6*mme2 z!a2UY6M|7PM0Pg)US8;)cGbHDq@WkL5SB)|8&Kv~`3uk@6*9tcnd0W*y__4>c@&@i?K!R`)pw~2({+3P=WLnR6 zMsTBGp`1+*-S@Q3rNT8Kgf&pVBDFVZCNvjfaP`=?5VCu(QL-KO<%-E0DCg4C0~0aH z1-GKnjc5ne!ic!GZPOf=DY*>06^ew}>T zt@xZE@ZOaPJI~a~Wv^#Ix3=@ay&M#ff*pXc1#9f#fT2#q^U#NH! z8+^VA3*gpOm#s5EQ4y!KvL+BVUQ`(>l7ws&~5(n?=3;V&5iD8 zbAs3G&ygT0-bBw2q)O(!H;MBa^4@k*RX*a%yM6pt1!QqGuQ(36`zR;Vx0@; z;+>w?8NcH4Rk?F6J9};BSvaOV-g^$dTu~+6dm>VtyTrS68 zU?u@ni(1rh)eGJchtlryfg`_iG6qe2!W2xx2cWFW^W_8eWa-oiARYH9ZMHvh^BRsEaYjQ~CluMl@9!kHUXUFkS$C?E7O1fu#@dHdXX!6&a z7B3Ifh74MOa6ZxKz2FG{%d9y zNS!Opw5Y{rx6xRpMO2SHfNUwN6)GD zb{r>Dr^U9&9!_~L;>u{iqAXMTt9L8d@G0r|K(1pHsaFzhU1`n?Lm8G~MKz(J=>h7gSNABe zt#U2&!1^%9sFmrJcnblP&$zL3<4aw!-xYh} zUhdj0bbWWhc|x6doJ@P<+lVgZ=nGDicGe5?zv&RqJKzHg;}k*k z>P5xdlBpqgmF+wN5^S7&`4~}$__B9VH-CmSd7=qf@26vyV6RmN=o08dvvPSOBFtbo?(>dq2ao`w~hN!|w`*-Sat2 z!;P&$g)v2e&j(FXf4!C!e$K+yBKo(#guJsGxxz~>+!{C&!Xc->10*;gulj*MC!-7Gt@Vq$Drb7MUX zHG3_)H7I5D3D)ZRg6pp}hc_JDa4F+d2$dQ#ne@W^O-R$xPGi+3dg!lM2lt`4ip@(1 zQV6Z>)H){t3-rua%^~Cig}ZBZa#aU}BmXwCmusXbTd4Uqaf8tH`kml6&{j1U=3zS@ z%mk#r-Dj)37bN@Y<1Ry>I)d0Qzfm`Q`G5<^=(&H?LUZs!xbH4_1vZ<}Wn`-z_Owr-w}d|L83G-3}bWK^&$sB zH?s(GM8mO?snbHM+3_EI(t)={xR6YDOkT#$f0*c67YOjT!Aak~O8085HpS%U$l-2T zhehrMd83FL>s1qX(Of)z#Z<~Sg{Aqte&ZrM*KY)m58`L&JcqIeC#HJRDyBRb@8rgY z?8g~B{?diUitm){+YRi!oosT_vdOcN9=$Zs~YqzP({o;^BpbY4{0aKWe1L&|X!!;td6GJ_K z^b>yls|hvx&@X{pqgWM2Nk}wKB))L%FbUVy*X($z7kOg&u@1Pyq~{dQRW(vGEz$Ys zaahDb{9C+R7ZP-o$v@N&FH8%Yo-fcQtMaCY#{&;Iq0+}`R=q2Vx1z6NFPB=x4Xum7 zQc}AYUoN&DiL1)7H<$Gc(t3_}qTB#fNR-oarfi|DqNeX$L~~coeGUl1&U-01_^elB zwZ?_~b&O zig>x??Ls@kfuAq5#h!sq?Uy$NQ~c*cP@8uj8}arnag)RfR$Dv^;Mg~QK9qv4Pw{(= zhj2hW*4{jo2H0z4RCn=(rBcYh?bOv8hs{qVTp#5d z7RvQcy2o_BgZOJf&hE-Efwev*6u}gyKlP|WMdPjT)QQW_opb&5P)<8$BrGyoX1N1f zi}FWek0~zVM9HkaY5tQz&-PFH*B`=q>O`!jMG&n`IT}Ia%I8u7rl{6ngMi>_FveDP zfa2_Rt@+6L2E>Q1dA`h|fa0;*LwKso9)`lE8kYzK}Sm}!qquB6kt$#bURjkiVUKYi|;{P-s ztjWWH2{83_SI3uQaHHi=1p-}bOI9zNSJr<>wNJR-Oml!gUCxA#_HCk-K%&i81CkJS zRZ;SJnp5suryVcz6;h|`qtL~Gvzu;xS)dp{B$8_hxTm`l6$4O2V1y4rtn%v$+7I|4Z;7}#59X|_ zF4FH<=RsSz3;n3!N>h*wv+rA*Q?2mh#Pbvf$W4@WN?@McSpY$rhdV-Mi-x6UMt z+uwNwrpdQX+u`~_13j-2pChpb>Eh8Jza(?R z6RPnOOV?4N`EoGkg)>g|sS_uJ%PR~fq0!-?S1CrE`H>rFgXEJ8L~ra?+!-uq#Kh?@ zELdoF`Ed8in8pniub+08Vh|hN*$ED7*;j_8Bp&Cw-o?DYhqtcy!j3kY|FTiBvy~QH zL6xNTy?!$?Q;oB%XpT*S)rK_rp&%3tqBq-3L$Bn>)s!j8_Y1Z8??lnQ6Eg@uOf*hv zkCE=7M0h5CO808~2B3;u?_3cW0|@L#luSG_;9D0EcY;;F83!n3$##ab)N@)?@#su2rS3MPTa>k;I1V^5Cl`%#Z!Qzg{cxHD^Mu#FBk z4ma-gP1Mfj)wk%|l>H6^L5E*XnKZ%xpPH(zcqe>ltfJt0g3a~c!&CRY%7FXUXR8H( zvsdj~xOcY(P#3TTx3h2v1lIzz+SoP3Tx5lEiObEp}2 z*wj$&ro*Yv-n>U;g^<w6DHhh#M*T!cQrcxiB@a)NN#uavk1s z*dk5Zkz#3x7>_s`$%-{kHRwX76ZchWkQ*Ug2D2+QTapV}c$;?pqfJeI)h6q-b-%Nd z*V`y9D>g5u`t==}2|cm=!Fr|ODRH*b0kBiU=)N_-X^kH)t-R6y6!R9*(s#)_9y>SU zt9s*IED0U!AD1u{mc{02&ptAvy*s8g+&1;|iRk#sDY0Meunoa)ryg*6#;e}xw7M4^ zRx%l;yh;S8gZ#LTB>LM!&6(wFRog;ok$N?D_i@K*oa$}+V-)hCSDh<a0xto!!d1-LxuP&|WI+V>as>v^w_x1U&?gUOC_DsTwV3%W?R~J%(`VDkr zVHn-bE3M;;g?9dC<#-(aW(YDOfVl0%KGQm%DZH-%fJT@Fw}u z6*c=SdzmzC*YC79q6m1wnS4ebIX#6JI6}pUg{4UP$Q4#>OHi?{HyY8Wb?AVw=ljx- z**N_7h%bfT2QFthXPXfw<#KQi3R%g?KQltxEW|7DLU~%Hv{@u%E@21$pwhyV&7mf4 zH8AAZijLsD?Khpt75583!J)%5d-H)pbYFNAR^Qv#S-?HWA&_K`))LGq=gUqlfXVBk(@(No)2>yQ3!A6 zg^(U>`}qfR5v)y*oMn|mrUC|Q=HWMQ!?#EuV|om~``QH=czCS04CbKJ)vX)nud-fH zcP@IQt@wyH>W;5Uc`)hcbC90Y5PV<{xi<@}p=v2afSj3knzy6lPK#^(M!eWTM9!M^ zOs%|ki-z6GIR@ZtUM_Gz*IvKdjB7PQrGEoZ(o$t{ccH>1^eU~V&?mW zfjbzGpDQM3EGG_3|8Tq~tFUl@sNB`WK9%m9D6u%VYsfxdFdfIVbGz!%X(W|N&X-lyNYf3| zd{n903xg9Cu?;L52Av8y16beh!hRdi(d~Nd#ae0+-!MQtpfF-mX`95M?vNcZsEt6! z_bxZ(_6GGz)e*b8tV*J3U0URZ>`1{|cDP2?7)6dLdO&_3JO^{o4j!qwDA@g{InplC z<9wXC&eE<&MdfxcUtElPIIk2juGKUHt?6B7YcD4|nc5S&^kwdS@hb(bfel+_N2dDR zzeh!d93|S6dwjE>FtaT(2N64q4uWa9=rq!lf<}GV=&NIOoB;J1L#CcraQY?1yvuP> zHn{7C`MdY>_kl4C?>?muZN?jx7IP5j3yLA6JN>DZvIr?3z^oYXEnI5P5Y~3ZwfDhm z;ecJe^9I;bt#ad)_(ATi_BUR;BWh;}sf1gy88?1pw5EsGFC9I!0K}fTk%>zlcPyh` z^e=y7a_rgR=9*hK$bnp+dXl@tJcsAVq=lq0)tjHXDvn%8<_sp>v98T^*QlL`R&(-; zyTc{ZU{P(eds?_nV2oM54X%_ATI%MjUSEl<)Lzs~rIj&n1HnV_t5Hu#`HhXus3q7e zjT0jusc48S0o;@-t;X+24ApC&Hp{3nWq-pg=m3r~6mh(&$iHR&5T=oEn&zP!HslDj z&M0u=awehaRr!-MS~42c(H_--he>qBN*yn2bu$6+Ex z2dP6eQ(|@aG`IareBuFoq7AWObPjXbIB7jl|3tjCB?v974WO@((-c@iO%KtDgBA?C z`eJ1@{lf|oUmEgl3s(p1>P$kqh`K2g4Tj}-d*u!8UO>&SWslNuo}~e0*0P>ccouyX z?a=l$!E7S*G9o;tW`pqG#lj(m7VNt zR5OgoxO*N3E}UC2r^0^^OWQ__aJqZ`5rZ8L<GOdNAM=1a|m?6G*jGs5F@po^w4NS0P-gF@# zmFXWdjNyDcLOgvSR!wfN?Yo=$Xm#=I2+nu@rL0M|9K3}L*1K6Q7gBho3Jqy$qraL! zw;M4OBd{yP1v>B`D;QOJx1iL4jI>c-LX`X8&I@su-lOUJl3`dK{W9hC&9Cz|c`Q@i zTkR(pm_g!+Q1NZ@Kpq2Bvszo=NcU*P_yb1D3bd;AwwdA;Kv$UiVx(l?8|!i|4WE(u zRl&d(@G6QH0S``=Xt2#?p=_Qyn8Ubbh`ozG7Bl&JzjB1&-u-&xbL+B%>E_Act@d}HJWfB^%z)A~~qm4mx@r6bu0>JlS7Y>mr zaxA{8m3_0yk6kG48@M!*WOw6ciKg9K+O8j7f&f0k)_5$)^W5%MF4#-k?;YD9{1jc_ zXEy&c*ub?6hbWp15;+@~Hh&#qP4;Wy`JYdMqPH%cY?fKGRk&eRsR!2)-P7WEjSlNs zfc3Vx)uFi0RINcESm8WFnOW?7#7;MfFIaiXRmeyO0Vah=LSJRDlCRZCNJ8k0W z2ai^=FBy0p0pdYLwVvZ9l=Gyb$msaNQsvnb)q#uQQChl-;TIUuB~k~A^w9sPnkUFg zS?W%;)8KUf!4f*&mp-&g{&KqY=(?QVkAvk$zP{ioJnjti^oY2+K|J{Vl@ozaeV*B* zspI#Gw)no4YpQew+Q03fQb`7Z7w*F|JDGBd1J(HA$S6@86B7a#uN@TU0vRlvIXC?3 z=q9~!R3TIwKrH~dHXQbezDieHGXw?p*bhD%bNxZn-afAX$;fmg*9d;Cn)hy`$>=tL zJdmQ8I}p)%6AW@IF+JMsRU5#}{`uA)`{Wt<5}6I=*J8w8v+dW7T6X*+jsU~FngD#N z>;8Ol!i4K+0Gp0&P1OR*uhHu2e=rB`2Xr|=-5=Ng>CYL?Xp?^!2=H6{pbel_vapX?u4 z#1BLNd%^$1z{>w`GyVsv{{tuhaQz?k$!qbtWNb2Q5N8^H;@6)6SGRcVo-^;4KX&@R z;JF6T%p(*dQrOs2Vn+c6(V3IxR1KBP*|qP!nJtd$2^1qvYi0gPB7S5bCjj0LU_rQL zYmjUtc45jVi%?c>F2Ngm`OCo%Cy&awSK|Sd8la7h{{w<>4S_veIG76L#5k2AgFM3* zV9823RDg#EnEh;d9X4qYR88zJs9lu&_H_(w`=@Q>NBpcJ8`H&)jF0hFdY7>Pv-=;!iq<4|sP1~IG-d6V$%X{e9;BdSgXuj@$vis%w_ z8PJQ?OGyXrsAg!mko@Ey2uOf+*je$0diH8fXPa~7_pvdahJNOaTbPM`Tt~^)%qH@W zV7!(cJUQ9#t3$4T*{J6?Fh6&Ns7G4&B7U#o#Q1W@cZORXW23Rkl=$*VvcJ2-WiKKb zAj>SEtuS<9;aD0z{81vachDJZ*|ZrC_Bdo%K3CqpuLT7%*iwFLhhAz8IfRI;H+MIe{Q4ueZW_~comvDQQ-%KWKeLl zmK7P>k`AA(0(d82ao_tg(tB;;H%x9^^&5M(*mjZ} zv|Z1Cu&mj(sK1IU!|t96f(l1v4Z~SCUMD~oCNCL2_~G<^EAQO%1}&`!8gq-z0n8L! z8TI}|Rm#A%Z@t}xnu&f{1rh~(QrOhf48zb4+|+1pDOC8`+wkyuO8Bn*4>kAq$mHqW zK)qMIj(8h>elccRwnr~7w4^J2i&ce7ZFo;xI*4<@)iSVzeUS=wfO1OA4MY1H6=;yi zGKDusZq$hi1&(~e44l5IBB3IsBBP?Df6U!*9JXz^x6q;1xv3|g@&HV_4TOk8l|=(p zTcEptpe-+%S;c4LWPMn(^JDoYNns<6<^+TQicgyew^;wH6A5$swM+H8ldWb@@u%~o zUag5XT1x50{lQ9`rzLxo@=R}F9XH2uUt_K#f(+A?9qOyEHWKA0fxaZgRyoI)`>xYa zOV17+QYs@#NKrA765GSyX8reUD}t_d1Ds~t@YP6e5@=(QGhs&R5dit@NzET9=uwJF zNcuImC^^F#$)$zG@(3d`Oq1XC=3i7fh+a8UtRXA7N9oD*TD z`swzwDedJK^=cHWtSIzqD~j>qNcGLgnvmv9Uw1i`VP0pVYHoFG`_7`5a3?--29+3@ zcG6ud=RORR`IgMN@#&4?(Y~iPqv?xdi^qd zw72l#rL*Yb+L(+J!KyvKhtg}FT${0+CZd=pExhWC$mhplD;<+RQjM2+F5aiF-FZhy zQB>Lou%i^)%f|C&>Bx+fhdaI{mZVDoJofMF&ao$l4bE;fu6gh9^Y@NO7|psfAo?QFCDn)<^{_Fa(cvDbN^TRsXu4 zG3)-jO_<}qro8s_X!!q5>3^a0zqs_Tlk?NsiJQaK7!3=*zo|zX5v#8(m?f*jwX3%VXFVbz1iFW|{OhH_T|oHL zDbKcaAP`6o9vo&i2XJll0M7~W^4DMfeB++uqedsd0eU-VysgwK=c;ir zmOJ`20q@CiCP3M8AOqmBkILVN8_e)`zFImEJ>s0I0v~CNo{WTvA7+++p%ggzA1STu zf{Gd?&8QU&U0l*8B^1zG&~G4b!zVx9U+1hb74AV!VfKgrv=4kuAG_S;3+~U0vleBiTIa45F0%S* z<1HCr)A+rJ_lNQ^+CXd;c;^xG`03`LiAkw5ZSoU)w8Olr$*aHTVxM*NowoT9IHr<6 z>v|qOR<2j*QOLnoa-0*^0bYkYSfn^h`nY4ubg#cx6Iy8^`=PJtn7v5QaRyHEF5PW& zD2!L()lY4VOS@$lI`Y@^j zB^KDFy*#tN)SrQbFD@F@GPG7<9Xt-h!u+Ra^&LNb_*S;ikesOHXmb10!%H2=#Qcb6 z&7D8#rvr!si#~juQoPdaf-T8eor@JsEGHL)J?Zo-@yvl`^X>7zRib6wF^Uz*)y*(q z_*anJ>D?c0kEy6S;cG;Kei;@TB~BA@{8w+S{$K39XH-+)wl4b;@0-@yHo^$TG=iGb#WBfn7AKx+f zkipL0S!?aN)_T^Q&wM5(Lvq#(kGA(`@~w1gxh)aTRL<)r&e0c3*TfK*X`kO0eJrS= zTZjL8?R@`Zbsp~bYFFr@%%^;He$~#uK1@Qdm=#g@J*2DELIW9{;NsO`HGUS4HG|i{ zC65tK0ta;5{j@60v3eU@}A?C}3g?+1P?a`s6j`!F*v=B`u0LB;BfB^3@h&rl(7~v|g*Is~`p68A z5%cFVlQL>>@M>)Ae!yw?$V9pl?XbY}w2pvYq|RofvFUf`)&@9VbQO-rVkP2j2B+*{ zH9wHOWjc-=W>-KREqq*%c*X|0c;LGO*M}8~&yi1xbGHwWD*@*)M3DV(s@t65fzQFB zv-P0P7yQ`>y3!-1N^RJuDsb{Q6}vcSHyeKyce$d4cgI{5>X|mJ;19WUYdu9sJ^KZB zr=0IB`UG`2&f(Xy@rW=o+Q8zKw>t>{Kei{kVdC_VlA+Z_-KMk&vx&jzT>Rt%R#^^7 za)OuSMP3UhCmAc3tbWNQm6)>>Gs)VoQ_c&GMu+#TFIsYgnw;i9P0-%xv=eMG-rAKA z#d$O8+xpEv6J#fX;Ugq)H(ESafhTgaB~RskaJqhrbuSqCu1PdJmp6UmbL|S3TWNN; z<)j$XNjvtbx0wyiwZ$xXdzfwG1v5F*Qn?fJ40WR0yKv@lu->3tq5WcwM=_^a=fr#y zdb`M=*(8geEK@wnJ*b*DKnMeFl(-c);&dL2`)ifF%^Th5jt;tGn;>L2`+ajX1Fdnr z19x;hH2^vqJ84=Ousz2zyvEK|;8)5k1Do9as{MYrZ1~UBQn|b?Bt5}%s$Bm1axC?O zCw1%7qyi9B{nc#QH|kkvO?;4ujvmr&2C|AI0`dOS*ZoZH&V#}uBu6JQ@uptgmyJrb zWgR<QLB5XIl8vrel=QV>{&3VXN29g!M__hq!>hv`Tr=3ul!{61_rJ`~@h#M*v9KM(>c<4)o)#lmd`fxUQ z&}2)?UuHe`&?};6O3a6Wu~|?2r6f?;)=|Tzd-lY7He9UDRZVc!OfJ z7_+-VCUwqMgDO>KMOK-#g)<~UR@l7#ZL*mS=BkDj-oPZgwtEA?n`b+HnmPAIJQQ{& z2q|bDq~smCY_@drRR&j$p5}B(2XqvuX0^?~kNhm2WnOW&8X+8X^%t$E(|a-+(M2RV z`0Z+rN|xYKtM{G@U*PF@0tMY~Y-hk3AnDk!K-Rh0C1SmbnyW*ycgq~nE1aLq^=nvG zn4GJ2zGx#{p#VxX^bix+L+)?343;VjB`uAbv>BDppqx%4#v5Ih2!*yM%8~qa0UKr0 zGi_?{oOW;0L6n{Asoh!BtVcP$eurNSl4_kt zSj%gUr3W;vL)|<14h*XJ4V02!9D7yr=M>!%sLU?;on>m0XX~apA)$7&RPa?sBMQ2t zL*unZ0QEfp0>*_NdO*?l2n{L!H*s{L0kbw&{OrC!UfY0HQENQFLLKLJDBkWkl3L&KbI^{9Sy=|jHDh~re6k{w#`J{=e(OFi(<4?+A!KsMQoN% z+V~n60c*NC^-6jH5>a|jnIC`-Mg`Z{!Vv-Z>W=l%t-NTS2juSb77Lu~4j~}EuCd8WMj#+zSGgiGq zCh&zwRiJd5xZhOV&SFEx@y^1EZlx*8D|5!G7aX3cm{qpin4@XLmiNMIEc;}SW2*Mvj=fN4L%fj6mWi(|6Z1yT?Rm*P zZPMHe%SKj_?3TE7H8dPXV2Qhq>258rn=g>IzM$Cxw%9PFmbl-^?-PX%92ry{0&sBy zO*SM?`x%4T120PHMBMLxrl=)t$d#66L@c0j4^24+`Hx5aZ=ydXL^gbt^0>3y1j(GZ z9l+Ij;WtLTvuAyAv@>a%+~l(KAnDwB!KWZCB47070uaM`;sPlqqR9a22ZdW6ES{a9 zZL_hWCeUG_W#zQRiq~&BsS-4n${S|@;|>vpW;UQxe{2lH_z(-R=3>f-8!^{QCG_O@ zv#@3euyQYw=}D$Q9n-eqQ{A!V;`bNxjyhgYV zUGMDc6u|7yDrRQaqaJWslZ3`X0LTa(>6yiJoXvYSJ<&v{MvOezcQ9e~l7mb}To7 z285|&VRZ=jsi@1>YQ<^Sv%A;m-wmg30r)Pi5q@qer6vL**GDb2AtfqK75E9L742I) zajj*=Q&A@6+6a5H0&z?>^+ck-SCzvIZke1x;$D^{BgXjduc*{<9_NLIrdJ<6_GBsD zE#aLyT2xb(y_~0YJ$sCcp%rSr_E^v3*PGgu$uCa*+^w0awx)<5Qc^8YaTYN{+6J8r zZwUh(YZi3d&Abg*XVpcFWPUdWm`n&F5&oClPP4Zd-m7t70U?|+3c2se@|Quf>WKc# zD-;@^xS5Jv8Qu&1xvSLwrcATJu+=#de$)9Lng081sq4QS+TMS@X|Y$Xm<=@tg2sw` zZmy$?kdy2!)2IbA$1dG+)5+Tp*rFihBFRL5vJybCcYi{K;LeNnth-3ZUx$bwm7P%P zTZ3VP9rHM|0G&Cr$;ZXR7SmKU8w%@$yc3oqVreG8kSaQ~<-da$VOS~Ud^2~eE^bE2 z1i>FpJ!h+%0MJE+T}{Hy3<;-U<6)%86Nh}eH^)P(qLfqzgJ+q;8o0m?2LuzT0 z(XOV=AlSv_#q-kTwjD<}J`zXV1W`g+wI0)rSd$|MIp!qobBm!QaD;>T<({x#6 zXiUo?;|x}5SFWx;otngZb15LMqx9NTFG;g$4WpD1)nPH|rz^kX{Z4l2u)yjab7Ji= z;h!Cw)jB)ynK{2PWj=82q-i-2LH6sd#moDipd*q#mDD@OPmZfY#5$`@gzTs#0V-(- zLio+s9ODfYAbGE=8Pdt_1CV3qUU(?t@hdA=78Yc@Q)lkWoPUw?rf`p=0qx%PRxc~x9Yb7D?oET>5A9K7$dA2u!VRq zzP4%0T6d@)B;*p(bf{yBKdZ*yuX$uv@Dk>$@@>)K;)&{`hS zWAR1Bofy$7IHVP9s;Madfbz|fJM%}WGqD{l+vX; z0DD6$)1n>cPn!`VKU$N!MSdsYy@`3cvK5f3U~QGKvpzWN*uD5tM^_6+jz4j_pQ1^& z3oLCxr;}zK`)pb;rnRGkCFJ>YT0y5@jS+D=H&D?&7^8evp+M>* zui!NT0*W|Z@;*WVmg}EzxzP)bOwyP zN`F>$%MYSdBbD!P?x4VxYiZesH1#|4`g1b&*IM&UBt2!-D&9&z{|h*&FbQRB?M6G$ z6||!_KiW(jp(Xpp`l5K15MaI5X<*^q88>x!%${)ZQr&GAjMh8l1`#+e=OqO-0jC-^ zTC#ZrOdJUkaM=xYiVvpu{F1~Zou%u=Yst9E|B0FZ6Lryb4e1X2yWmFVW?i!6(!+|| z>`vNzZ^-W;fNYN4DYg(WedMe5E&fvQB= zSCnt3;;V7aUakZ?#)=zNIPMuRg>B_ffL>Iu!e^%9jF7to2P%1xs;Q``@1IU?Abbk# zbPOn(992d`2L?<}sGzuF_=Q;_t6Zr;gUWS_C}Cpe(c}Fkp{Q9+2WzjeMDZex&qXkA zolr}~^+%)pGcTK!TL24W&B_b%HR18tRO__yciOd~aWa&XV@)w?bfP00-SJ{tdg&sM z+Wi8}+(Kd7mjWcer*E0J>X7N$wG_>HZ2GmRsY?93yv4xcy9wE&sz27*^g+#UpaRo& z=1=xLxcsa#hDD~I0DIr;q-cdAS+#f1U{X2s%hP?KqaCrYdruoUdt>R)p+{?9+mn41 z73XaMm({JR^{C_RIWf@B(_i^&PKQ69OYr!rjA3zQ?$ags{8kxCck4&}1h+=SX`qTC zK#fU4H37PeUV6+U_ou)sBeiO1pqvg`eJtjM^YqLlt*6$EK{fr}tOJ0wQE1L$cxb90 zdAKD_%_cy)l*A@*!E;{kZw%@A5r)6bU|MvXBZ{ZN7<+wXPLgPP(k*vNP*6K#Ogwnt zvw}QC1>MHo69_>RC`gq_2BwQIFvCw9;TKDj{Upv@siI@$C*OY#Xf3HD?`iB#vJ^JV zJVAavxXcli*^yfrJcl*8`rUNS{az2-N!!95OeL3@V#Hh#0a}$|#jxI&;qsBNkJFA* zQ5iRi&dn&NcV`^8=Pa~UEzt%^QiVB}2j{KhJOK5h9<|`(3-4ksyNOuVv>rT5ebe%r z;l_qjLLBw3@rS7U*mDzfskN52oK+(`%HOV^npJnAkLs8dS$7IBL5HJNeqw7PUB+i` z5D@YmdE`lj?qJ6IY}fZ^Me>sB7Rl^Cu}N9HvN zv}ho1s$^ar_NBq@avJ;n>|+S}z10iIfbjAIs%UdR*45Ye@`1b^DI?Dhl0u^12cVlK z5}18Vqs4}zq#CduZlx@jo8f~`q<>wFq&Gz|*((_S*6$Bx1EfAmJ4$Ucc?);WN~~`P zkn6U~(CpD3S$ZgW|KZxFE;_*+#}vqR4=I^&kG&Ng8Uy}#LK*fI5nyD6r)=>^2K?(} zQ+aMBVU3MiIfh!7CCVaYJjo8Wcl^u45!IDYIM`EZ^iXgy?vcp7k=vTuA8mLe?=s5C zA`SDjX{vu7(I?n61ez6_I`9voFY6|*-E8g#rf^x^{pa+ZfD=}nL0^l=C`(T^-;VH& zrsklbfM}6^q~`MJ=@P@${)QMw`9z-V$99b$J4t3iL)bV0#Pr>nuc^xXyflA-9|4wW zvl4iwLxlv=0(OJK7x;&C<4yb;%PF-xzsZj`-XwV-YpuT#Fq#R0X*{i92mDvN=wki@ z-nj<&Qv;n&Aj9qrqkK%PQcOkg-mn}DZg$npk{`WGLu0wdgA((M-sMX(0_l^8*=QB1 zt`oj9j#1wEg5s*feGLx9dIkL1h++hRLoy`Rdj5z;W9A{}VU9M`+$7g)U7}2%mA9mu z#f>b=4rQ)V@j19qV7vi7Tr+kt@iSBO7$k#c?7oZvqh&5r_4!MxBO&H1vZck-a>RS= zX}0DJuf~0F^xBdgw0vLlg5&N?2dAgfW<*f{^AQxe36Wzv54^cR?GaSIXvZ6s(!Fvy zunZ9jx<69NOKB5x5BNp{sG*&UAy2|j_*aRtX8Ij=fFtWz`oV-J%~`XTaa4|SoBw5* z0&fj8+Ppi=A201SswX8TZx`*KU*d@{CDeIbY@dnlFQxYD9?|Uad;#WP=+Q@n?WH_nT~# z5f<1%HHUWbpbH8tt+-8QO68q~Yy3pNTKZ?o;~>b-ZyQb^#0MK_CcIP(-L zMa^1rRH~0BELYHhBN#0S!9z$<9}@w=>Y4_fQL#%Xi@wx))2rhO&DwA;_i5KMS;x;G zOD7MGfN2@w>}n68C=5ngDJUGbsb|rj5Feufm%#eGImi*8CWnC|tm8uK2(x|Rky!T0W8Q|C=^$NfQSTJA3$xkfC|$iOViTL-x3;35W)%s_LKO-Us4aX7wy7ihL!Iz+^Wbe#Gqxgz0@voa7zfTj@ zZ0Lu13y-T@Ur{`y&x;+TkQ}bBTJra8xjMpBgL&D#oh@Y}00)QOkz$`});b}oOsCq* zcBy>MBmX3HMv`>l0linU=xd5kM)4waAZ>KJ-WX8=Ivl{8ch~qdwW|B_0%e2`RWuH2 zj^7tt!@M0cA6v~GcLP>9htHzJg_(}%MOO!S>PJ2NH{Dc<~N_)pK2+G!)P$=fRj?<#hs5#+aDGL zu5t!EYpgqz=YIPfIIj@3s`K{R*L*pp=M`s=tm5t@soag*-z1=R52mWLxInbcDG>Tt zVwa`XX+&uuU72>}rZtbTr7pIeX(Al#06Zq+R-NUNqZ1IrqNnFP*J!s&dl+XM<}aB( z+x&Lzhh1K6GDb%m@;Wq3CGQFlj79yp;J!4w`ZO=CIeXA%hB2;YB{6R{R@f6ntyh^W zSf_>?4Bk(was<}ShUnC%)0X3WFN_71E!AJGTQ~fuE$UpgUw~KruJi(2ZOJc8=sC3# zjexLR$lvTb4@b`b?tYb6N!Xt$F6)>8%n`$G{kpgOq4IncI>9C8nZg9w@sKL1lI=EO zcYZ^E<*;VL@2{$WM7bWN#8^JW^b;M>r=w*qaaP0k21Nuufbn%VkWr3*PnE$K+c9P3 zby*^z8W3%hJpQtz(6Dc~L;kQbIFtVm$i10H26XrYu9D+hwN z@jefT7Q$}FVtZ~IH?@4+T-Be4>E}d z!gYvqz-4>NqgY%ug@A->n0Uy4OlQt^KQy!S(a*=&`Ou-xEe zT4HDykZ$^&#_f+M9O!Y94KJ&`8Hi5YZ@5nKdtPgf8vM%5n%OM)RbZ^X#fXPECdpLX zJ5%~HM9_Ib_L7iHx2$R)8nWCWU(LVA>uCJA?l@*wf-I`ciOaaYf25t8q&I8o7yh?^ zP{aP>;d&o>?|k|yL(nxgxl$pnEp2NJ>%me&krce{{({!-!@lgsDgdDxEw@xNc-H05 ze+&(3NWN4`FL`n6oD3TUM$eWisdxT9oBy&CLu}IkftA)o4zA#Ch}UZTMF0lL#egU| z`>1RP*bFNQl<;v`1eIPx-I0;cHJL51IPI7nS~`Z`!Z%xBT84zo0rZ7Ju!?u8H>2Mx z1+e}C)*U@LIh8vRvR#kY-q$%yJIFz8WRuyu6(4?J5PPCBM%4Z!=oxUgDre?@SOZ zNMv3wCd{=QSqp@3=et4&H2iGHUb9c^yKLyxk*p5`v?&@9cYaCGSH{QVV5A>h(Wr1V z#O5jtp(FdI*IQAy+JLf>rZBObQ9gFy3#nR`D5vj1Hg>COl(NVv0MI?HlnU(?bXmN? zP~tD-BO&~ zzYLeWnl95W^+s-W%xLQ1U+!&uxW3F*P9<4o1wB7$f?zg{7QE>W7Qjfua&zeMrV;v& zUy!#wEZb(}P*h#x8dt|}IsRZ4ARv2?xvOMnq6aLKrNA;-6E@Y+#~C|+P9+gddnd80 zsDig9%p3S^mNCF5*_$Pg3gHUbf;8U`RTdGij zR`AcBC z#`68`3>*%IwH|}yOvgJ4tZT`OPAb23{>aATd|Vx^!_EZ|8#L37WBq)zd&fu1^1&A7 zz4v06vqby_N5RN~A!lNPclQ-wK-vaEqanEAy+Yeb7C3(#h`RPQ3)WRJHz}_I;$|UT zU^o?$#d)g0KHY#X7g9x21c1OOn?ujrpk~FPvfI)t>-9U5R;7>^Q=iDSq*y61KLC7C0vQsQ;hwZIYs%n}r+R)_`uwX^qg8{Aq^^|)qIP3< z7)UX}$3iQ$RP4aTU%Jaa`A!c&9C4iGqNZL^S7dttk@{W5lW{P5u3YUXTAM}}LPC`0 za09XNMY(K5Q&eDA6A@Tx^2jJwhrzh{Ee~6tXtAh>xtNqjSw<+l8wJGYYq6S0#y&7n zKfU%VS)re4HK2u&f#%ws{B9Nj z&|HOXz+KC>De_aFehRDyp%DzQ+I>&;0`TP%D9A`@CyK~fiy4cevT`JZ?|vp10oI1g z+=!`J4#Bcee%Pm4@GwayIMG)fSbXJE6SRiFkA&ZHt1QUuNO$9yycf3u#<1$NuaE`U zgtV&r8EfZInt)iD&xht+;P5`#u5Yp(lK3FC%SlFpN%k$s%1E|o@P3oaoAAppeN4d5 zZJzkF%HIzgS+BN);8<%aM3y9jIQ*RAp|2Xo82S+~>P35`S*MeDNTa{b#E*6CB%;Ydi=P|4gA(-`8b63>AIo}X}e^Vn&b-h!q1J=mcs5d7)GvscF6bJ=Cg8%zQ?Ula7~m1>TCnizgNUFV<=ARw^fUKNXPlFlEiU2_4_UYIR? zj~4a5mkv8Q>$Yes_Pxy*uHwEd6}@f9r)Xcw|MGdLl2_!@RtqtPC>K3%+NASkDDEtQ z6rd5#4ed@lR=ioW&@j;b-jpZZ(0h1>p}wH0-Y`C>V7xFMlbqk^v*`t|+^Z*k^;tzO zYbJ_hVM|dqbE`6Oz*7<3>U*du=66&AO>HIoy^@VfiOJ?3SdmBFuhamkZUY!1iHy;k z%)LQYyQ!o~bMxaSr=fgyjcmD~DZ_UAZnbi%u*hIoK2Ex~1t;YY`o8Zzi~e_V29Y0I zi&RGx(tLkBB5VMF2ikNg0)ttoI3&dtL=EVRqp7i2Alt^$8>vlN; zI6xyxgTI@0oPRIq4nV|kALeYf%oA7-CdFx1VQY@epDKp9kSRnQ*Ex)5#{ zhc<%F$M)EeM4u_nAOf3Xl6GeA(Z$b85@&E4ArSI7lFCVt#0tNgEamqpT|JtKX0y5n zocWQQeqmhtpLlhPYiU(2KG&OO!P8La+>MM;kvZ}R8~pm zngL%BZXhn+J_|sL!z}4Cbk?d0BkpA<%b6mW{SVY;F)#?`0ml)-3xE=_X?(7x{0cdM zuA{G+KB7Ny-{CV_nVZFAw4-{F0FYBN1=3df@>xg<4ajJ#ftC7pwH~^Y{z)FPAy&Nu z7gHgRkbv=W28gqdcnBQr&A8stG2Xo&q*d8U>k{QlHu>TKyGHK`&)1uu2n${GYY<*uRC)g9(Td0&`0Jx{YAk_sby73Y>zPPuy zs!?h|3JTN@i`-%SkSKA?KFK)tNw@ltX6a>Kr%EdBj|1Y5Ll8DZqi}a^x2@dCuC$(; z?>%hD@4(^F+Q`%}Mf&?%%RbehIDO0oJe0T6z5JT2NiFnkdPwCwiVB!Kqo=W}0iSaW}GBhDHs?HX1=AE|2)obNP+;__h1~8a*w*90r zi+xO;Res1CV&{)^e}d6O(%0@P&e6{xfPh|X??(#_+FGAzSM5A28dv5)f5(Y>h;dNG z>+yu;D-ymB+W;Y8L1t^h-Ox+ZSZJ#5T)eo)fBwlWek@KL|+C@zd$g$ zuB-23VrKoMKrm5wcmMrFPNH%#5D)a* zoqYRM#Xh4uBJRs%9=YbggmtK3e-=`}hz9fMvA=qT@m}%+a#39RG=ovHj@)tP%*)0+ z_^WmBKK0@dn1YDj0a>-R>G8wR7xdNlJnI71%C#R<`72W7=K3yG0}!XaT9eOS?yY5zh# z)gln7j!K_>jlCoyf6FKp`*a-8AtNMzv>zIa+2V>G>=Hv$MdS(Ugxlrtau^vdXbcth zq;Ks~+~?BhH6!({TY1*pX!vDEj&~?rt zN#gve%c9zG@ce@R$$rBt*{D8et(M6a{u6+N1k=MU&vw2BaDM;?Z=;KPVouy)mL!^{ z40eVf8NVS+b7<%wXDwv>O7=4T3rA0!%7tKPO{BG(B|y}Ci)XR+ZypYx4^ID{3d?@R zFG#r%WZ2*rBPlkechRYO$q$un=uQ-GHjF{<@3(l2LlTLVp~x*$-{&rihI5m=yol~C z6;uv9MHr%tE{#k8w85glRbMDF>@i?r!9qH}5hmr#pGrwZ$gKce_8;wn0OvLz^nd{N z7O-F|yYL~JoEL14cLk0Ttw6q`B~MB{qoUZ5feoGImVI&A5rmb%ap@FW4Z;*}FJMD4LmO&6}aBhNlBDzvbE zrYWBDN8fb1PZC9?ecvB_`y?!ij>`YKSY94KJ4?t-sT!;s(*O?bLw9nL*?o=t7GwXp z1OhFEn1iCx3+MY-BgeGtY%zQu+T{yjSb`GW!Ej zWa(s)Bb#l3FDeIfoC3j6Z=Sz-i#wtbI8cWZVmyEUp7wh3?dHzxaOWKgdG6uy10oQG zj*X#wRGz77GlT1L`*bTcI&wZ^i{^#_)0>ct$<@Ahmn4od?@1YW6x+vQWBgy>$Wo`c z=UtY(mEEFJrq-+@ebNb}N1kWZob>+UpmyF9>4opu?1Y|Y14%S&&S$Q2#j7OM4{UsIY*I*KX z->gI+yvw{9%4hoMu0WWDXVZE)fgN%}}vCed|`{Sl7>z1Zl*0>qtWpLLqA)$&}GQfY2; zZoh~FS14#*{0~wArdD9s6*HS(cEiPze;x*E7HmsKx*04IBXMKz8=vCpJ1N}o>V*UW zmpqTYYyT(n9~(=uV6fQkDn3{$)Y{~`AN$kJ0$EI^-!zb+TxRoWf75mm8`Jog7L79j zybqw27bDh3zxiukgvop6s-?Kh>ncwYU=6?|t741cZgH}Ww>kE#0zw+0U^wH@#}2?* zScpLDyV|;%K~rqAHR&|Ax5c=d>G!^4t|{NEx2{|1I`3p}DGed<6XNk%{&w5iQ2oAa zQjuzwL}h0T3cEV{7t#IomOI!-7=ss^{Tl2n*WpyuTn1&=Qs_h>JK{Iy6b=t=J#WrD z{)$`|I?tI3VDqk+-XrXssF^7l0eMgPoI7`)> zDt8+4P1|RyWt3c#x)$odoh=3>z)7YWmRLs-(U8B*E&0v7Xc-Sl&tFd!NDKuV*8yIeqDG+B8$%i9 zoNTv-08}--#FS{I@2J}r4H0JbxrzckMU>yth7)Z4c|OVqXWPs7QneJ${^j@y_6Twv zg$$4~8gspOL}p-MAPTj2+;5Hq1>ayy$TK~It~4X_Mt(p#zcgAbQ@g3j7`eF&ol4fe zvUp>l5x9{5g5zMtSGV6)?9gQ<3&noWMjVyLvO9eXOLa7Nnib(6AqG9!%Ep^yFWo*j zNy7$W(j*vuT&Wwv(Qm8$j!tU`b6XXy%`{{%7XlAn{4P&JZdkoaIJ^U?(?)&>@BV1N zli+mm_FDv~GclJ1c=F%>%D`-rn9N#Y10VHQgxBByGWoloyUSAY>36G^Pu>c!pOnv~H15m(*PqS|VCw&PE?boy4Bi`3dbxu^{M5u* zt1QLhww^oZbU%|f%$u}Dlq&?SZ*s1m2C4q@7T~8#+*u30?Jr2G2cC~I6gV6k*1F=a z(ck|^W6K`r{jr)&5eH_l--R|%MH27vm^;d_$jaJw2xy6~`hSf?NW|uuV@1%#dUh{`gwfGi zx4hc3=K?CR*%5k_beR!q0j$Ftsl8|G%xW>~mn~JFmqq^B^?&)W0h}$(ET7%X-3A58-q{`t>%@{V{soR5$Q`hAoJ_C1w3SoCLUI#^7}T)_Uc88vCqxWRonV&vmx z%CTNmQvoRYIkcWoYi#i&{?jAb%z)8MAL1RuyFB{1l|3+7ob5n%L`1Ud7Ka{mc0b};UcdjUy+=G@$NcqS%TLNi!$gK8}XtRg+ zO9eu*iDpZmsN-K>!ar{x%(sK-5zNtU3sNp64_?+GB=z_@^dDj@X!Mg?jODVl{@b?x zIlwxmvY7V226-o^)w!5@+wt175&wMNzkFcB=Rs8e%P{|W^PdkozT@Ek)Rm|_wst$% zfBH#T4Jyi z1Ag#--NBEr2d*&xt5Cz=+K~=ey*-TbUy_sme(Q+GpDX{XOYeb316TgnV_yBOJ0Ab* zF}Z&lxhe9$`uG1eD*vzfe;ca*U!$)H^F7(Ibq8e4=NfFYD~#X<$<_Mov`?D`f~9NR zH+H=)JKIr{`F&~|Q)!rc4cHuGCN*lP;`;(Gv^c%9fkB4)L*dwkD%A2H`q`g?Va zvMB}gbEnw-^;gA+7B4;WzDFqndrz$g zCX#CXMhNGcB;~4ThFAyv%$`#)h{t~~;H!0(Po!_7Dt~GBkvFoy&$ZL}v12H%osFQo zy>s!i!o;`fpTp?dURSoNY^<|+c?Gq4qS+^HN0Ty*d~TbN2Toevk)puA%}Mzj1j z!hh=-@-p4G+$cLPu*oX&TMP-0NdiRh+N`ZsTKvuA;<74+w#QmBj9Zd*wgm*8zWdrQ zHP&fY>6%^XmZk?-RJ0iko!sMotWQoK#fb?Oe3KqWBdH^Le)P$Y%m}n#rYBKmY~+A+ zWO5eoIL0m1@RfbXUf=o+i1qu8ym=?>R-JJn3}uo9>P%K_{hp0{?~deJ3HtR~P{w8Y zswpNsGnJ` zJCevHTMzI(J4yts4T69EXN~#yDafZZ}m7F1)?TzgBcJenFC9ZQ% z^r~eZBpVprzazCXS(tKz^dTFuLa~zP9JeJADX3^cGHAS3&*A}9N-^N?@GO!KfAM>n zXu8mFBo1^QfHms7T z|2n1Wz}K9+elPB_8fAJ2I1E24)y>a!u^gJoDo}$zKIA>2!T0g}IypvK{&31+6b<;D zc&9X7%yq-zxZrbBHfT1L!j}falr51`eHM%0DzffRb<;X(wh#dfEney7{!mQj!UWfw zh!+f#-HY$n$US~tQaEng0;1fXt`o&2&h3$E;OJ4%O6WWLIq2UShA`#1+7;fy_W7THa%A~qHtXbG#1(@H49^nWx>eFnOz*5>lCV9ZccPd zzVth~Jtf6|T4CC)TWht$7W2gihX2~7Z@*OKao{yKW{2g){@OZdYG>+tYtbc-%Oj_0PO_o*xnqh??zwP~vs%(xf{L zzC=?C%fMPAU~>HXK&_fWFEK91I|}BTBGD^=R+(qUr^0LThX5?y(8N(WOYSi?l^#ZJ zJoclFKeR@Hy5A8!yqs^0v6Qq~)E@DCyJpc!{_N|UPu$3hr{>_YFx#ygZk5;~m&WhVA*xN|MIbWMgMg{u4QFj!Wnw zPVjR-^b-^bPtfnuI$n#Z8y%yPyf}>bIMF{g^8c~94z~|X+8EfFzupdrdE==%;xscT zrwHVSmK4dED}Xfk5txvb)pJ0g63eFZS@hV*j?6E$VRU>Z@amdF&XZRQI*RV8U8nTt z_%3;YLhq#_>j|*@yo*e)h3P|oWSxtsOoZi16FPbVz0iP-r#w`c@hS0$y+79YdNJ7{ zeF5>&L&CZDQA}R%<9H8NYD@(~*q09bXRj1{8)|Hv3+UO;_imkszQ#0vRuCn)Hu-I==kc}ltwN&F z>l0;`+_&=j%#+2ksS66Q!y}5p+aBkR6rl=V5YvtVyj5LUf#l?}14A2TJftQWZ%;?t9ND2iqdmE8?huQ6o(dnL`P7+Ih~oj1vVYca z>G?WW+;Q|NF^HE}$i$QG5H0?)NHv>NDY@zsKu0wOT>-iP@$vc0iU`wS-p6*$?>UWF zX;S!1iq^dafkUJJ<8X3@B$_9f0)NC+Z>zlh(rU;AEW_rcFq*yAPNDe*Xh^zVqLGrd z*qlIA?axur0Pa?<8p`4}QAmRq9TQ zO4Z4MAvH3)E%er~(NnFW5lu?0g<&hbkk5#RF$GZKu0eLl5al)6b*Bc7K#q(a>SW74IGMGFhJjWyHv(bWEY=huj+u0C}}_{{B0U3 z2&{>tc*s^4BN!;WsSmrl+4rb)z74x=oAlu;xY%`0+5tX*Bz+JgH1^nNbZNx0%s&nJ)S)g93CzpYvP-GWFB9 zdVc>BCza!%#?)hu;%6+5VE`O=&My{{AQBM85>h$|T}M&N3~o4$ zee_gsgcDGL#Q+#KTW-f1a*w4=zr&!ZCvtvoiRw<2qda$(<>6+{zAg3qCv=mR9jQ%v zE5VSb16c?)L!7n19Jk#Qc;d>Fx(7c&`{Ec<)qczEtwmkFa&F8cIR0)HS^f%`Yu3jD z@3yF0Iak6Z$$c4XGConFKpSouV$Ur;k<0*oWVG$|0XNDmWL~n_#PFIi)|#;u?2hr? z!;H<5Ondf0q!jlql$}U_e&vto<#h5F{3$0*Z3W8@2!@c&)257mE$M-TAI86@gmelJ@m=8rudK&7!?3FQ5UaIq;lch}y0e<=V#?;RJy;dnvs4?Sq z(D2@HyUT?i;r2Vq^IONjqFW(#Prnhm5`qbODj}kFa?>C4DAb_!?6_f5XzOMtfZ;4A zXj0~AztB-edpIXIel^3a==VlwP+~ImjyyJBGS-`C`qy2quRL`6;b6iPankpWVi@H{|BsMeUllR&EL%%Yb?vz z_T%+Fu}Tmb-}lZ@!9cD&mwMa27p=oMG9$$%dZ+*=IFH=?Sr^!Tu_7z|&1psR_yis%5iLE>FEw2|yrOPE9Ak=Sqse8ck z?|tC!-YiucdSyhZ=>^5)WC?my)$^Wo*#tCvYNm{AJQ@eiHUJ7&p>vgkQP7CWAsC;2 z;(K8R-GMg9{-|!6rVy$MU3Vj%@nMux)t;of{`j^bVf4#P5{~upbz3fH*m`Q}=GnC4 z+!=Yu%S8UsyH!sf)zyw&@x08H-a2TFi(v8g=>&9TcD`nSPz3SYT!g6sYzy8p_Oz3Y zQ{SXO~db-2-CLPXPXVI$47*xHjMh>7z2Qjde=3 zj-yrPhX|Dn|J_DTlg_f2d=hH3h+)A|4gV#HM?~iv>6;?Ei|gsK*)hQnD2v}eg!)OM zFu$Pk)d%;o-wv)7GAmN2VhJA6KB^9sTX`>09pgqn7XD-T-~EP4ka45efu zd}`;q)VT-S3Eb)|I{QHLkk_&E`0T?+8eMINkGgb!V9(HSaA}(l-dv!=i8ZWPgyY`LG2jwS`-7ilaYfQ8^g)$+wrcUmZ(xx0E~7 zS#E+QoJCXS?M&5zvPyPfaF;_=#-^yIY_)!i>Il#9$NH5`chrbSs)xts3&Ge!aiY(= z)}sthC4dM?)lfJOb&I`!E~XjKV{H30%COaJI3jni(J4tf>ol4jS)d}uwf@Lw%yaQX zqmoMt)6V?~M`!aa`rE3xPN2dMWDnf>z-DbPCX#!; z+L7!DxwzSz{=o6Y5m!C&?>^HB*=tp)DvdVWIv6EdU$F6PN>s`4(a&ZOgXI_yPHCeS zO%l|yJo?$*dEx~2_{Y)le=R=RUQ-1WXw&9?j4$h*KYBP8ZV_vMSx;sB20~G<_@Cp% zGK~OxIU;#j5h^_lsc|B`9jpuJ9O+abHw~UGtXanE4Q0uaV7fMI{Kk}lh-HiVgvb}xpd-H;~Q=~n5s zJ?$s{4IGZ9IKrMBv^#Sj-r;ndaT1Kn?|?{f+cjHJX=-(pXv~Uv%hC3==7KbWL&K;I z>*h=_kA{{hy?eQwOmGxOzO(;- z*m}=sINPZGJ0c;u^&~>nAU&d&U=Sfl5J3{rdmAmv=rs}~dWl}5ccP7664A>GH^IeSW2Zwb9m4 zq6;Q+JmIHyc{TNWeeIr;fFF+vjkf#FDS44V;|+cLnTZ0nxO&((`}(i7k?q8@RhzbY zib~apU9p*u4F*H25+kG>j;0baT2KHMU5?zm7@EkAt-$J)Ef|bOQx}YVg9qfHun+I(qi6Kpq)w> z!7yw;fgGx^6d9=JLmjQTjXO^D34H`+ra}d>;6ojHZ6^*IZPqw$%d=15gEMHL1%i$) zQV&~uD)>kS^}t47iR8>-2XTMjFgT>@ZLyt_C{0DwAPJ~eE%Bv;bQfDgcOHaEDR+wm zbeLyfjN*>|;6R^QwuBbTszf=XLQ3jzsY(A^sj)nzYmc%cc1V9?mZafg{ZDv1>dpusF9yDcy!3yNeXyQO{wqO9}YM_Pq; znJro7CA^P7ydd3CfJK+gO!yA(Ba(4O5c-g1+r5^QHJD^s1%B^_c`5@If8${q@p^R` zH`s&A0KU3z(e1upT~-ex#Gr~@sX^u=5jevWoi9K z;=4X0@$?UiMLZ7P8C;iX^2EH1f#-n&aldz-_$@`T_WJ8dCQR^R*w~zxqzvoNp8F3?iRz`xP2V%iC&5O@88g1TNO0obHzs zDI=E2=ZK9XmbnlLHRJTDt`7-yFr>r7&eoE(wd@r1xuBQPv22rU`Q1kP1(xVVCRZlFtWO&OsUn&)S@vGPqNneF@vqs+r`^Q}CH7A^RYJrLczCQTnT7;Sl zXZJXePrUCJ1q$ocZBJbCVv8#G^R3NvDj?;gvwfE4OK%~$8b;B!Iv*=M&F}=*TP9zN zKCRf(L%>>CVMKV8)N8U2-O-k%?d|_)lj@%XvF88&=BS7%4dfIw?#V+_dA(`Q8pW?G zDlGATzB9rv4fbo_7MT2|cu zYxx(upk00>JZqUd`8#Dd^t)k$R|~K?OUDLW^yLc$?Nfg9bgRNgY@~ve%|_{Yt&<42&EjiTr2C(c_Dyhe(cyciM{uVk&t%Ft|HzS=Q zZC=%}bu-!5KX;*fWU^4K4oYK_A>?F~_zzLY;3rRx22Ul22tt0W{u43k__S}HC(vHO zqe+e;QFash zMxio&mgt9*Hn;AmGLPQ-pdoF(#{6&>Qt*)nK_XKB?lDUey7-7Pm^K`U!tr=;qU7}JU1ydWYH2_Hao{xcfMGz}vEn0(p9bU;=!NM{(lj6Ca);WnYjbkyM_iqLoaSTxH+4KF}^H$YacC z@EjTm$1rFd_ACU*TqpM#nAyB-ld(NlJ$%!y0|M_!-mWwKnk1vUxyI$odq}xfi#Vu#7Xi^^`uG+TADsge>YNcPb zVbr_rAyj!zm~gd&GBMHs#*#bDZzly%LqtZ~%~bg2SSa#%z&EMh(#w@O!lH;2@<=aF z=hpkQItP9Tj0pDL>>tUqVn+FuGgfKm+IM#P%A{nSb_cGABN(1L7&>00iG1>_O~-rI zE(E`N2-Y;=eC6u8>Q|#3I7e^aO0P^FTGuYUwr}n7%;pq)5j>2LDu;!7|JMzX6R+Ie zzmr3M@$h`GkA7{Y(*SJ&C_rvI-cTQRtl$&-HIQ6%8K)QGS#kDCg?^E}Z}yhAAer>f zkA+WC7xygAH0?7RZe;@E@8qmPA?Ed;x!J>{_SP*j-!8F~kADbP2%J)#)@q4yc4q;X8E^Ur4GE!PsiOKSyvnCv}Dxq48(jekWy@^Bj9-{ET z!!dAJ`W*Lsq7!3gm0n>eEOB7dcNpb;@=oEXquFI&^>+L z9I!__HpvH6?fib&{6a2q}`5R1uKgkVYHd8DcicsO<)krG$MA3f{{f6 z$r`dJot{K}3L1{0ZnF6%7Uck53gBnG7He#XsPp0M=m7JI*%eX<#im%`MB?{ao=|S(!Z5U1dmj1Hd)#~e>l>j8Y z@=V<20)0?`++WZ@5P#&{m6WAkZXwbZ#RU0cfR`~6K5xBx9AXx^?#J_n^jG8R*pm>l zPe0BPBJ3Z#h&^KwsY*8AXNAW;)UJLp0ABWhMGF=yusQ52=x3M9ogC5{tk{+cKIJ;O zgH02XK_OAKd8_!n7;;K8QB6i6Kis2+*&N7oiR%Rz&#CCcv;mGggike=e%l6B7 zUOzg{FA@)cgEe+&;=ut7%(kxvSpKS8Q>lfa4;0N$&Wf(H8bmY*!!*2G--TReDHI@3 zeQAF51cps0p~>IK+@ zliC~P^C_tv0%N|oM4D0a+_2!>Obq&QJ;@09s-3>KIit+}D)xeJ57^f?p43ISM>2*} zrV&7wxPR1DIok{?Fcgp49CGaXs`{|{TsA^IU8bO$85z)q9x@v9BkOm-te53c=qIC% zf31CP^nWMQ-Uh~n2A$2lJ7mwOHSeu5?Y>Z#Z*auv!7|x`stL+Af%1%#7D77Kkt84pTe}@JKvvz zHl9_`do7{aubwJ6`Iy7Kw(VD?!hGNfCGjclcwEpQd7Wj-BA^tEYosGrVQ>+#=$ZkHtq3pgNzt?Y$m2R|QkLA#Rc~a4Gq&d~hUO^(M0wc81tj zB#btgH9O@4n`|aMO>T+WY~2UvLo7{DvSQjDL*!5G}{0 zmq?(4k{k#lV?ufFRdYw1lrBQ1=@fhDm_M;QSCIV%b+Bzbx~@(6t3zfZhsKyC%0A7E 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
Evj7_xv+r{3n&&`uXuR>8vvr4;R%Zk59 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 W@L#6w-MIQtT{vfXw&2XQ$o~a}k!3aj literal 0 HcmV?d00001 diff --git a/docs/user/security/api-keys/index.asciidoc b/docs/user/security/api-keys/index.asciidoc new file mode 100644 index 0000000000000..c00f58cf598e3 --- /dev/null +++ b/docs/user/security/api-keys/index.asciidoc @@ -0,0 +1,86 @@ +[role="xpack"] +[[api-keys]] +=== API Keys + + +API keys enable you to create secondary credentials so that you can send +requests on behalf of the user. Secondary credentials have +the same or lower access rights. + +For example, if you extract data from an {es} cluster on a daily +basis, you might create an API key tied to your credentials, +configure it with minimum access, +and then put the API credentials into a cron job. +Or, you might create API keys to automate ingestion of new data from +remote sources, without a live user interaction. + +You can create API keys from the {kib} Console. To view and invalidate +API keys, use *Management > Security > API Keys*. + +[role="screenshot"] +image:user/security/api-keys/images/api-keys.png["API Keys UI"] + +[float] +[[api-keys-service]] +=== {es} API key service + +The {es} API key service is automatically enabled when you configure +{ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. +This ensures that clients are unable to send API keys in clear-text. + +When HTTPS connections are not enabled between {kib} and {es}, +you cannot create or manage API keys, and you get an error message. +For more information, see the +{ref}/security-api-create-api-key.html[{es} API key documentation], +or contact your system administrator. + +[float] +[[api-keys-security-privileges]] +=== Security privileges + +You must have the `manage_security`, `manage_api_key`, or the `manage_own_api_key` +cluster privileges to use API keys in {kib}. You can manage roles in +*Management > Security > Roles*, or use the <>. + + +[float] +[[create-api-key]] +=== Create an API key +You can {ref}/security-api-create-api-key.html[create an API key] from +the Kibana Console. For example: + +[source,js] +POST /_security/api_key +{ + "name": "my_api_key", + "expiration": "1d" +} + +This creates an API key with the name `my_api_key` that +expires after one day. API key names must be globally unique. +An expiration date is optional and follows {ref}/common-options.html#time-units[{es} time unit format]. +When an expiration is not provided, the API key does not expire. + +[float] +[[view-api-keys]] +=== View and invalidate API keys +The *API Keys* UI lists your API keys, including the name, date created, +and expiration date. If an API key expires, its status changes from `Active` to `Expired`. + +If you have `manage_security` or `manage_api_key` permissions, +you can view the API keys of all users, and see which API key was +created by which user in which realm. +If you have only the `manage_own_api_key` permission, you see only a list of your own keys. + +You can invalidate API keys individually or in bulk. +Invalidated keys are deleted in batch after seven days. + +[role="screenshot"] +image:user/security/api-keys/images/api-key-invalidate.png["API Keys invalidate"] + +You cannot modify an API key. If you need additional privileges, +you must create a new key with the desired configuration and invalidate the old key. + + + + diff --git a/docs/user/security/index.asciidoc b/docs/user/security/index.asciidoc index 7b7e38d610843..f57d1bcd3bc2a 100644 --- a/docs/user/security/index.asciidoc +++ b/docs/user/security/index.asciidoc @@ -36,3 +36,5 @@ cause Kibana's authorization to behave unexpectedly. include::authorization/index.asciidoc[] include::authorization/kibana-privileges.asciidoc[] +include::api-keys/index.asciidoc[] + From e0cf748a1dff029c599c292f4b52b4ff51e410d9 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Fri, 25 Oct 2019 12:46:09 -0700 Subject: [PATCH 172/191] [Reporting] Fix scroll timeout logging bug (#49111) * [Reporting] Fix scroll timeout logging bug * test cancellation token * test time out --- .../reporting/common/cancellation_token.ts | 12 +- .../csv/server/lib/__tests__/hit_iterator.ts | 136 ++++++++++++++++++ .../csv/server/lib/hit_iterator.js | 71 --------- .../csv/server/lib/hit_iterator.ts | 97 +++++++++++++ x-pack/legacy/plugins/reporting/types.d.ts | 7 + 5 files changed, 248 insertions(+), 75 deletions(-) create mode 100644 x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts delete mode 100644 x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.js create mode 100644 x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts diff --git a/x-pack/legacy/plugins/reporting/common/cancellation_token.ts b/x-pack/legacy/plugins/reporting/common/cancellation_token.ts index 11425c3002d97..c03f9ee7328cb 100644 --- a/x-pack/legacy/plugins/reporting/common/cancellation_token.ts +++ b/x-pack/legacy/plugins/reporting/common/cancellation_token.ts @@ -7,11 +7,11 @@ import { isFunction } from 'lodash'; export class CancellationToken { - private isCancelled: boolean; + private _isCancelled: boolean; private _callbacks: Function[]; constructor() { - this.isCancelled = false; + this._isCancelled = false; this._callbacks = []; } @@ -20,7 +20,7 @@ export class CancellationToken { throw new Error('Expected callback to be a function'); } - if (this.isCancelled) { + if (this._isCancelled) { callback(); return; } @@ -29,7 +29,11 @@ export class CancellationToken { }; public cancel = () => { - this.isCancelled = true; + this._isCancelled = true; this._callbacks.forEach(callback => callback()); }; + + public isCancelled() { + return this._isCancelled; + } } diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts new file mode 100644 index 0000000000000..c439c2bbf60eb --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/__tests__/hit_iterator.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import sinon from 'sinon'; +import { CancellationToken } from '../../../../../common/cancellation_token'; +import { Logger, ScrollConfig } from '../../../../../types'; +import { createHitIterator } from '../hit_iterator'; + +const mockLogger = { + error: new Function(), + debug: new Function(), + warning: new Function(), +} as Logger; +const debugLogStub = sinon.stub(mockLogger, 'debug'); +const warnLogStub = sinon.stub(mockLogger, 'warning'); +const errorLogStub = sinon.stub(mockLogger, 'error'); +const mockCallEndpoint = sinon.stub(); +const mockSearchRequest = {}; +const mockConfig: ScrollConfig = { duration: '2s', size: 123 }; +let realCancellationToken = new CancellationToken(); +let isCancelledStub: sinon.SinonStub; + +describe('hitIterator', function() { + beforeEach(() => { + debugLogStub.resetHistory(); + warnLogStub.resetHistory(); + errorLogStub.resetHistory(); + mockCallEndpoint.resetHistory(); + mockCallEndpoint.resetBehavior(); + mockCallEndpoint.resolves({ _scroll_id: '123blah', hits: { hits: ['you found me'] } }); + mockCallEndpoint.onCall(11).resolves({ _scroll_id: '123blah', hits: {} }); + + isCancelledStub = sinon.stub(realCancellationToken, 'isCancelled'); + isCancelledStub.returns(false); + }); + + afterEach(() => { + realCancellationToken = new CancellationToken(); + }); + + it('iterates hits', async () => { + // Begin + const hitIterator = createHitIterator(mockLogger); + const iterator = hitIterator( + mockConfig, + mockCallEndpoint, + mockSearchRequest, + realCancellationToken + ); + + while (true) { + const { done: iterationDone, value: hit } = await iterator.next(); + if (iterationDone) { + break; + } + expect(hit).to.be('you found me'); + } + + expect(mockCallEndpoint.callCount).to.be(13); + expect(debugLogStub.callCount).to.be(13); + expect(warnLogStub.callCount).to.be(0); + expect(errorLogStub.callCount).to.be(0); + }); + + it('stops searches after cancellation', async () => { + // Setup + isCancelledStub.onFirstCall().returns(false); + isCancelledStub.returns(true); + + // Begin + const hitIterator = createHitIterator(mockLogger); + const iterator = hitIterator( + mockConfig, + mockCallEndpoint, + mockSearchRequest, + realCancellationToken + ); + + while (true) { + const { done: iterationDone, value: hit } = await iterator.next(); + if (iterationDone) { + break; + } + expect(hit).to.be('you found me'); + } + + expect(mockCallEndpoint.callCount).to.be(3); + expect(debugLogStub.callCount).to.be(3); + expect(warnLogStub.callCount).to.be(1); + expect(errorLogStub.callCount).to.be(0); + + expect(warnLogStub.firstCall.lastArg).to.be( + 'Any remaining scrolling searches have been cancelled by the cancellation token.' + ); + }); + + it('handles time out', async () => { + // Setup + mockCallEndpoint.onCall(2).resolves({ status: 404 }); + + // Begin + const hitIterator = createHitIterator(mockLogger); + const iterator = hitIterator( + mockConfig, + mockCallEndpoint, + mockSearchRequest, + realCancellationToken + ); + + let errorThrown = false; + try { + while (true) { + const { done: iterationDone, value: hit } = await iterator.next(); + if (iterationDone) { + break; + } + expect(hit).to.be('you found me'); + } + } catch (err) { + expect(err).to.eql( + new Error('Expected _scroll_id in the following Elasticsearch response: {"status":404}') + ); + errorThrown = true; + } + + expect(mockCallEndpoint.callCount).to.be(4); + expect(debugLogStub.callCount).to.be(4); + expect(warnLogStub.callCount).to.be(0); + expect(errorLogStub.callCount).to.be(1); + expect(errorThrown).to.be(true); + }); +}); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.js deleted file mode 100644 index 5ad6182568721..0000000000000 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; - -async function parseResponse(request) { - const response = await request; - if (!response._scroll_id) { - throw new Error(i18n.translate('xpack.reporting.exportTypes.csv.hitIterator.expectedScrollIdErrorMessage', { - defaultMessage: 'Expected {scrollId} in the following Elasticsearch response: {response}', - values: { response: JSON.stringify(response), scrollId: '_scroll_id' } - })); - } - - if (!response.hits) { - throw new Error(i18n.translate('xpack.reporting.exportTypes.csv.hitIterator.expectedHitsErrorMessage', { - defaultMessage: 'Expected {hits} in the following Elasticsearch response: {response}', - values: { response: JSON.stringify(response), hits: 'hits' } - })); - } - - return { - scrollId: response._scroll_id, - hits: response.hits.hits - }; -} - -export function createHitIterator(logger) { - return async function* hitIterator(scrollSettings, callEndpoint, searchRequest, cancellationToken) { - logger.debug('executing search request'); - function search(index, body) { - return parseResponse(callEndpoint('search', { - index, - body, - scroll: scrollSettings.duration, - size: scrollSettings.size - })); - } - - function scroll(scrollId) { - logger.debug('executing scroll request'); - return parseResponse(callEndpoint('scroll', { - scrollId, - scroll: scrollSettings.duration - })); - } - - function clearScroll(scrollId) { - logger.debug('executing clearScroll request'); - return callEndpoint('clearScroll', { - scrollId: [ scrollId ] - }); - } - - let { scrollId, hits } = await search(searchRequest.index, searchRequest.body); - try { - while(hits.length && !cancellationToken.isCancelled) { - for(const hit of hits) { - yield hit; - } - - ({ scrollId, hits } = await scroll(scrollId)); - } - } finally { - await clearScroll(scrollId); - } - }; -} diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts new file mode 100644 index 0000000000000..68836c01369e3 --- /dev/null +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/hit_iterator.ts @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { SearchParams, SearchResponse } from 'elasticsearch'; + +import { i18n } from '@kbn/i18n'; +import { CancellationToken, ScrollConfig, Logger } from '../../../../types'; + +async function parseResponse(request: SearchResponse) { + const response = await request; + if (!response || !response._scroll_id) { + throw new Error( + i18n.translate('xpack.reporting.exportTypes.csv.hitIterator.expectedScrollIdErrorMessage', { + defaultMessage: 'Expected {scrollId} in the following Elasticsearch response: {response}', + values: { response: JSON.stringify(response), scrollId: '_scroll_id' }, + }) + ); + } + + if (!response.hits) { + throw new Error( + i18n.translate('xpack.reporting.exportTypes.csv.hitIterator.expectedHitsErrorMessage', { + defaultMessage: 'Expected {hits} in the following Elasticsearch response: {response}', + values: { response: JSON.stringify(response), hits: 'hits' }, + }) + ); + } + + return { + scrollId: response._scroll_id, + hits: response.hits.hits, + }; +} + +export function createHitIterator(logger: Logger) { + return async function* hitIterator( + scrollSettings: ScrollConfig, + callEndpoint: Function, + searchRequest: SearchParams, + cancellationToken: CancellationToken + ) { + logger.debug('executing search request'); + function search(index: string | boolean | string[] | undefined, body: object) { + return parseResponse( + callEndpoint('search', { + index, + body, + scroll: scrollSettings.duration, + size: scrollSettings.size, + }) + ); + } + + function scroll(scrollId: string | undefined) { + logger.debug('executing scroll request'); + return parseResponse( + callEndpoint('scroll', { + scrollId, + scroll: scrollSettings.duration, + }) + ); + } + + function clearScroll(scrollId: string | undefined) { + logger.debug('executing clearScroll request'); + return callEndpoint('clearScroll', { + scrollId: [scrollId], + }); + } + + try { + let { scrollId, hits } = await search(searchRequest.index, searchRequest.body); + try { + while (hits && hits.length && !cancellationToken.isCancelled()) { + for (const hit of hits) { + yield hit; + } + + ({ scrollId, hits } = await scroll(scrollId)); + + if (cancellationToken.isCancelled()) { + logger.warning( + 'Any remaining scrolling searches have been cancelled by the cancellation token.' + ); + } + } + } finally { + await clearScroll(scrollId); + } + } catch (err) { + logger.error(err); + throw err; + } + }; +} diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 62f8286cdf364..731d0f084a718 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -112,6 +112,11 @@ export interface QueueConfig { timeout: number; } +export interface ScrollConfig { + duration: string; + size: number; +} + export interface ElementPosition { boundingClientRect: { // modern browsers support x/y, but older ones don't @@ -248,5 +253,7 @@ export interface ExportTypesRegistry { register: (exportTypeDefinition: ExportTypeDefinition) => void; } +export { CancellationToken } from './common/cancellation_token'; + // Prefer to import this type using: `import { LevelLogger } from 'relative/path/server/lib';` export { LevelLogger as Logger } from './server/lib/level_logger'; From 9bd8f74ff8795c9c5581968fa256ab140ce0ea7f Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Fri, 25 Oct 2019 13:27:55 -0700 Subject: [PATCH 173/191] [DOCS] Updates Snapshot docs to include retention (#49007) * [DOCS] Updates Snapshot docs to include retention * [DOCS] Creates tutorial for snapshot & restore * [DOCS] Incorporates review comments for Snapshot doc * [DOCS] Fixes typo * [DOCS] Adds x-pack label --- .../images/create-policy-example.png | Bin 0 -> 219430 bytes .../images/snapshot-retention.png | Bin 0 -> 219515 bytes .../snapshot-restore/index.asciidoc | 228 +++++++++++++----- 3 files changed, 170 insertions(+), 58 deletions(-) create mode 100755 docs/management/snapshot-restore/images/create-policy-example.png create mode 100755 docs/management/snapshot-restore/images/snapshot-retention.png diff --git a/docs/management/snapshot-restore/images/create-policy-example.png b/docs/management/snapshot-restore/images/create-policy-example.png new file mode 100755 index 0000000000000000000000000000000000000000..e871c925f5fd525a708f838d989611d914a39360 GIT binary patch literal 219430 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

ch<9G> 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

^fRCT7NOVJ&F-( zP<{B;SN|l?)YkZleC1D1VV^2PktPxMp7`gQ+@n_S#FtQgdsh6`{fAlIHf^Rp>a(7^ z$&Ix8q}o7T@vS?YHWc1L*5krFl8s-DNFb+8ACyKNw7V?t?M}a6r9?`P`Yb5MSiB@l8 z+bl?$nh05N>epMThWzYXntPsJ5&ZS5oOmGUZQXS^QR~j|C90LSLsZu=_3RU-a+{O- zdPEdA<^jT>4^?)%0xk0``thHhj96|Tc^_zEXyW8gr@c2xMEE}PsW&H@Q)Swz1;JXo z_a9S#Nu#rbIw|Mh9O=_~a>REOs|0nES9bfy<_38~{lMPwukz~4Q0xn4zYVx<|6R!> zti42P*frJf;$I9Ni~C-Eq&>j^aw+=HMnxs2N7R$r^Y4o0b$=khDG*wzaleM!Pdn+`$8YTp-TBPF zCL{kfD%pGqIDHc;{hETwaHAh;EgPCJnjJsE$4e;g?^3D#MJ_H5*iy~4f$lQd=`FYs zSPJO$$twpetbvO=mvDa1vAIFX@SS%2c#$`EY|ARu#26A!jdpsDHSIQ<&Yeu`Tv7(y z%EC9%%SgPJx{y-u|UZG{ZaElp$jN2*Dwr0_+IX;gmxHhPa zE1+RG8=gP1uizgN{3ap49Z-He-}}g)Doh*isv!=6)PiQLlL3!{gfhZqiW)6G%If>m zxyBVG=;WadvD%vu#z3WBg49L8kK#Z6EC1u*9(zP7|HKJ}EoJ zJO&VXg;fUiY7`U~3Ivi=e*e>hbmu>&(cF(_<`)2O2*rKgQ5&S$yuQTp)jtdJOOFQH zJ^t;%@~R?feE704w2?G+A8V6*$N(>w*?vdbLS;ub66MoHPEo)1)% z?W6+mf3)&)ON|A@KypBUin9vvKAWw*dv|3g5!7^1ZZ>-P23P$|$iC{!59IBNC% z*WjXh!zZ8xem6W21Gu5R>6kZl5D^rM_~@$UK?j_8e_zgjpZ9;>|9g#qv&?@rasL;_ zG;4f9lc3s_?k4xId@QTwt}QgOB2#7*PSZ>!jYbA{mD2^tfu;_JJIpfVzy0 z--e$vF!!;Bs%~0rp4_Lw-5OUEO=EV8bq|eLXS_WsLf!p)%;IX(NzI>T6PI)G5|j@D zjajh9Y_E|)$FJ+v&j~5jPc}Hkfz}v%sOrLVs654+51&ifaPD7IDZt@;OkM|Y9Wp>Q z#@zM0Sg)qy8!-rQg?-aQerdwucYmnM3LB;FYEhU7db`JiCpqN$Q%RHLYaZnR>0$?8 zRSKXl`A%TqjwFeygJ9m!Pq)1s+FeoZoPuvRH9qkCQ)cF)?M%KN@T~{Qe74d`4J%}k z543Cp{8vf9!2UT{jpo1teI0|`@|gyUKYu*2J{=}8(m1=h%;2AjmR!rzWa^cnnL3u3 z5Ol=vVUb^HI{G5pI^D*LKbtJGIRSP0p4FSzRxEc!xH81O@B{kLZ4azWd|AfNmSDxz&C$;Bbq9$8z^qEWYO23yX z=CJFq#~lN>ewPkJmmuss?rYvJ^J^h2^Kp#vJe{$rybbGZJQ`Y4nOJO{YRe9JYA<5^ z83}Ak%bHxrysm9@9NE6LCui|H6Kc|Q6OS*fQ8BaDg@xb_@Tz=#iA2P}n?qd;nS@z{ z*NWA8DyK=r4+YVgV|&iABG;NtAD~7eFB@Qf(wJKxEJbjEtG7imN-`;9 zHNZ4)&iLnVw+FTl49kgP?R7;zwXm5@ZhHTYBF$fUvb14%+cEc(gh%4i_+<0_VBIIe z^yI^)xr+G2Y#b=YNDb2uN~fELE!QNa@N!4sIWeHfds(^ihCXLXu3qhvs;~{xFPjYd zS}mO3iZF{O)9tncm=L}$vRqc=O`%8A)j4*b=xiCA?M^VKZt=%<-Y(Hf!hvgl(8Wlp z@Le2OXM$)sNNbou<8+7BgHO4=1C?`_Ni=mr&7&a`)e-*=E?-nbT8>a{*h+NnB#~VbtQsl2`=A3NZlj zLE3J*CHgM!amRZ#;3nCIq)eO`<3_44%mXfc%`GuL;gh36QH4_ZD99d>($%S(PuR4B-c9(Bcar@PZy0i5Eno}wo6LBrnTuAm*w?+&Xo0ajhkBq z|E%9fxV>M|5>tE@CSDem)T~}&YeoN)$G$g`?WLUH$URM@YCZ862HW5CUzwQ>%bc~S z(jwZ1eN!H&DPwl_^+Rlz5-geN2|RG6+fXjz9U`?3M$*x@eYkjv>orjc?OC~vQB3VK z!NvLvyt@)HPz{r<9Sd6d5FYMQgNr8$xEG@Brz=$m+pMk? z;D}SMLU6Cwt*8qPUBS&ZN1|FT)_FEil0Y32VZDZXu)RhmqMo3klQ31vuA zV&l<_^tT3^tm z%CWbsMFM1r^5i78Dm2WRGg8(69dVm~MMQ1;V~THT+)mV)U>Wn*@!6q-#u4c_*`Epk zd%kXw=Vjrg;Y2SiKA+a~)X#K2WWdYXv~T!|SsI4(z0(aYh}4h~^Cssm60@L%2UUzw zx{Jc00g-7j2X;pz^KEL;8g(i-@iX<)HMWbN#$6Skfci|dReyzu3+`*HrWp5haOS+k zpMc0(LsvA}b3codJo*DHHRfUk7CA_k-X823!Jlw2pu}EDF$>DQ>yzMK!?XW%Ca1$7 z%!vr8u;;oF{d~xbNUTQg0WI+)4S{5fYE|CmxMDkV1|6pQEEx^yLyFpMftB3WGMCZD z!?g=_&ZN@73b^U0sXuDc<+_GVA`uJq8DV}Vrse@BU$T5qscR#bw_RWn^TT;D-0w6h zD`}EXM18_*O03@lqMQoXIxVX{#EaD2|KwpU@2E%-=?K?K9QCY|@B{z^U35 z4UnPYd)f88dLV|3U5zIjFJmTypEj=LP#5#LsuNZRNd4gS!EzgyRS(iSNkTez-@Uqt zlLn|JFpKpxxN&;JmY{ix_%7#gAH2|~kuecMK!9BP3lHf|D%jP?!>6XFaljx3(h?~i zl3?0^3%IL*09`nmUVgqwye59FIpG0{ueG8N`}av>bQK3w!_j#0l@A6J;`4GA=>{Vq zZRnE93tKHQ`=92(9G(n%MfM>U@HYwEtoq0Sb)BDY&whgspA^GiH}co>5h^Q;JxpNAIg^bp&;=(5IS0}hP`PaO=W=amN%iPE^$3Ox?mL`TOSCh|v zk>L72K1HunGa6|gkkVWud|s|mmY^kth-x)G109`QNkpH)PwT$48pV#Y+B;{@YKlAf zHA`=UbBx1$2fnZ1zojDm`%b3sWF1vCYgfv*@Ba zlw>qPX28D=FEs{KcTy_~7zt+ZM($bX?U=+yp;|G)!)>>Bv%~f;&20yNA*}kYeP5}w zK(WMC)S3)K8S%utBm+sNqIhnnC#8aaq+ne<+ISt<6o1QhAI7FMDa?#AMy{6rn6*3d zLyuW0wpkfZ8Axn^bH>L>v0F|to$2^0?-Aw#mv|<8i(*HKKfUnZhxea~<@4xg`r*n4 z)V=`j83XBUTcVD9^{9={T$kr$^uaZxd2kX4X{y87WqeUTmbPTbtkHofjs~O;0&}(3w+obg%TI;(l zb(G*()Q`!Lkk!a_59)Zv`tzn+##_eRicnm~_kDK$=^x^MvST-Cwdc|;H!>0oCbr$n zt`G+K>;W#sro&9b9ig3>6w^P?#_3jUJ))kS6|P+Xsh~N$PPfZ10#~MbNAfe*z_y5y}SgU0k$eu3HRuk;>wpj%K_cN7uW} zHCnQ{IxyRNyfa;lqYW5eA9CM4DV<3D^d?^e5`qNwTNu4^R74fro2)EdVrAxoyfTwG zlBpemPf~>9VRyD4g(wh7u1XC7^$mW9^C zPlvMFok9va9-inTTEd$7mXLA)%JN6?}B)YZw^+O(bjJ>&J<{O zn-=KeP|m*8W-M&Xf-+KOgwMm>0j8Q8t&9cSA%(CIE*V^()hS8mvFb%a^}plf?+;^I zL}KHAW(0`aZCXTvJy&fpzCaOEb(}oJ_Tk*ho<_>C&w@w{KlLwVM$5;k-@&c?2D8qV#Z>xVcFqur9&%wst%lQ%+1J?|3Qsi-l$%b zeD4W2kdOQo<2uPDH)wNDuuLKsVn!5tsCf;}Lt}E-N~M54OJ-_HUr46Ov{q6Ro2I*7 z>IEUwssf)o^sm)~E)r&Ae)uGiqv=?;gg5o`a}vMu<#tMlG7A*YDy}N~jt~28u()~B z@UE_?pPNSZ|6`w-FSdlia?>2!VqY=b6hJe%>y%AI#@?~Q60iduzMSzS}!e@2$%Do z?XAmAR(5hn{N*~F4WO;rt1WOU;&GGfTdbBrlKK_&`dZQAt8pi2hCm7OsYbmAZ&_5- zlK*bmNjlv-sFC*a0N&{P+ehY4vACAaH4Lzrmz(%ELtTZhUkuRdZV_)-4wp5dX(4LI zCJ}<*hk>})f|_aZgO5O1%+tBePYpi7W9OW5vZA%L0&HWt`e-*Bpy5!E600ggzU7+8 zIf&oV;EL9%`?keb_!9w;U!~vO7n5cU^*00|SDVZ#;qxE94@?7zd-Qc?n{OXXD3^xu zL?tMcO&}q=cB+v4>&D*L&MAp7_ba~8iMc9qS`w98j;yuy^J}{^m(-{cK6O?xb;Mzz zxHyteF4A;;iV4UC$IMjplV7VDNlspsMKVlKi8U@OZ{2?Rh6K^iveO|F6~j!|US0Q; zN^o5ilK;07h`E+2y>QKUULc;_%hi{Q)bUs+d@iXK%ULQ8EgHx#h` zS*pdL3lLnTf7!ZfKDG>{eAKtB7k~YRO z8<=f(esP+(R`5SH7}syDp^HN!lbu~eK9^yK=Wp4^=wT=^d{$y{d2}p^y~ceNv27cu z8P2+5lIyV{rZ^B3qsfwQrqL2@V@*p6x9%p5GMzGzvGEvsgZqlfFC+MJeEd&9FXIiA zHX;4BPfjr@p3ODAIJ3Aw^)FDYq16iUpme%rATHj_CiSvGO7(<~DA3Hq>+vCc7bJqP zd@dG}2jS0o5?E@^9E147>t~aZ^h=43EDDpFyty4n3T<#5!SMg!#~j;PHZOcTpkh_d zby+WZU5B9$OcO$e3xe>^!WLpv=CzPOeH5-!6_ea@QN&NgBz5FX`W0Ll0HpLGTukhP zupmU0F*^Pn#MQzcO*4^jwo4M$j8@j!jm1HK`SL5`%MMC7@F4t&qOm#HsRpu}?H=xj z{cnkXo&zag3ds1C=MY1w zeA=EHcIoXLHLqy9#u>d{NselFxGi@308g`3~%o*#7F z!K?xj$%=Z7K8f<$``if+R8F)%ySN>o-TthOs#$1VFK=D{wN_3ze=2kF+}ytIx=cvSZmOwS6*v4I?iDliTxDmOfnWoAlL!N2Y!1BZ7l8`%L_DQMm2CY=eD# z=NNyPw7lCQ)pzPJcxeP4`XEKgNt=12wS#msFAG3){GEV@QCjDLR~3T|dTGzi+rnw7 zQRX3~^uvpk%LXRc=ya1RM^biPhI?9{I%V9A-*qMvPOUL=Nr7wX&APw81sdL#hg1gh z_fT?0Jen_|S=(U+?o9#&O9CBJhMArpcRk>g)y&uzlvrw0wN{f005s1b+%1Sz)Ky4% zpX6dKQ6xLpAk~2q2-LIXgTUThFGHeJqSe<%*U3s*V^R_!n|D39MTd!Lns9&4=ByDu zOak$7PQuLg6On3nh=!bc8Fr{_4xfFu>QGEh;T$ZO_U7P8e9g$j{c2D6GJE79`Sb0n zE31(0UwAizHPaHSJhjPSP@Ua~qe)ky#C37}qM2$hqSy#IdR$jX^UrdY)`4sv97d+e z4ivDM@^-$@thj7@W5i&9-9V|qwH!F(&R=pZy$8icGx$e-FDyOtxR^Z1u%w(#gF_eH z40$$rX?*+k5(i&=D6e%gL1vQ^lbndq8g}f9h^-ZZj9e1)c8U-t(125-Nif4k<_hGQ znq#U|;fVWa5`cUCGtGOARp{)R3>-bruL6-)>UvwR4YNbwjOuY9Tl!vpH=^=N3nRy! z(6;=CQSkMPN0ZAxw>pypYQdfZQ19Ad_LrlUxiO$+^Ne!Gm5yaj+CV-+Bl~7VCNJiJ zRC|ka_zJW3;aCQgVk`vo)S!s(=>C^8oq)aanw)ILORs& z4Yw0^qQk@^6!sZqT1qFo3U?ioKN$Jo+Azkp{<(2zMyj%tM-Um!!qcTu)(`84i;z#3 zh;@8b-IGYhN`N+LBN0PQEp6m9uFu9y$o}O5)m))!24%aJHfg~jEB%U zb~B7I5OP5D;k8y?iffq>k0W@;b)>XtDsf!Fc_918;>!afxtN3oLu^K%i?CWqa1K_2 zd<}Udw$uh$yjD}_0z+x0t&X15CaXuUP@8DoI^ky5Kwrb-Wlg$=-3LO2>`brqBEZM! zK%#9WhHLbrJov6F><}6pa*aE!E1nv^1|<8zxVGD;4N|W44o50*U$p81i_`|X6FUCT z1FCZ0u3Yz+f*ytz<(j-~F60?RwZzf{ec|ui&)b=lH@-l1KhWf$w_<*PTP&^NxG%_H zw0{k}{Rv(-U4?&{I+8bOOE@PLV#f~om9Q2(zU3xTvELs!vEE__Y28=NX<&unTez|q z+le)Bk4>cpg5dYW^ct2k?uB0R6yHFR<^#~VPfhX?Yk+iv@QRbg1ZkaB2#OAY&gbN{ zh^A~$ZercUHlX6qKJ5VN(`TvtXE%h^e4K%}SjnwLQzS+x05tf}9EG*qV6Qc=d|pW; z17!jH9!$&L1UBh073teGU$aQ^1o;_%d>9%HQWS}|Hg>k&7Bb)ph~a*lbImlUs_c-Q2sIUf|l(_}q0*+G8KmsU>>fTQh z&WRquXtStgR$nAI=7L%m4`2ce!XDX=F(pISyqDL3dBn4lFSjfS#+@Fn6YHZo`j1+& z=3utIzEG#X4BYqY-%~&~6+G7TX2i|z;QIh-n*Z$3dOE5W(K+u-q&H3p(jVoS=Z@80g1Eyk)>g^Upa0|Fib4)McUP}?x;c$8 zW$KLFMm;FbMBSddWX&4qF{V?CaEj(%70Q{O;a9j}k#-+aHj?6mLo{S;HuV!*6~|XC z%dSDch5x6rUWr}u~yw#fx7);%Mw4gC~QfJZzg&kQia z+@97wU29C93Mz0Y8rG&QPNJPOmft}S(XP{f;bqe&5k<%=y%`zeE}M7!ZKBneMtvD_ zbq@HR-{jN%lpPo{^#nLq0he0y{81wX9b#cTT1l#QF~}3kaXi(a)^dCwDdD41*T7l# zttFP!zXgQEbqC|d1%iRYFF8-9eB9^L=adn5O*gS{Xb`u6p&Fl{n9g2Ibh62$xMf!_e6> zmn&eGr5QKUj1N%zHVy?O3KGz;c`vcQFfepWt*IxEh^Wac!u{75|PeQ^g>i z8(9Vb-lq`EW<#m7V=}j;IWX{Xum{Miw2Q{zjFYNVD792pX5tEiG43}1b~9StZjSb4 z>=ppF>?{eLgOJs!?+&>?x97hmx{pa^Rf|}NWH|%lf?F4b;OhG0zykMLn-Z*DD>D#?B z)M)o4V@C3ItvfNN0*WdNam|{7##kCU}$;KBF#a{B9!@LL&M~s#DVE4Q6wJKi2 zmA*fGY^sbWXw_p6o+((iT$c5sOcKBw5+IBY6YkW-xE^7eqsv!T=Pp+WR{!XlO?r!N zHpgx;`euD-glnx^6+oAU`7QAMpVi##)_3boBw9w4mV%veo6N7o7BSmv?Lm)#oXPmW zufCxscbz-{OwS=iTon&IM+qh8T?7uHdG?CoQ$kop2JX5LP-vbCYv9iWyhTSm30 z-)a}bv`nrpKYr51IRFt)@(4l)1a0DPhSJ`jXwW7VEZUKxdc<4J>+C6|a+9AFHl=2r zdNQ`FG?O#=W*XWUbHtgQXv=E?zF{wnv$1Sjd` zdB~XNa0)IXyuEwG5u47BcGQ$M3q+lfw@NL+g>;J`Dt%5@{rP67fgws>Btas(N}aTo zCEKp8060%|`7k2#PFd6r>OqykCCb~RL|yGeV(;dqp`tQNmthDn3^Fi?CY>2y|sR`26efq9xZa{4Q7+J(Z&w?w*!>O zjjYYwlTCB}tmIXyN`2+<=gv9*M?S)|)FMM3IgQl>_6!U*q;fJ%d3iZ_;Tj{P=eSC*U2WsP z%O%O1$JH`9loJ@2hX_HLRY&`-+d~9WZIYrvxl9kpGachyq7G~a1z*|bZ2&>`$w-b* z$DG~J^qpy4Zxgy*d7L$*fK$shYmtZrLjR&DzB&<5R-f`YMPc{(6DkuL5+u4|Dsq3fuP}OG{A#YVUp`!_Jd%#&W@d4 z@g`R+Z-m3CO_L^vT(dG*zKPf1jE{dR?$*qG62mxEriSBbTH8@I3;^65)UkEs&x*bv z_w1dLMi(|&0nN)a?h3e850bO4e;!tQ8p#%S+q`3MrD(~HQX|P+@b6({yBPqOn}cRu|GbJ)?gL976>o-8 zkZnOM`i-_~XM9yps#@8Ckehx6vd2sM%;}94kncKw_1}e3DBCP zH6TC-;B$t}Vq!7Gdy$p6h~rpefAYN{nICp+EuA|?y*lQ)7Gjs4ovNa9KG_LOxbRr& z2{MC5ZuJGnN=80A)G8RCx1&F)^WDa$<0S)X?}SZET;yYh5wmG;JCa>;}Huw?=i8sSpF))hbttN%-F{uG|avS9GEz?53Q$`iLyB8 z(KQh}(lu{TZdeR7{MI%RWilWLh!b>uh#-50#+328?#m3?wKIQNeKO!@K(LBAY~=== z&UI0#W;>q!Q~ycIWP|e<`>X}p*I@|gaQ?n4@!I4=87wS%g%7IhJ=5TNR(bz8BZS|Y zzm=uNw`c(i(s4i`mGeB(i)ZVpb(M%qGHtP^YQ28~Mk+L~O}r}+zxW>U9=`mc7wf&0 zB~}@`WZa0oeT5z%Eq?wTMuZ*|$6>n{TQ*5rd1~_ixHW!2QTbNdtoeS)KIdhVkQ7ef z9bjgZD<4LPfP3A%XI|zdiA^EocXt zH6Z$fwrqAd1mt!%$)y-f8!1Ef-(imWN7iq%$^9Td!!Ba{9E{Y$i|FI4jM!$FmRdL5 zqvGmI$ta}#bXxl<8c?NpbGF0gb07bXK%d8ec^K&iAaQ(&u9r}I0O0~yZ~l{TZFg7y zN#WXFbRN|7FWuw8PpBEtiyo1a(QD<)O?PkXzjR^CYX8eb9q5b$dpJ%TV z2&agiwW5z!RB(wU)`_QUyfoML1zKmxG-Ms=OYEah-2(W&t7+$^$j%W}{UkQ;J?@`x zM4w-2%Nr~4WXa(-xH2v(!{WT&qPh_qq5gMb(i5%R=L+!XFn#k6C4#oh;5H{{9Bf>I zouSq<0aE;kgsQ;5OatWc;f$3=_SV)1fo^wY$5ZM`0XVT>ctmT@UVxvh0)kPC_j>gu z!ijxshNvL8jUKOwixp})XX_j3P^aie4PUl@xy3t0W-oB9oLCP-{9lX?N01`#0I~yl z@WL@53vW`(&wbVUNbb+^EW zEDvHS)Upp(9w)QiRqMHvZaiA^ZHk2PI^yJI>ZawNK0ZV_c!+;3IL5Euvt^E%xyIhn z$)u($?rEPS7^)$#D$tMfjBI9_IprC+&=ww6!};Zf`i8qbe*?Np~Xo(Os5zj^CEk zdeW0ENQ1j}veh@2;*VJ8eT;2TPMKX#FrU>zMOZ($Mor? z%>$`Xh2SfXljc~o1+JwNewKgD%RYy!3cvHXV_<#N>2>8T zbv^;05_@fNxhH8V4yki602BK-v^X)Gg)fNGaI29}OoyxHAof)qYGdiL#ih!+6MkBp z3&!U5uVw_GKBQyB7F9A^Qk6WlgVwqwwXul?dor4gW=DrTMw1L8Y%O3YjL?(yz({on zb6eF)462VK`G1XEwtwH%rurm1WLz1b!AlnygnXV;V|K3QWhZ1}NWoN^%E)NZ z%xx+CF%xX|j_TSqe)_i}4p0SF8Mnok&~0r`wGo$OpJcDyBMB%JmrWwtmR)Fe!PsJL zS-jDwGmiKw?AR0_Oq@i?gh1ag02xvEa6nn~BiE6<_dW?ZT3O_r%;#dbo-118T*$ADcEtF*qXnQOI?_4*>-H`N(S;< zyYq6r7pMk3*PSSIdM(k;>yhdTEJ+3KU+A;?C3M6P7>bZC{sV24Y>Wd!d>FtnWCLu$ z^_42SbhlqH?VQzI<3*$)Rt)(dh@OMYY2k641b4SBY^)IC=h(oLunI&|zl7xhOj1iX z4G+jM^Xeu;)WodoLdLRsV5KsOS9w%8_1+3G;Eu9W-!(Mo_dd0$}Icf(*cJMUER=X9P$F@!{V(qKcjIP_# zxsHFCCwl}#@tx#uyX6D}2Z5YB{}xff8NAv!oRDp>bILX6HA8pL_VCk-;Ye$f(fRg7 z>x8$060vAi1Sb-JC>**N_`WV3585i`h^m{+)mhg-8nnud0*Orkj8gG4 zR($~BXH3qDwl}=LGQhxlVjG7QT}1U_0sYLF*c`hbi@HC$eVuHRqysSOhVBYFs0;*k zpY}c)FfVqv$h_9gLL;A=;7p8x(BrPTkFASsmja1h9%gtdg?w597d}|Vf3eX}2N z)ywW2yH&i&0RHQ%e}w`FLgZkh0nt4=e-c;{5ejJQK;Gxql$^2_mr5%dA@H+g?xN>F zwS~*(^DN(?p^+Rs4lFJ9fVO%_LhBvEZEGvSxuYjJ#N^+NdhyWuODNfiatGTuUm*}w zJcOWy@$e>mu@o)p-|~nNxE`l^wtjux>^2@DA#jHbCR|C)<)uk$TDV}Uk3xA4xvM9=Hx~IB@wa(tu4&@yF_jDXXy&X z|7^+xE68do+t0KOHryLo{}v{Z$E6}=(*2k)LgS>v;b{|Zve)S9@%ZT6ox7BmfdDAI zL)&#E7;S_LQK6`1H~5f$hrr9dEq9H;8~Tk)DU^Ymew28T8arvkX1_F{c;D~6bKf>H zld2l*A4E@`UfcoAvVKDKSe$^Gp76Dx1_*#l$;*DA1vYsGwGhgI0?T5^RvKMv*%Sgb z{bqQ+Gd-U*62>Ta4zLeYo6bxrKP)N;a_R9mprp{u_3HymgKj*DC2Mg|ga$L;3 zCqJ?D^7U~kU5@+Foo{<1C-WjoDFC)~-P_Pb?Rk*PFw~oq+5Kj)8k;@n|8;%Pr!DOo zjJdXqxD?B~q(SH-fh!tM{9H@6Jl##c1n4#IG)(K)OXE9?zAH z2mU8|J@qD3ZV;SAoGy{0Icpd@p~OxjO_S>Vn*b#8AW-hmFBy~?bxKi_zjbdB;8r(^ zfTT?)5&L~tS@W9Zm=j5kf*rZO@KaCs0j+B-xb0o6HktnsV}~kH;aiTX{7ze6j9tFmW>f28BMk9z7FPENSyFsrxTNCZ!EqjFz2@9kxg*!sbLtI! zkoj-bChnS+C}&mHwB2#dZ>d^rax&h`uE{}@(zt;)vs1gm(H?KPowp7_j!MBbx4|p` z{a@&Z7VIucy1pO0Gk}i z!MbfQE|6Rk-1f>@R_jB^)cBMWWIli${-t3@L-TJ&*$Mq#f`7=|`ww8%HH`05Z(0>Q zAntp|WuTfMpa~m9etnVokpr;SD4l50N9(B5vZiOm@Fb?@-{|cQtD)@{na_M6`bTt) z0OYL`F8R|~4J|3EqpWzdvr0xW=n1(5Od=gN!pkPdPEBwhJ z-T{fAi*h!N)ng-71U1q;HSBg(4PG$cL=DtZIdY|RZbznkKq5G<(T`@lvQpVm{Qubd?yn}dtzF%2bz3=# zZbbzYwjiP)T_AvkqEr3>}2z&HJu0=X{>|%r*C|O;l;w-}d$~L_tpTn5#)4Z0FXnkQ@Uf z5RJe{=TvW&13gXr_azq~LJ6@^QTSBxs#D5UqG6QByH?4VwFo zUObZme8MZA5;xaTw(L6B3}CZpV^xjw`BRH+N^cKP<#bkK53qJ-{^*jfU)Nk&W~NUg zzcs!#v*pyC1!?s58};pxv&(uB$IP-AZ<%W#FF2sd9g+&HpSZ7=HGxK8?n-~u0i6TjC=y&|OB`K( zbefHLPcz9qIQ>OvJx?a($&!oX1oG~vbHg^bOh_uowW+PO+lNL>rUf5&)FORKTY}a5 zv*reKpbg$Y_;6UbOM^3!nnDOE^BkA>l?`S@2LEw30D0F;3U}2ou3`OIi@+J{jVg_= z9~(cQrA1me@5fd=Cu$wl<`**dq=p6`@~i@Yhg#(|Ejt^fCu*_*fp;^26R{uonx^$5 z!rmi`D@u}cW6v)yNn<>f)HJi7{+?u;>tLyVki{|T7|#al^l%%xHeutKvcpBv8gBS` zZ^Ag|?+p^L#pTG0z8n9eI-%f967Xi{=qpL z1oDeHd_l1i?zl=&+Qa3*u-bac#LoW6@oEZI{j@s!4C{!Db&R@QX~}an-6)FQ7Ygia zBdh=E)@{-$t$|~ei?ivWvgeN}i3)5FWcdsf28t-nQRZ=H61t!nAUPegDvDTh8D%_u z5z3~O4d9F!$OW%snh&(u_q0!#Lbk{OdDHxH#u#VJPcVvvQ zg7P}WdA~B%Tkh#efu!ux54Zym*i7V|fG;n)eEZmFg|GnbNpUFTWR~|so;Y^Y*m0#P zm7jcg)-G_x%(CjSV}8KQeI;`ga3dh&PBkY9IWB2IE2T7I)!A{jL8moX%cXgZHk@tqz%jrF(VHAU)^kfho#JGVZl=5w@u zo)Heb#!JV|R}nO4lVP%k0-DQ@TtR>~q7;;SKf{}*1?{G1EphNl1e?_HfT6nzo2Yw> z?@JJ8=I264BPVV#-T(*id3S^C?qxaq)@-1|b1#r;sE9i=25rc=d`#Wbx;(X^vS`84t8l_6YEa(9-8kM`%ga0s7H} zzqXyIK_4llWa^0q$V(?m6P;e{;5cwi&3!tV|H|kj1+2et2MBjBQ2W?C>LZorEmf39 ztmF?Bl>Wi{x~gZ+wH@DvkOE5Y1@Xv~`82jrkuSFJCd6;Cwts z{rFh4%zE3(%UPs%ca3@vQa0MUtZL{BU}CgnHi?Xc{aQ=$-s>;+nYJ0Hlrr-3<45@b__pgNT9nZMygd_sR5gD_Vdy-L*+$BP z#Vrp{n>c24RhXr(FRrt@b=hq*t9M=mTD8D!le<6`F-JF26E$u}tl7EYaZ9M&#kN!@ zF6QELE;hE&vq4R_g&%&DUKfYTlPC5bz4)jm>yhDgO)n5EV?Ao-FRBQykI&{8V0v^rNC<$kaP@0T z1%nv7b$7&)u++1RCwwWtP|21p^Se7?zIS5KH^0i*f&_Six=K%? zl6unPz`pdB5nO@1Jlx{#m+JX4wsQ(B2pg#+wR`bmuTD~=mTqX<)qOxe-4*or=>VfQ z&ylnJjw5i}YHyd=VP7N6HW8v#sgn_w2hM?{MA&=!YS{Buo;&HKahzQ^yH-yo$iww^26t<)UA}$3>@t*ZM&!8{?$d;k zyEiOMrWUQ(;{I_U%e6kH;S?6VXLFm~)`#~(^+RKe`ZofDv%d<>mOFA%b9M#Q-3UG#YhjXl>#Ahl7tEBeUT%- zyEJ^D1=#=*_UT@9!PIfiANsK&zH}DvGf|~=d*cuSnX>h3XZH!IDf$&zs6E@f%%u-f zxRoB_r~6lbDeC3ybrUao-8!b>Z+J{?IpeV0Gb@Qi1*xR81MJ{)n?nR^0sX zN6Q$>p#IHw(jC9oOJe%}uPy)oBk=#~2m~on@kIt3o^spHea6v}CLKJczvOQN_R|cg z=n`5&<1#f7tDY(w(l&q^uSH8385_jO7#&yf9HViMk;Z{1`Jx#vtd3q7U1d>C<7Bk5 zt)MjuDR4G?wl&GqXd@}9a&U8h{JLh89jHp*cTDl0lpwMy(dbbB2AlXx#0?PPbZ z>&Fy)-A6y&Z}KFPfJ2l`3E;nag#ZU<>b@cX#b&H$6)j?UozGd{tvcCkIxsinwpR2@ z2DN32ulf)8`GY^;6`tdvyD9nPr)oX}8^j#IE;P^MulO?=CYc)Sv6@c;N36ZCPnI7& zjO;rd=TV-z=ZMTw#qYZurUCY%y*Gxka$+Mg1d>4CF1}|0#O~9*%l->#dLe9Df7g0c z(TmNhxhlzIvQ^7V-c8{uM;_CBR5DGC)fG01u@C<}gIuB3=Q-mhY66iJ zK$ut@CafZ(!5w4HhL!eqO{n|M-$9E1wi$M>mTLdb%Y|qG)YShbDx-wZDTx<=lG5ze zR$>M!fL-t8xi`JGQAcn=0==XyMqqPrKVx*@wxPGpQIRK>J~s+zZyh}Ofl6OGWFY?6%!j9>o290yEW^Qm!F@X!9$t#{gbZ3=C9ugx1S+k+MT^B~o0Ox6!(gNBNuY+-fxFE1Ua__`bdO4q!`7~w`lXSh*T z_Z>gaTb@0d!7Ag7v`1ZU^a7ecM=7ZQs9U>;R#1PoQEC)TSvPVh?P@So7^eN6Y9jQV z(wkD@LBtZjf{xc_RIGW8C&Fz2TNf^*&7u2}_#Knh9^7&6eyq$NL zu|sk0Oiy_s~5S?q>ecJRVQUF-|F|AV~?`FXXRU z{dnWko1z63kJcp?U>Xv>evB~B6VUSY8JZTVQ&qyb4WW;e3J4W2DYB1<67p{|STw&M z9*gf!`)ZULIpa{}{;XrVh0K;XM~`*>wztqQX^X;}(N3Q4FaN7({j0r7Qoe>(vm$J}Pp*1`yt~W)um}NJtr#xvr zjDyZoDH%)M%fB8iQFCo|>hwenZ87!95((>Xw03YSSlp#x;|@2Z2FO`a#LV)oTL5nB zs8IRu$Nqjcp0fQ-jT}xuRPzD!aDe2O8%2EQqI*?hFWSPBzKPW|an|kDnI=cdd3|lE zqd=Pf00-fw^BUIqdd+H>x|_}Bh1Q2*-8D+M!+rIEE&7Z~#|IHB-&RI9pJ9fgO^4kooR3qgxngt2(gXQ9-~XbPplZ8p>&Mt*zBTeZrH=l>)K;)W@9fgW0GKcf+=D;A!~ zU*ftxF-8hZevMDaIYPY>{K{+WXwDn{40e`@YdA;c7x{?7=dVlODyytpn>&7hH(%gh z#Ynj+64BZsM8Va6qfO(h*EzW0D_l-*&frc_b*9Ez;CdIgV)dlb`Ecl?{~o$_r3<({ z|MIg(6*zfU%E`PiWfdY~f^4$gDzE1u3DDtTa(4o?KOFFqjoF4NP7UUT?gAQ1Pn!Kn zG2Dp=Q7sX#jZp*Cy6ceJV9EMQL;D+8!lr=yxeo4=UcHcbQb{SP(9v(CfJUFFQtp zv)!8upQaNirbXWP07}^8+^&*jG|J94*8^pd(V96{XMpU zs`BGJ`$(-Hb5+3^B$BL|+Eiiy$oGs@=GtN1$LESlC%_RR4nOL-a#NQ5tei4dCUg_O z|2AA>e{2}89CB5EtVQ0f^J3ep<`PU&a@6`8>zh2zRe$+Wp z$NphKs?1$JxwNvFb6(2DyV;A;3Tg0~&IY_8K_mdueQC%vh`GC-h{%I1k$*OCMf{WyGHQA)&0D)UL0t6{vm7 z@HQXR5xnp@m_VV8`aGJZXZ*Doo}^5Svx^J8%i#&=6DJT{F|nU!2KCOEi38C>x4Q!8 zhZh^ws>z9pZXyS=WCU%ZX7Y1H#^VwXo!mCwKt4p{-%P++pZELkMfh~=m&KPPR~i0j zHA-xW|0-LzWcjb5bJN%_CJnk-50KJna(TXIIxj+$D#LJ(N&JVvQtrXm9A{d;MuwVu zh{ZN6%_YfP(X=fq)-(;_96W8HRn+?rUPo*x{ki^7d8C2O3OSHoJ_>FUr7~b z4;1Qjod^eG6S(j$&39$#Ma;lCLL2^5(yD*aZhlWrZ`q(Hb%~LFw#Q8U9N;A@zb$vmdVp_ckt# z2e5~a*nJ2ewxGz^*mxtvK#M(-g&PvDwA=oB^=xUE+OT3z$SWY-R03->5!{{Gi_c#nRZAg(D?fL2+{NnXdXBH|vl;b7COv2& zl@}4QJE>#gaG9%iEOb+x-`wD7iLMTT z+325ZD|@U{I14PiGu{Lzv)B#Od4|~+x)$LCWE^rdYJa)am=Dz7-j6m~{!)q90_x1i z<6kmNqQ*5ByP2yK@ivRAav~uoko1-IYrZsb5dwzv={*B^v@quy+(tk%TEZm!It}&E zZW6KTm0%)%tD=JX^)1xvzn4P$;SGBPE|;t?;Xm@2q;s@2-$K~7$y)#Vh#!$1c1%P0 z%L(LDS ztYm7CveR1d{^KI)wqo*Vx~$N89gZ6zmG~U9`>Xk0QgHBpORVP&In>{>^y- z&9(URcdO^IyHodmEL-)N!&9t&A0M~*ppUozcGCHWdF}QlmP2z&V(As-xKmeybqcvN z4XEzeyS1)E$1E%$kP?4D;{AF|V2h6y8%j-Cpe+#u#6@R1#6kfQND5%j?}`0O3f7~F&sSA}cc{x|2N6-N4wCj_xk&%xQwE#Z7LbhrtMF@}eLPV#| z`446AB>EIy z4K_aT{uJcl!i^+Fmk^KPPjYFEXQKT+f4+Qx8%Se``2zlph;=5iY4o2J=}mT@GH+(Q z_yIg4#{)hEXWo2dRYQ~;P zl(<@U$LFBwo(FOgOY1!5seqy56@b!j*IX|t3`MOM^)uwkiOd&pG!G<1l^{%Z2m?$14u<9-Bw zALT}bHmu7%SOLLUU#G>-k)j+$dQydZv3*{iZ4zcQN?fmw)kRTfT6@#*O+)86aiE-0 z0qaA>o}hkByIOnW7g%d=I}>1@TF)!G*5_CF=jNbug6hUE!-fi!?J!& z)_3Lc0|gi`tmbn~k@M?Z%sPxpr2unt;J!I29O$(cNCme;@9@2Vx6JesyTzuLSF?^; zCYaR!wM4k(rO2KF=uKdZ4Yqsv#}qB76xvN<|NhW)j7pRO;4RS`{zg zx!ihrtBRt>3>;ZHY@Y6r_Xc5Pi1JR-tefq1=^cY(?c4UN1H>BP*7s|MKG&Tdg~Tn- zSGp1CZyG3azt6cmsr3|Y`?Ot}X)UWTr}XfU*;Vd+=L>CDTm5L&ta(uZ$iXP{IwKIss_~N6J^!on(2rHTzOT2%PBFVINIR^5f51Q+3gIM7& zDdNBlyMh3Iuqekn(k_nID`9wzylHMviV6ZtzoQfc6ngQ~BXT&_ScNZ5ElCv?8)|D; z=O3PQ`*^sfRq=xlMb=enXIPnGHlUNL4{K1?rutA}0Bux>Sn7-cd0X7y=Plgo5|LqF#qX%e8OLFXzC9>#mi@mD_3jY~btmy+KIJ2YhLMdtgVN?Um*E zAtH*;VIH7ru78oHw_LsmtV-y4s|w56NUiWYdfC1itwyvjudJs1=wqtK<-IHGmPV5< z|5LlH8}(pU&p4OUSj%Wy z``)b~qfmTpmd0}Xv>fGwT{o<*R{xmNC<;M0Kjt59v*@Q^-M+M-M)rS;{aQm0J%mty z5O~;3RJL^UQND`;T=pJik&TN#d~~Qn0mn-IIPZ+BTPV?Bb;H;IJdc#(8r(%=_``s> zKWJEj=YzM-qLe_x4>QJaQK3CWMur%VvM=wULjNuWQir>imWjM2D@TSZ#iwE(1m>S2 zYn{J3c9}ODW@-k0e>0S4rFF-`<4GfN9elz^S99}5#zcSb8IIj;MHl=R{>rzE16%?F zdPvIk!&!@B63{c+%D4ZuPeqPZV>mK1vf>A%@PFKEZokO}Znafg3bHgTXug_ZLd!`- zmWt_w)=a;wxZb}frV!-iM??bFW-Ec`)-|eCb{g|Sl3&5=12`hwwNOlk{GX8T{UZfz zc$=|J;hIUqaJ0#~divjpAVu6&!ll<{{5n@{E2Y=K)5}V)vejig)=e62mw`TbJvPCU z(*@TB64x%p08ezGv_~J<@-5f3FW&|VD!v5RR*P#3877rTP+e}|D_?rs9B@RPDjWFt z0cvH<`7fh$C?#if!2SX4F>reOpIzXb>buTmdQcA83ToBTi5y1qa9Z|kPCe&b#`O-( z+1XjZ9@V{!#`vsVpJ4tbB@YE|xNEozYEMr!W`T)0@R~#WXSx(HFJ1#lq$0RXZ?dWz zSbsh@cP-k+G}m8@y2?D3}mDHJ(!nL3H^La8!P?(`MD(segTZ zJEAZCo8sJle8Y3JL+nnNNv;|Zu^s_v;j2<#k1M;+&mn^eijjB_XFK6E)=OA4m6P{1 zF6uzn#h<~^$6$SVT(AeGrdmSr8P3qS{U&Wj4kx-keyCCp`l9Wu=o}0Tab=v;BzI-0 z0O}6#gx^r4|B6BYd+bC4WsY0e4NE(spV1cPbMxTa^e)y)l1|87oGoI$M)d4IinvH& zb+Rx<7uy5VS#m4U_3dE_Xr2?4Q{Hz>`E3nKf9u-K@@fqx<48$zWf}qk!X|Te62r!5 z6EL-}YbR0sUt1SH&N?j3_grvS32eT`89M?jT?ZO?`8(ibi$Y*ueW#jtarWj@VnOD= zN|A19C)BZQc-R9K7s$8@OrGP+_BWj5pS?AVooz#~53b3fF)@d@WFq4Q?Y(Ze7gx=X zUVAv8<|TLjFk>ZPZg7?kvnwK&)v>w(?{Hd$UYP{JU6}uGk_O{mBgZ)Vpu}NPZsuUHj|2Z(7!Axea0g9&>h? z(N%zv=ilTy*DXApDQEiLq*h#&g@F+Bs8^8xeed}@u3tPH!Z`E+*#}7n#G@bJO^JV> zTkFcdT|}Q-oLy5YzQntk?jXf2nqr`JQ*Cbn2H^YyWT_KwKU;jD8cGVf*+psY5jzPg zUmQOm*To+o!tKQpE8HEy;Z7f{7=TDCJ|O=7Ai4l%Ss(ansEBydyXV6bT;1CHWhf%s z4bhi=+Lr6N)bmR`dE?R>XA~8>TF=`F+G(sBvYH$p33R5DtI|6KL?AP$Js=*Y_h+sj zid8j=BKfzzRmMr1@x?E+g9EcX#uYxM_nPURT@xzztb5()yKTq*$J|@3((9!M8L=f% z6R>%J+qSV5QIl)A%l)Fr_m3W{Zko_TdoSQl8N`eR;!qk`-*JCHT}9KzYY08HxK2f! zTQ5q(jmu&9d00|hK-ep@dNOJ@>G0Lp`zwH_u~MSjBI@1%inif%Sfs7C2eG~>7ISB^ ze}~A$Cl~ahcP<^TMqeRVhZF&72oD{87;x*>{PL{AdY{|o`k=2RY=jYwg>RNZJ_PwC ze0Fd^E;`-?2M+pJGXnvyhc9)8a_QV9cBh+;bsl=g(ClqDQ;l`(3GP~j1kab=Kki6< z|7@btrSuI}*>y~@6=GMpfN_tDzjeDtLT8isztp&$d1CkZ+1VW00Iq)bE%t0ykA+=a zY4rV@yEez*5#=9wTnl=<#zx~Y0$p++Q*Ztch)&M3MWxpcYWrycVos*UtfkYe@C&YC zL;+X-q>T*Ekf>0>nOTjm&#xS@D_*j-3IZ_)xJNbe=Ez=Z+yTD!bbbz@0*c(Ah@Kxg z1sLgRSohC>;#;0x z5%|5Df4{J0%OU>@|31_H_iG=&zW9CK=YQVxN~HVuHUIt6ndN(^&F%Q_S1zT2_3`gt zHviwP5l{KwuiThv{D0<_-ci?h9Fng*Pi(WF#$Rby(14~s6z_cZKTq54) zxZUo(dXB96pKA>FB*jzy{b_hm>q^=7?f>=tK*stO9`U=yM?A%MrL+7G=DE=S%uv;S zvg+^qzYo6kKi|7CuLpkrfq7!%XLBYtX7_(C7f<=m3~kKu?}i~?AZ_61H?6WU)8fDX zuyNb}zVS*XLG*oG%?Y^q-Y>lF$eN4bOjFwHvna z(|$??%J%@|;h8^WBRne;k*_E^ckz^faVwP9?E4gTWaI482WdL9VSRs{Ll*{-#jN(8 zef*U!ZGrap;3sjHHOW9-@M>;i1EPQa&&6NDBjC38_7zP_8jnnhx6QZr4gTRgWm6qE z;ybTje7FEVQam`#p&4YD&gOUwCGNxCA5iY9^j2-NPfqmx63(cCZJ(~zK#&WIY%4lI z&(bMGu|xAYE#zc+5wUWp)i~bCCSV`dvo3geY`a175URP0Z+{ykK@efFx1RQ$rs_BT&?f^ z3oCv0E?D=LV}5-8pTA<;|NTfPfv8=0zi-#v@YMz74~gSkjk-(a$bnd4e5Rvw!JYDF z3O5;ghl2b!sB%d;tt=*3!XxlocQi?2Ai;4|< z$Z76Su&G&R%1S_Awl-5q)ca)Ur?DC`x!Y>KURpOi<$;jUNNW72yBwDSnKW)0kGXq zN7k{5QYAN)A4y)24?z-@1jR}F?=ud^RlKT&FFv_wm${7BPW%TWt8{bvbECLd4{I_* zqMFT_SLqg_jX2iTn5a8Ws#t}D+vz0#OY(K)?Oaizv3$YYjgc)`<(i< z3789wHIIjMsOIR2GZ(-iF0*qfjG;eZ`zbiPPd}syBg=R9xKq$ETy|Dp<5fL({Fsii zGykA^06j1Q+Y?EKr*0J=(|&5X&$7)1eTWHWvOEFCe=J39x?AO6XI3;aXj2gyTey)A zy2!k{Bij~D8~6L_)NMP14h33Ta+2IwopWkUTRy?X6P(_@IEol4S7|uf!DWl?mJmKe zLwF`qI9x>H2Y5Y#BBHX@VKzi*m%{m9X61i933L5I$e_n~n#H>*OQ-Bxjs@o4mjlus zgKScbfWl?HkFc0$38uT#;W9C5kcpLi-6!qeJ=~-M1e%rPKg`(@bb{n94*L}Ps(6l! zD0@!CGSHY>MI3{}Rg`8zycxD#M@D|}aQ|c9HVvQTJ^WZhp+Ai*^W3ke+6bMEt*9g2PL{OTnxab0Y$l?<5j^ zX{$XGKb`(0KCDVd9UeKce!6#GoTd%&Z1@w%p#ybZ1IkH?J`wvwG(kQwQ7GiKW`Il^ zqQFbB5ddqTShJEiw;m$ey)cV`YvtL<&GPHp>g-B6aufmoCcpW*#OnSj_T^ zN?#CzvZGki$A1W(;Vqx<+mAUjkI00+jfh)pAl8Ux_r_DZU9)ZxDzmdw7FH)2mCVW0CPqC@vA3zt&5~Dje_Gj3<9joN zg#7l&4Oep5&4zn$oK#xNNXjgZw$_rdEa}{TLT!$>F1XV6be)%va2%2aXBm~st|1z5 zXE#Fj|G3jD8(ub^;upGCM(7E8hgV#E?_bn0`+H}60;p);)&2c8(6QR_q4e0iD%odI z=M~Vpb+PzC_1A{#q;oO%GieU&9;?d1W92grN^`IG+9kl1=CF@$E^+s3(>Xuin&Qg| z_bO=fE1~Ioe>8XyBQ)^EZb(LaQS!}#U4NLlDV3`2BVIH$d>x0SsXWZAz(hA<=ZdEj8X_kpo|y z-%dX|`7p429V;9_>{i{Al3-bIS=u7Ux(#h!Q&pgY+4Yx-e2-rO=IZN67~*f+vzHnS zc)?*y=%#mz`5h<1>)bA-iW+Emg6yvkIV;G5Tb3e5P|D`Bt6w`lC_q&QG5Va}2#17h z`Fl^D9EOyMxMQc}6@6{)2?cX~8>Lrgf+%U6tv+qVO;+?k*XX*bJWPRWC_QF%VQdW6 zvNRse#9yR&PHCE^c9n7Znxla6ub~cz?jdMmijLVO(E6f<25rmLz0dc06HpVYu^KS98B;3q@G(aEb6ld$Q#_(M zHvdAT`chNiss04l%Cv%xlV`8rXmAPe!>vcbd(-$X(-L1D2wTiUkl~To6g7L)X_EvR z`aUa_e!2W6=`>B98L%zNL& zlqaf9U)y2dL>8`7_Vvk*gU*$^k`%<2O#3Q@tCwM2hm?dP(#;*etrDwaM$W4dQ+*Ph zkG%}9WBWc@r}z2g5-lpPAJ&(iI7^3vi@(kG(2Gnu==d$AxUs3NnpSST!-=Upo;*2M zk@1XRB5eU}_a${Inlin*@?LJ>h$-WoI23*lFU3p{crJd=3{s^4{q3@vQP z9A+Rl+)D3eRS0OpQ^Y#v5Rrh+$S$g>#HsmE8R<#oDCmRE!rMhZA04`krmeB_dgNyd z@U=rI{tG?5%uov?XGTF$;a2_iPjz%bqYF1Oz0GH;_ms|Dzu3Ppv*4 zt9a_@9-~X|u8)>EQa(Q+6a%nuQ1t+LUbP}cw1Z({_=pUf_Qj981(=gdB{Fl*Cn`>J zp3(OpvORcj6(`A65g9N-wS170i^NzUq4Fgm-;d)$u;S#AM8Xr$=No#|{AdMkxXX=v zhhB_jQeD80?|I(TA?Te8nnMZgjE{-x>t8EKbqTGppH)v!#?j28{E{5ccO)dSF?VsEcr?M`JFw zNnZvUy9x(Xf3}51h~e_!GSS8o1*vlPhUQq8=U_rq#Llq2-NO%=)`(*7AIAs+mU>Qk z-Fm6pc1BjZ|7n>$EuxzEw>^q0QIw7Yxu6fPk*_&5&^Mi75yrtmHHj2JZeI-QfhBZu zGvp6AIHIU(7JqMPpjY+>a|tiR-g5UHJ8XD#_>+s3HPhOIK4$;4>)bbJQVLg_I>-O2 zX<0^dQuobjK9{Nq3%d7CS_$!F6_&;K9IDs55Sw@u=%4&}{rRC4Yj|GVIQOEY5>C2` zIYXz5YrS}0B6vnjLvdGjLf4^3Aetm?1-r>7Robi;&y2I_uKX^cpQ|x;+hIQKZ?K0tqi z)Hri?Lb!{{T%baFsKG(ou5v)g!!;t#K=PeM8k|Y@<%9$V@vjpEUoR^Zg#9{b?Ejup zg`Uq7+jP}l=*;F0n56ECU6DxM`%ycO!0d-ucw=wH=)smBCMvu?bPD1*wM=ThBhGHFvBk05eob8Wpk)DcP^m%Zt;JXXZcYI($lmVO{Em z>bjOBkFdRvchXiL%9}vLQY*i$DSu$?>zc$3OI1Q59WAPJ=M3{x6eKlnr38x{jhz zs=KamCOV>L<+wKni%F6m>a1O@YGa^1JLXlvB0|y!4SRqhETI=0{>HqytH=8G!ME-) z>ouOh^{h$(i*H0$;p3t8J_3erKO{xMBK)vn-yVU-vng>m(tcS9{U{(THxXW%PHvLa zpScrq&f@j6ya7t<{QA;|g5EMbN7oU`1wfMC46(>xo#5&HnIP7WOMa`0kM*drPL)dG zUBO^@OahOLZo!UwfV^ui*9ZEpN_;KgS32l_fhPc;{t$#tlRbJfW4A67-hVi7vr!(& zs@fYbRCzK#kQ$^T)N7d8}nAQ@c5Hso(-FwkLbw5JyD0djz zq#h?%*+H#R^Y&v6RkKb-#-_&tltSLyI?wikfGuiCW!F7FGq`Z=$D`Y!nkYCr5hpKD zZb-JS#hy*P!`-iw&3P+_JN)W6^pB^uk7viqjJYxh`~Dn~8*|OU-~ZhgyQqc5UNik; z>Z+x!KGP>HRmUKNJHdpHz2`w5yR$q&YVvrSQWiL!ZC>=)9vwZdOJ7qDOsH)#`aVb> z$K@sElCelTZ>rM83r&Ivl>8RkocqLXtUv`#o&AIY(-iXvGX6^ir{tnNA~?m$sHd!X z&oci$=hJ3tm4w}k5LI-YkZS+-FHCCS3;&-p-__-DN>VMUmFb3uRi+$ve&syK_oHP2 zh$uG2(;WD|&qi`pGg*^sZa0?`=3~^|=QlrjQBZpW4_&}9gVAs#)uu9jazbfAe(!HA zyJ7#K0bz;pl{JgfZ4dfztMHzS%`4@isNw z03~v>Nkfvn0;;;M`sCF4&Or_)EQFMWTQIG&@Aq`8^~#4&mz%lvWm~m>Vnv90pt>H~ zlzN(W%Qlz-{x(!b$Qd_RgnEyph##4&> zNikMf+5-Qz6+_;2oW_@d;{>J6i^`w9&>JpP-7^Nu(`=Xn%1W&#!@_!wiOcG;olC*X z#`i%RL79PQ3C*vPn=I7^!X)VdNs#EwOfb&7Q zX7oEm_K4|}c4KcS`hX!9A2vCRvRTp1hN222Sk?QirV}X!7KJ@P?UKk!vcbMePNvc| zxby@#T5(GLT>;*84)NC3xH1)xGhGe@e}3kxYfQ)rDxLz`p&L9oVN~4#tXryli4R{s zlb1+;ALc$D+!^xmtrVCd9~0}^_yc}*fFP@aef77OFod;)j+M6!p=nwl=)ax z*eWn6De)9Q9_&T8+2^^a9+S*UOQj%0e>(n&^(6h!v{3zvv}RZT_&juUgFRsMU z`wL7ld5Fa!0jz6Jb&Ya4E9_RezfAzWMT|`kaIAGsY@##w9FZOQd|7hr58X>n+oxWP-tHogf#dMB{Z)V!Z=%HjQk-Ex6V$j8h0~Ib8vSG*c#$J z%uu05ehd~dSlQ9*-lIRKpi?&y1*fOv?Da~>6K^v#t}NQy{3MDpCu{WaMu5`WZ@wNM zcIU(Eg9h-QkJ1z#IbeHP%^jwkZU`p>;}{~T-@xF6N~GQ{8akIdWb>{E)&Mn5)pVoQ z@%u`iHMLf2E@kw&4Z6+NtE?d$2@pbEd~SGNo@6cK^|J&*P`iT`e5q`xqgGcpEFtE{ z9p&zGTfdgraDXB5*~e|WWy49fHPF|?1W+OqjXVJVgLZg{J~ci)htZDym4Uf{gP{Rw zb*G9EUxzaSftFK`zorj&z1iMC2fMeX|Ltkr2YyYY| z?%sv9@#5rMTSV8rZdSrMZZY@G>r84hLKfya2z>{kjG>v<>7X_=&)u(+|FXOskyqqr z34Ba?n6VZDCI(xa=_{*L!kHD+nma8QxLzWmizc(ZE-T=MCj5;?w-c`W_6}hP2-$8} z`StRAC0+H5*jE{g(RqboTex0sDB!vc`Mm>;}2{ z+1wUV#?yBUnXahGpGu`b(r9JRNlZ$+)6iMFYRH+iCY@(MLC0C^mir; z`_d+;{eP)nb!C5v|DhL=ZCNq#f;k3>iz@eMqo4G*O|`4}JHS**%%(g8sN#X(XqVWt zX`x4eyY)SQ0z=$w&iXK#YdO_>s7A;wM5^C9de0SBGSsO63f|uN*H>hF?&nX$sL$T4 zo*H1*TVd1PySB*NOrJ7^)>POD6-)~K^|%XSA-XEzW1C1xyf~FJx&e-B$Wu`zoR758 zQk+npCg%%;@O`_D+lK;`vc{&?R$4TSf~)ZuN6e15S)i>u1ew;HHGRxF;}skoG!b1w z!g`Q|qn}+S5Yw}yUnolr!Ht2l8%vswN%`vcOd{gvEF%tmXL?lJXIAyXjGd03Wc88q z6f|js`S*Af9R1h(i1F1L9MOj^s8Z7=#o&64c5lZc7am%bdcvC3j_ny2cYTrmjl17) zcNmf-x#6wJaJ~`_an)SH{Rz)~Gaa#+@7QqHj8pQ{=7pBdAM%wxC9*74Gb9bf196%K zLnj?<&pJN#y%n01l~QSDQs)_Zl2(4hhS4{jbCIcn>4B}oNbMGiYxvw5m`){oM&qAr zH-V$Y0V=25tdGLm5&1Z~5C<5vA{`?AGQx=j;p|(%C(MqibB-RppT0t-*S<1Hb}20D z*~7Q=ZHuCe8Y_MBIVZ$hoXhF@9@_`>A8}g=;0V1AmIG&+eCMqDkx_uIecYxOKO@8tgGe>ccK` zbZAPZyll+n^q>K@7X}BkFgA9)9j8a~mK6?6e+(GJ?3=*CQr{dD1l*!G@w!bNTMx;Q zYN@6N>nCuc8yLxn6#re22ZNb!_z|d!C++JkX=KlpQC8CP_q!&ihiZ*DAOCqVI@Zs% z4T&qU(XCyzNs#MrTK(nYnQO6^tAnPUsN;U`6wt>NT>+0`_!vnT?}ZSsi6>NDI`>)# z)_C%=@wJWt#}#BojP6DH)&7vi-&udwMJ+>_zDx!#0~IX8oZ0oA-y}-Gf+yA z8GiZQC5L;_0zu3F(bu=_VsSS+!%s8=*D_4MY1#xU8^ug#c z9C)^4k;)TK%3X*ptr1DzH3CF@81D}Xn>tR!VyvfAh+7IM!Wb7O)^>d_42SQdil_y4 z*YLBS5Uw7PzEv2b?h9=Cn5uw~a;LKU*um0p`S{Z&iR2U$3l&dLx=`9;VDSXu{q_iY zGy3_JKZJ;cVCVbA51Eam8Q5{|#U0j9na|no$tc1ESIi$>-WD9T-}Nvx$FTpDcx%-m zO8rP6u)RRK+A*h>mM`(i&|9d~$jT=)mm%VT0-4ubZ{gCr1?X5s-w_{}$sE zRZ;>hNF5-)sG!v{rH6RUH~pfJz+{h!>Lw2@-!Ek+6U{7Z?!(YPr?p3D#1$ZmM1uLy z>4qqmI}|KjB=Le*k5Ig2w!I%a)@|uo$)Ph}DsD238>>1O_DZ}O+XlY$VgkMOb7Y|T z%AZ+$QZ=H&pbN8#x5QUp#l1Q6eGE8f6#x4Xqxqw%PVWhEUDks^w(*oDGKa2pXiQ)u zYxZ5L)aDSsbBH<~wB}f(zWi7g@%RBMnErML9%~AP5N-r>K(@drd4HI zW6bfp*0~0=#1BSS2;46%(qibSh5kbzV!O(rZ?~9eRH1U0MJMO#rL$@bk?UN&)5__L zt!X8K_R%?dfss9l6~jjQZ<5b=_pqwgg(oGh+SI#m*t&Sisg6v~{@VY;-g`zhy>;EA zdMq4KM2{i@0+wSz1eB^&8=@kjAib$bjr0;AKvV=21Z;E(y+e?e03nHpg4EChgd`wB zfRF?X5Fmuyjh^Ru&;NeCW887a9q$(l3=*<`d+)W@oNLWlie0_71Gb)v{%}`jno14k zR0@eJ9?c94ZQx4yt$mSMq6nndE~dk$2T-^J3KmlKO(@si7P(?eEHZ6r{o1WZ2)eo7 zj9PV~Z3w9pJ~_Jrx_g5L(}Qh0OS5-uf)0z4>hWIi^-|Zar8ys&#W5Oct}J&io$x`6 zN(tfbLt969Psib-hEUhbIdU$2=bfbVBnB0q!q*DDzo@SJtJAi}SXnmZ%I+m~BxBA_ zdBnq3*PElfNT8ibR$s$Qaq`fj^|>Q~t|RA+C0Bpy@R^8>fu+iNpWV`SaFSwre5EeM z+z$7b#@*4^oZ!P@+O`^Y!MRC`Q!0m#?tFS{sSGD0-Fi}O7#_UzT`(%LDm zr6f+&S+|hvn~q7hE;1Cr^-ndIQu9hNX}eW^h$6*9PCcwXi3pV6zqsm@c3>|lA}co) z^Jk}Hvdbq>!t#SB`PJ=WwD{~;da8F+gc-j{pO6M3qkYzDhvIA&*Sg5EvQVSBNlyK% z3gPP;dlz@_OZ5!$%7FW%n_4eM6giO+hu-(oot)nd@9xdt?{Bz+` z4pGJX$Zg*ZZIO!)lnI9E7wAWG9Qts}H}A??u5ICdr%RVyD~&KMS`h8LqhPeaJG`m} zZ~?-~PEm~CqdJ_$f|k>LqFYyc(Y<1OkHk|9RA4X37Tz14S}tb=^=&IMEqj+6h$J|* ze*o=>Yv*@yS%ZZPdXICr5SBDU#LXN$1a6%-mw!7uqy8wls<@VF2>%C(0U!&m8 z3NYTDndV7bJ|eC_O~+yQ3~Z(PJF+Y)h;F)yjffstFTbo?Cdt~`T>m~9p*5ljr!$P) zOQP}IHzq|!y)o6p8H}p>dT6l0(LY&c4${uVaw|`SB|fzAz*0Um#^rlMG;XlD5D!iNRmnHQ(S zV-7DiSsk~@!KIIF`d8})`0lG<-)7*6r}G2}*4S^7ikrq{caC7njTOxx->{e5=g?T5`O@_|8LayIFr zA*9?k;+J!=iq>D8^WC?6a5>#F(i7M+`gR8Z_eB*o9ad!wFt_9xdQHh$&qZ=e$6Fu8 z)t;-z85Pwqv5^4bUz1(6b&2N&(lXz>4kf=D%?@eVWg7Bhs;X@`u4n6MBXe4w&#pz7 zu;`+En2`*T1f5PiYlC+LiqW>TLjRkt=&WIpZNU>W{Yi^{%oH$0_NQs-f>0_N z&UIGqY`xjl3aK0}9_Nbfew5(PUcF6<%;$?rsJi*2x8=mB4v4%dE%28!%X`{aHGZyH zD`d4KModR#N;W1Yw(OLBE+O`Ie`#Nsr5(3#5KJd5#xgJIzJW*s{xkL*ud&&?nYo{? zxDTJxCjv4QAnc58kl( z_J@Qy?f$DfOS6^Pq0j4?#$v2h>${_S_sP_++oHTnWsh{#8HZIzDQ1tWE%oYtc@8yBe1Y zCr<~A?X!Nr<8nIPQU`uyi63)Jujg^s$MOcOs5+E|o7dJK!sxW^P)&I}=49N(vG*O? zo(|x+nwG7Sm_?sAyrHzJjYQ5<2lO}(q^rB3lv*5aubZwIf}tj-`+YODDC0y#=k=vy z@Wu`{TU4>+I}5Jfh<#iuNTIg+Fg|e5wRpJhhqhax6N}&FO*m;Ov{lkix_9QON68)C zE??sU3FV4u)i$}ORhXv?(8J0hO@~CW*0X8Ca-i0JQAMMxKCa^Etc_@&W>*VIpF1&? z4S?G1%;g=%e{3=5DY>?96&)*`h(Zy*S?9e7$*oQtlI^XB5!RW>1Jp7gU$;h*cE<>A zL?Aq-n&z+U%lsr87RsU#)SaOeEzzw0{P(oJltUSGqic)U`bb~K2Q6r)jiH(cC3XBXBUSV10J9wO!pqg9Juz1j*J&$focP|p1gVsW`Q;qLSSkEp`((p#o}Gb%3u zi}2V6{h(4vEaAtl;Q&8u{2$hDTJdJ3l6(C&Vy;nDxwKr`Um`>Gqh+~EEi`H!hW$Dl=?%C%OIdYj{U-ZYRIMgy8|V#v+_!0TvLpuSsKT4oM`yc zuJX3M(;9z4Uj%wf$CckTc1+d%^CJl*ccc5EdihSoQ2ZHgw%bUR3UXs;cl;oh5#(Xr z8p83Jd>-a{2?P36W?y-^6|XLYQX`#?9=zZR+R!kR{x_h{Rip*$!d^-mFVw~~S<)A# zbyQV_%54vhqA^rVJ(&yWMwcaGrE_B7F zVQh*##Nuq~mSWEt@q&78WH*!Ox|A3zwk8U(o}TOyD5y~%cIxVov|9X_!L ztq;LMB-J?|tLdt>yNoOrAAm|hojgAOOK3DV26dw0+|=pHu&1 zB>hol`647w!LEEb#I&L>-~Hj0HIywHffcA*#H}!CFJArurlW)pX&$r@adJpDYFtwk9T>U59jjAY&A3nM>CJvNFTZYI@BvPN5Bk8W&rQxJ6joYJjIrF5O?bYJHo&!&5K&e z*#zC~M^~%1lQn_LkgM%<-3e(NGtkFBQRKIy*{ms`9D3Q0CPHR##;5;D0khE(CR-_@HOm+HrlcC@(jtX7%gfdO^ zjOF(MS++&(@8wmo$hPAjF;%WSfnA*?qzIKjINFre-jSr$YudjXT7P3>PXc#82@IvC z*>kk7l(=W3OhE%96d_r+REg#8UT@a72g|%^zw*Weq{-5>DD^_G7v-7mj$^HfrRHvS z!MrQ40_A&sdK26_XX7s*QwDG{rTgi*ZNZGA={}8`iC`#3SPaJseGCGGcX}Zi2v5Z; zVVnpyQ?8+rdRNf&!49#}m;2oV+FsbqEZ*Qnbl8wR_}1@>)_N6i)x(S88ulPf-K|Ct z*(O=W-@Z%S-2*ELK}c))kLY&5?Qn0ELPShh(#C#WIx8g~xKNj58hbpIMnbV}p2sPU zP&cY11l10iz-uv1P!4*=TQ+tOb%4{8q-%Ewmy-Par^z7R0JJv>jKF2#yn4;q!CkNS zGAmhF9+UE}W^x%ojpQK3R*?6my0J&%^30|;8TikggcK;~zh4_PsG92a@Vr_S@;_MD zIl_@6MdkGY)2@)7ipt|LX|t}mn=dv@v?u$h294~88WL;{c-#W%19rCU0E6lYzIZT^H54GpRp2AAeAGxHjTD(vx+(&E~3S67`cQ3=0KS zsi;``_0UxJ+(P_hPafo9!;2iRff8K}?rdAv)-X{!naM@7ZHeM*?j3A^ahg*%Um?>% z`BiSzuh(LdfeMm>x4jaibM1AY?Ic9)#$iMt4!Dp$AJ_2exhHFTbUzjsqLo zwSj?-w`~I$*8O7J%1e84%U=GuD6R@!WU>Y{r7yTzJ4&vkKkiLn>^Me<|Ec{x3-|cy z`w;(jAE-8EUir=aJT=v*QGT{1PI)q{Uie2P z-*K^2#R1R*a}?x7V2D{@@)25!XYE_Ie!yfEs)Mb)H3yK1YMZoGgDZt3c+u=khFPgC zu~eaVy?uyXJD{eXVDusVd_2>rF-}UOfpTUQk$S4DM3?kwD<1HA`!xmio*B;T zAkE%e6%*w#Ijmtn2@kN_RW~tM~m8zY_CrcXw3Pabb#C({; zn(0~|5AH`1tUjK9U?=;veqf`HJ7zTPMAQ`4Ne6;hwX|)yRb?h8`9KGcNbr)@? z%Yia`=*SNCM)vY}^UZN;o{f_S_EnObf_43dV9ZxHuGNGN!+ho?Xj1rgcYOSD>H`2S zR9pBQs8PKdS9n6Qp5NevlvdvHw=L;+tNv$ALdd_GpI6{&#Pw?-Rk6PBx*j6m z;+zI@13DxPU!kRvHYzzt)}UUQ!D;x0wnF>=kQD1bF$aPx7w zp+HYS@6Hu%FaU0ZWzFFdGembf?)`sR+g?;`)uepHG7bA?9Yo~&0oZZRWR zZU3QwH}R{+IShcF(hf0P8E!o``cQ0XVCX>9e%bis1TJI)CMLN*{CTg~1oH;F+EmH_ z1O~Aj#*sXDu-O#~FyRk(gVcB#_Od-zi@0iPtBLDyQh7_KCxZwt2;nrAG1+MS_oxTQ zu2KC!`%w~WBsU*|Uy=z6Tzz!`xjm4B;C&e5w$i_XV^YlTchvm~$!c^i>xd668+!#6 z8vxhX_aBA#t#UK?LlX9K#+X#JD=SuJyjHh(cY{BbZ{F?C9QFZyDjJjPVN1OVCL>n` z4T8H?rqxq4;BQnO_b3)r%KK;rYuLdDN?0fpI~CWSR)gii3b%YK)Pr$TZf5XtqT`}h zK2po3BOuLiiw8VqIg?SeZb2|wlKP)K53l#%@tupvcf`rS0{@lmPBpld0oYQo`Bn6- zWi6!~Oa$G6?q%2&_dCa6 z(?9!bdxRCu9M)RfmyS&~a` zpuiyoJ~e|oS=5FLm=MsdYN*aS{F!qSX5`aM_n#?bGn zm$QJ;`R~ljYx>Aeu(MNsN@2H~$GcYBls-$dE3jSuG%K@Hu+e4+x)&07=plVDXG4O0o;kd4ZYIi zu8T_;H>zKs2w8g`vNXYwA2vS$8=l`+J0Khxmse-W1Q{*LPS&(?qkde?@dEUL-|8XE zYcH9HJUCTHmUoP@iSL+Z|RFF$x{{MvEZ0Fl|?6jd2~4?;zz1S#_JZ9CIc-Y<@zz5mqh1^@u&hw*Fh`O=O#gXz`LK>Uo2Fi_vp(E*`yhgEh zb@xPfY*+zvZecwNWo8wzOTxh{Yo>u~uLcTVbZqD~&by{ib^=3Qm&=0pc{lgguHP+< z6%tqPNrRY(#mugO34|8koBzr+x z|Cu5RL_q(w`FzUSeW-t%RH2Pv`FWCYFU)ai@^-b3&4wSmNeIn&M7EnxksAqGJLRc+ z1~g5bAjaHf7&c*d+4LL5CEnCT$K_9Pc>=ph-S&n4)7}Gnd%8gv+-+&Cgvp+{boG!E zNEa!&(s!YgCDBPb-pY%JtBx4^AcjWp-~E!kabF0wI^jKJ2sgm3Uj=%a=j*ABrtAGD zA!6_T*BllzH_&!ZPQmofU%woYrUh@{26p#r5uL)Tb&%HB$)0|@nxwl0 z+|B=>e(bfK{}}??^h5nWztxeASu2p*Y-HV=Hf;?0{ht$FzrX%#0`Z@*wEwr~)xdn> z?@#djH>&@8&~wwql;ZC-`QMMQKPdRWi*#q~z`v*cCYw6&4Ci5s{9}cGDZKi-V_*zae&De&_mU2XQ~gzT^Vr0vsr8=-FBY?wouAJ0D{^v^Ts3OS}l zn+{}sY3WS}UHt$?{JQ0B>b`4<+M6=~@<03*OdqUi5!LgwvGPjhdH8(NjGtzb}S8mpL&=fw~7k;P{(z=T3?e znCATFga42TvinQ1>&l5b-``zIN5EK0cIwl0e*zpXdX)w;)PFYJsMKGIJ^z`{Btz?j z5f=ZQo&4v;{(m`#JIZ%r$**PC9N_c$(s&k)Lb3|KER&0@%4N!lobF4zydlO5g+9aR zdlE*Ic{(~}&%fdA|}@P+F^&;K=Y z{J-A>OY*;q@V|@j>!|!c+zFuqHJ)S7E&y!`3v_6h1@2+4#YfLKaNfjsZ{nLIoGCC9db(#e_r;@L&?buehzL8JzI;7)T( zSH_ytJEqRro6G$74K8lJ6kvN%Qr&kDC~!5`uPnhPkr=Q*}?K&VAcI5=C{E* zc%vsdx&gMEfSTqPWw(LPnhSH;YP&kJ+p^E>9?II* z^wfAMy+a^6ul*xK518(rqd-ZgGp$XP#}!uA1)gdr4l1nl$mU%RznOP8J1@_j7crUY z0YCdyUsH;Wi;UKB1h3Wp&kG|2fCid)xnVG;(a@2)&U^f;>-^Uu{4MvH{f8rvu$wG} zQsVy9W+~k3^Q8|o&Qh?=j~pFSfQo+#(7;FmG+jrONO5}^p8tSZTXyG*lQwU5r_XfH z@z^K9SO0aT?zetU+x88NPa3rLxlG#eYfm0so+ZMcT!5*r|15y{hffLW@k5B%b*Cs1 zc;EKg!5O&aE_eDfo9WHk^+mB?v?xPynVxfI@2)iZ;$Kq0)5Bu+CJ-Rft5f+ zMd{&>QyOtV_@@mMG?VVFGtlr@wQsLmlxPP&SKii>&M5=k*~yOGK+sxoH@bI*g3V9X zJpT3Z(xesreD^{XvzjtVu)A-Gc9*D?#`52YDfxfEyC=%qB+yrSxUo`NGjRWMHIG&F zI?{Xo`*FY}tW@aLNIAn;=< zcs*b?fZH%oN?HrFu0GvQqRNwq@^-k#K*!jXBi3OThrlwlizpIV#HW*EU73xJJvlOY z`b4I`bh2__)X=+x1iF2LTQjgNOa|+|LM3&OV!>89C$Rg_$F{eLynkF*z&3+RgHxO} zFi~oWj{Z{%&!2blnH$ZN2vwzj*#Q>TSz=ewsc*OR_1SjmDzMnVv9Ct!zAC15m%kp@ zPaJxp9W>%=mZAcA(4!PPdGMK|lN0IFPc*fy*;iWnj0c{J6Pgk!YBH|%R`DUiS(Pjv zoWELD_=9Ife>7V&KRHCReWhU_r^k`PuANoO_tQA;kP^FBb@>JZKF5(|jk7^KxL8qDiS#c9YbUeA!{ zRclvNR6NX6gA9B)lqhG;#PS=gBO3&Rfal=B`IS{6@zgB>!YN0tL?r7;#o%WRwRs=J zlmiMbglfu;RY34PI1SeYbK})pKqN%X9^CYH6H=xh%hw>P4F9;>p z@vig-ka-cc;ip?s`;wQ4nh=alAakuMR?#?=A3B zGOoE^{+!P5RkTaF;4?YYD)QfpZ`o-NkehVX)w(~L@!~ZD=qpx~K4c3t2 z>P9CW71r`@%vg*;Q>x{jjo&>xTxd*8LQeXeHYx7^Selcq8%e{jnRcSSz%%BqT)1u6 zFvHPVe`wX)yi>LRv~_8cNC3@oz3-Xb5x0e;`G&cXP@1q#s-@oy*)vGcp04Kn$V$CA z+jQ~W$^0amKJG*D3WoLcXx`2K8P$WknWFqh0mvw!YFDBPaF|?qLmI&qd z66)_;HJnrr1s;|VslbI6YmdkSa#ke7KLV*>VLa)3!IB8>1G-aAVMF&nnWARVs_!*I zCff}RHPkivAR2HVl-30*SpRrn{Js37L8gFo1wYn(-n#Uf+q<+7?T0Bdr!fw6)VT&4 zaQRaNx^Zs<88K*sLNn@F;R7Lq5n~O+R22`g-WgSOO?Y7+1m#ehD&VKf@9QO`>Pf>- zpD5wSacY5|iB?`b?%A}?>3gpN$`V*(dQxg-`1#mCE?Ky}E!S2Js<({}(8>f0Y>>g1 zs%K-hI6er6s7t7wz0o4@_U-xee>j9!x!OpU(Y^dyq-bTk%YZ!;Y&d)}+_NS~S({83@eU*B-qb+@5^3sEfR#|}2p+Ea9Zr$@CKQb!*Bk5~t z+?1kM&-Wv%vYX{8IHjoaPQE;&MXt z*rH`7wU+h#ySOaAtz067+tnC1%-G{|=3bdY*w4eIZ7s%mgZ8I_@WHb$o!WsHm@8rl zl|5iMXMV@w2~g%t?#(y!ss8U}QuFms!p?&+9_uYmc3&8OSUs(L2CgvF&__81`xAPR zG^FO8nu3)HqIVt;jdfgp@djL3QYc+NUxK$`*w)CtfA?&${Fn-2Ip@YZH_ig+eNsK1Wx0I1egLM7 ztlbFs68E=b0e{5t{h8j3Y}N`F1mY^cL`#Hb4oSDx&6A1vdIIW@>HwGPxcfH`e&>qfHcFp6=X z63oRW?XjRQ-KsGPuggo<4#^|y&GZ#Y&r{I#gx%trUv8ypHzp)kI?{qPe+G=LEHaks z3yrEHra{=1jKlenmL@^A5nXsOSVr8U3IPlQayCV+@3?@u+F2){u2iGJMQWP13; zpH2D+6(Ywz1dP>^v;n2~j;wIab$z(1k~*J$o}0YBv>qu<;y6pwsqhRpkuqEHXDk@7 zE9(Fz@y7<U4vkNS?@t$okQ2C^IG(iM5YZ$x#^y}8unj4}|UCqejG=kEWOpUY5* zFE)+)^P)%vbh<|ioVbVU6K1xYu#4MzLspm6hG@sE3W`mbRW3@m#stdZHrssT@^7bM zuGK4m*E-jzlD9n8sCSf7{3+nmr-pN-3pzk?c?cNW@o_+B>+06{<90z`&sf%Q`4&9eJxldwcH`7FzzOg8x%kUfr6lOo{(TQ+Kl=X_ zP7^@#!dcor-5xh-g-kpUM3Ma@Vux7xtFUO3Obms<&6J3BA{S zba2L&oBPZ=#y~n}u`*!Zh&^e=(yemjGcnQ(^?%?7Fy>!+1!S#h>VB=SBy<|;7dv4a zxtxak3#2KA$yOz4DZ5*I z`_{y>9s5qKZhj1OWsVJuai!m@f*N7`wqg9A8#TbS7%BVaFk-+6&|>$HlaxdhPhcpi z1zh&jxo_3lpn_oHLuUuik!H>>BZT$guBslCx1;xQk5+{bKKhlrs*7s}=cuIg<`^_~=T>T&-;A^73TSK(fTu#N2G!gKdfJoDDUH=xqk_X3H+9Zq z#gv?EsG{S~X~*q?kLUG-lSJt%&dy96=jn^6Js?Sp=8^$*ry3^^yG;^0Z1|z7N|}^; zX$~V&b5eZVwn};{#=|UkcQxuC&8&Zx`(hz|9#{dTI(Aqk=cfm1J0AKum6b38dSa2& zBsBc$DE-S$0&pvNJ;xRK3^$$B=fgx6Le?jUUX6h~gClEz8vg6HVQFM~@aoWuIeuh% z=*s{@-vFdn(MiMPl<^=VXYpB_4I3EYz z5`kZDBBA=>NAv6bvdVvyLATir?h@KsWo%@0w5e|ZuqSWFW1^Xd&U<#PE%%n~C6zzS zEt(uGr_24|znrrsF9Rcxb7Nhbtbe$1K;|+wGV9s?B%DdX#$FWUe)*hq~AKvs{|Bg#Bv~@9qa6r-SGF zi5Fru%AVZA3T&0#RbU0nx54b*+kk7@W)}YPgR`v$boxMfJqvEG{_xBq{HP}X6Swm| zbgEl1R!W7+U-tRp)W-`&-nOKulHVmbCdga4H@%W{YR*D}%q zQ3Tcbl|waBXgfvlQ$N{X({*nt>t2R+{g?5{^~<_$J8fdZkn+Rh)gSP81J=K{mHjw) zJNj8rcyYsY0yq1a^a%)-w?_9kM=f3H4tA017lI}e@QPamcB@W{iS5A49z@8#RJ*@Ujh=i*IBI3bVftVf{eYv~69bUX6XQ&L>T)m&UDF#a*)ZzL&>=;^;GaH)^n`yZp(BN4P?dU5Ao zE+O`2Un9*Agn_Y5kt@$GakMxhsK(9bg(OsBl5}|d5K29@;HvaK@dIPS)%Y6M|6YwF zN1xN6AAvP@>dMXo!(J6(a!Dpp2V@_hwpk`L?<9zLPX4$yR{M+r3a`mXX?X1e^v^&c zg2=@guKU#oKc74eJDOK~ZZwSS2)Tdry#nW+C1%VtPD@?0Y>r0V zNx-kJl3uLHuyu!?+cXJuq^VI+_jdaa;X|4i-FSx2X&WK>g6}dboHpz)PUEI=v|kLt zv)dTr2#5r+$VRO>kl(z zNSf;&oC94I1UTuhTgO+?mb)Rhra@*p3`B-^q9A^LiHO9xwXisC+*pO|AY&M-_r+Ia zGJl)p!|0|`Da}VoGQ1Wi6vo}pqbz~;^0TjBChpnSljAJvNeQIb*jLypv)t!HrUS_CMZ(y+*4>Ch0c~nP zTPX-w-l2NT^tp}V5!A8T%aorYr&HimKf|k2E8q3YQWWs31HLmO{ixTb(atfwrCl7f zH~dE-X=wwI+K#@UoijI?Z!}S~x0hG>P{e~LdE;ZOLJ}Z5lAeZbPX%>UD$wF}v^{0f z>JL(j@28*Zc>hi2KL*c1&?Zbom=egkQVHijl{mw4PzwH1@WKT*_gxkQjr_yUX)|J@ z0PlGbU?VqW7s4=LHv$cE%2wsc6&4)R6OL1#2B{wQ5r*pq-NJ!fKAq$*&yWSjvl1pn}>XmonkIH zH77n$`lfq3fQEm7RRnO=XkUoMCLYDXT6!EVAbTOibwycIq#|%FMz@u^A$mhM_>>W( zFaE5@`XB5s#+j|(#Ba|spj0&x;EprK1eP2VR8GOOh1Z#ltQx;L!w8zJS#FA%Ev(Is zIHCuBc+*A71{xv0lgUBYKaC8+HP6SKG; zv?!rlWs0ZaE<5)8c>jXe7(tWiJ(|bu#7HN(k&}48mj67`RtZZ14^yYN9l76C`Qgda+V+Ti*P3wzj?@(bEaYs6Et6Gv`Wk3zl4s_E> zhc;6fKZl#K@M>3O(4u%H5b=H&IBWhnGsf30llncVEC^*3K5g$sDdV2?p{}QKY+ci})u{aNGOva~PRkO!C?kwdi~)KHoqlGAhts06Uhc1ZS`8G8o4PyfBV*I->(H?AQm6rdD1i$aZ0+?z5!9ztU`ua4 z;iG*~VZZmBl5TYTN41&T;4TgF%$P3>>xB#!xU^r{O3sNpc&;b5P4W;`Lv5@!s_7_k zaIo%%Fy#Y%a+TvfVL#AMz`ti>&gyu5&jH|u*|9&2!iOLO$e6&4w+O@o3^saKg`E<6 zvV%i?2cG=GOt0E^KLhlv8a1`AuYYe_ambbQ7)qxD?i57&$5owxyM#>*oasxqX-M*H z*k2vQqaU!cH&~xoB^Pp zSI&{B^LppFw0`GO8B-}m74m?>{ktqgtJCo50cogST(J3Cg44(?HgRdh_r`Ozp zDJWLjD4cC(2X909^JnND1^`3nv5446CSMzPRdOZCb(|{BULD?AYG508B$dJm9w#Td zBI5Lfc)2bGKdULlUZh1yam8DWZwigrc?MQ%o74^>Hf(YR2q%Pf2p zWJu>SSvy!1mv3DUQ0R|ntV1a9?V7CzG9YSsR%j{J=fb75GrfgAW^C_5Vh8pqg;-@> z)LwjZ@a3tl0j{!iHNCI$NEOqJ0?d_cPRQBGdXOPj+hyi9KoS|6Ty#WtkJ2U~QBEe> z+N7xe;}LvzYvasqTPoWnS>bW`wngnb!>K4-cDtxuvXmBVs8!Gh%bgX3o1$3#LH!&w zgxHOVdsVvW!DQmc2ZtmmZ+T(Mcj`^LsFvp;Z5vd}M1jwJdT^!(l~m)sPR;Gp~6Dg-e}r#4Whb zaRGK8Ate0(7>zjrk_m+3sdu4MABc0-6L^m1eaHaZWXa07(o_;QzP_63LBb1AIqg2j zJHFg_*8$iTp1^TA%j%cTg{6doXbhNnPReY&7QnvH12csDf|^S7s{h=Liol7C)k^KY z%2CbmG>sQ(h4p$6abYeaRmo{O)z5`-tPNTXG~3UiZ@jMSGE02%Ms8XfEv&xKmF-Vn zt)(bC^&b?Qz7dBS{82e$0s>c|5HxcS`{$oCtvu^hRW(oX_ z_!%)*|D=0M1juod672%DmCRwNPhBhNp#>D|1#y{hhp=?mMM zZ;eZ17wZLtYIhK-g9XLHN=Yhm;napeLCSgAuD-^|!+zmqqZgKK4XosbRpK&N&K#=L z)(@iJEbRq= z%I2%Aci`=1PYvK%0Q*Ra`pea(EaZ9{1Jz~&rHZmgC;SBoZqW%U5G*G?YA|tuKWxXU zCY5`(&u74ktMv=|1x3$nJpXps;QRM3s>=R&vS0dguL7QQvmXOxz2w$T%~^B)C{nhq zb@h`#Zig!sTLpwKC<3ZY=az}+G-DX5oZTF|Gm<6$N&X@0Wp<;FfxgzY{t^@70^qv% zp*(j5kka}OXWayrz|2sR8Pceu9r$LV_P{kXeUm1kfCXIAK6(&ASKj;Sbuo!l#lo`eNGM&VM-=(=sKT5(s`jVmiIk^g@m_;~xCZ#F5@{-n>?=dVdF zlh6QpSGlt;J&%lkWPVrsfCfPIVC3Pz9Ry%DBuh#g*?HWq(`z{BY)_U01h0W{wm5lv z5V_`!k=igB0(nbT5|Zp;5`Y{v5q=MNsAB65YU5XFB`w&}jhcG*6v6jxW(5bK;z9Sz zwMK3pRpZ)&_?xu}8v=~=$Z5^8Gd(soe=2K1seSjPtI0Y=svdHTcAuBQ1CZP$|>+JY=s@ zY(&sD;Lw_hH8c5C(q*m{H;t}|C=jG@WX{I!CYWsBb?6Z**P6~LYkXS9ywtB%v!3VG z940cXVz=6X4D9W?HM3eD5*drqt*1!uBKVc{XFS*k(<$J141Vm6_~vdoznV#nXSg~y?5o3@EdB7Sisk^p~+8QeZ2 zc99d7s9<+4yPm6x{|f`9R=cndaCt=mnFm%@VbgJKgB&{7MA>u|CjI<$OYvvyfX=Ti zZ~&AYc@iBUq?0T;f(6p2?)6a)$<`a+mGkJo4afaxLq*ep=iQgBxb=>oJr1aW8i-qI zme-_rPqve^amlj%I(PB@G22fy-X=vWRqcrsSkw@}Y-GL>8->Yz#jpiXUnk4kV044= zO|HUGy9p{ysZyH?9F`36YmOK%<2y(fIzH%pCUSKD$CH-K(Ykwbi#_SVjym~)y}rt2 znJyyLId4hI;k` z5ZG3`^s`4v=1+`2>&+ZCrSm;76`n|(VifSr zii3pk8Rc8Zdwx~bX`cK#kl|~zCq>xyuvYIocrL0hI(=>R|MM(o9dJQ5mrSmBPp|8j zg_y7I^O@^9!dD>+PlwX2{ZT?p4wDSI;uWLD%*($IU?8*en4=>V_o3-7ltUGdY7eK?)~fA_06fC2r?~6`t93eFWx|rGn%^snHf02M zbNebupj}}$qy~n!d@8LIs(C^)ol&Zw7oR5b1cM|w1#%J_SkUxtPd7_kv02&B0S1#L zUTizY10>7iySj7geiF}N>NV6`X{u>k_JHkq5xD_0DlZLFu-wOgA|wBlG0snRpa{(& z$ruCw-Eyz_H|jDeQ{*l}(gjjGFr3HKQup_U1m6aHVngIH!8>MwYCSXZhBl96&vwX? zm+22;njDNz6$hGh@T#ydk5tgbz9;)Yd(b8&P>fc3c0bfeK+yB%9G!>y;xW&lel$@s zmdChwi60d&+fg;GH0#Y8ELVD{`RUoU_}x89inEQm+jfc$Wkq@>CpWvB4{bcrQw2yH zZX4N`+qMWwK>M$+nZb{ZXbA%3*L^=eYYr0bOt%TUms4KAYHXuZ>K{pccDT}j6Bt*g7^O9CPBW+g4G{6qo{O9EGe@cz zRql4d(7dxJZI^`zIZVu$DxnE;2Q6+xkKBw zkNs-R-G2sj3>hq@R2zJ~X=0GyY2#)t#nR$qPby2*S-w-StXj_d?6WNgso}S+S!aEr znBgD7PLNamB*$J!4Aq|pzej}qaIKHo7Y?A7*+HCHyZ159$w+zPB6dc%2!Iy;AN>5l z)TJHTb_?mIdf8ZQ0c;sC^MP7bcDSS8!L%D<(WS-gBUUa=-wh;yuU`PzOn3vRvdHlE)TlJwXG z!Cjw!dGeex@2loSk6o<&l5Lm*Y93N%#eVC^h&Xlkh`56j0y%+&y13NCp~Ineu^WUoYK+buP_8<;Pe-){e0j}79eY?MrVTi|KiY_oCC^>Di>lqqwSa{(OvhrXA<}yn!DPQC@S^VCC8<8r zS7b~S#zt!|yqF%Uj1y{A!PO*Ofh(Ab3Dl7 zGBu_UuaHT{X3er6WVIO&@kp!9b#+hSpet)KGg3bZ#!~oTk7mSauI32UZb0;)O8T6R zhcRXMiwkQVx|pBulmu|{75hxcutH)GdHW2M%6%gJ2e97mvc?86z|jd`5EBzqJqtj! z&tvX`(Mf;BX-)90CL2svDuy5sCw8V0doHZ^I*8a{=$0P4{YJ#W4gbFwf zR;b`wyXi3sSGwwHt>qE~s|6g|(3*g(V*n&Y)liF9uY<$dn#FCgG|XiDESRQbCte6y z-6e1oeC{XK$29ex-pzFt;&0yc&vD-+E@5qNR2;tW&QMEqZx(nE5`aBYbsv6w#ivC- zVEw_gVS9roaU^oLq$+4X;DouwZ;&GXW4y14cHD7aL&V#^_96JD$Y;}owb7E0k?>i; zFa6%O_SG2X&>|Jkkp{q|?^gH2xT|NPFVES9$~hfSuzhItxh>|iPe&>Y3;e0qsf$`O z-t{5eSPBjCav32It^GL6Z`;bH)%M8_t9EIT)2keUAW0*zE&jUgXExYOgZRSKg>L(% zWTP_NG~ATFHg4FOG~_e63g?2Fa}vP9D^iH)I-=o?WJm4QWhE<%&sY`}N`_DZ*peh~ zJDVCM%Eoo~r2a5ik#Y~Jc4hF_o3LZ06@dLP{pAd|f0N)@krR-5HbcWdX6j3Wv51(7fjs z?Nxox^hL4h@an5|K-rs>S&$BC26T0f4_8BgO>QOCYiYJNX_F~m8!At_4H<8W@mF6( z0!}6sY-io}xYK{susXh-7gs6;<}<^4tjqM!ZwFv1WkvflrWMRTek-xX4xp-t>d|^_ zxy+x!htA(OB9_b#%qkaFA7!4dbcky~VT_xAM6 zst;7yrBl2#bXKiAVYap2U(-XUs=J_|1-9uigd-M1XP!1YUzC(da24zKTkn}@W31;+ zya-j;I7&bM2^*WPs{`CLJ2|=J;KrA)Km4b&_3-qb-=is6dw>7^Bqw{$+P)C->T$ef zHGSB<@fW_?68-yRZu(m?hJ*#sE?X}=3iaxcin?RF*TxH8^gi+*m#vNe{;l=4Kfm8|KmX@{o$JCCIXOA!v)=Fb=QXzb(kwic z?_Ut%i@Top&#!ae`#zTA`TAQG|2^n9dc&f2nW@^aKWG2z9sm4#*K(m;>B6CZ(_ReQ zptJB>3n$)3?j8Tn_f$yt=@`Sz{tI;M2t%%K+7WKb{pVZCv$Q^%{=c`N!Dm3l|NULM z81FTT|Klpaj+o@E_J5x)gvtbjhQ-su?f&Zlzo8w%UHpG{5=YMhj(<&}|8OPD{&jo* zI{O*EnehMTH9REUloLoAFviR@EGOPX1@vl?vB-6A0{jC1^utT`R z!11q+aT{TC_%a}dDj;9%0T6dRdg*ILVf)8C z7P8_NRwkg_fAS`*nn~cchzVu>acl0kgM|Q4`3r>%2=Z|Ml?+-8Xi~C4Po?8Is5N$W z@&kY(wMpp47AR`(AKn++2Q2y_@-pS?otm)yYvFp&^*xw0V4P zuPjVZzSlvb(%;Lsl5RMJrSXd^6Ez4lKyShWi>^HYjqD~(5PMd`0kZjJ<15MRcANcF zyngoFQ|#Npj~g`ZoeYU4-b3JaKMy@#JkFpodn$yLv*#rApAGU)>$Y$VaqYHo-Ac2j zBK|SIP#<3zZ^W9-!Nv}c)R9lJSp$Sn`q^R*J^B=8Ki7M@En%zm5xD&-WMuTQv|gw~ zKk264cuT~Dqbc15y7tqunUpA@H=!$lt9jt>R+gLRs~-IIAar%gpt(}yHpIC}=BYQ8 ztdknLJVrw2OfXW?Rv6r#&erbFw_c?XpvE6FOa}l*q1E0W$AB;e4yc@cD7VBNk=7W~ zB|RoDF)WG()O~fq{BfA0Jf}3)rnicgg(^>bG&I_Wjj=N*)G;F`;js^ zzzLAbSbOg=P6bz*@rNhvI%lU^S50`~sN2~QtB#>FtUd)A%f|eQ&&p%Kyt0#8cNZJp z9&?6z*>9rh5{`2NP#2+k@(N0M3dr8w$1a4ES6hpqteDW|PjGT2NCuL6oouFXMEL*P z6gvV(aZHX9*BXJM>!b0<=97OgcX@wr?=RvZ>R!HM6@J_r`<;?n(20)Zb;ZJ(n;CqHRDB`|bc=iL5 zp47m=#eiETGi72Mt4+ir>H8{IE=Caj0do

ojnkWCa@N6AobP53Edm+(;f^0V2E9t$SnuzFJS-hAs!X5%cFm zNfzhM{I4OjBX9)A?0CRAKYn=R^j#Lw$Yfs9^t#|+^Lip&&wbm`VCED^B~1jeUQ25V zHHz^bE@FHG#Fk6|J^z6K8q89Y6!vH9GP~u3o?qFLrq>6%wjf_rb8-807emjRZAuZ) z>&8=mrHwV~RRpgeHl_X!-DO_-Y(ZJk;Z_=T zFoYBBS3p}&Soc{&T$wfyucc2>bNI67tV({8e~okuy%j!gUDhxi|8pqR;#{)DghufU0F746=;JoqS85MDz+@Nez3hvZW`0wNKE3>tC&+|vzi z^vS0F4IRrG+W5J#rCS-rgoj+x4eNYJXnr~dN8Ix0-=yj&i$qlXZL<*NsiiHpms|S- z*_ui%y9Yh(tvS^r`F=dnQSmzYGrIDy(4)vCSd zYaCJ&Ngq0_k!HIeF$ zF$>OY7GS~Fic`jr6JebudzLQWHJ-*NGQ&3)#~`0�r|i^hfvJ+e{h*=*5~oOe7hV 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

7>+J`eD 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 literal 0 HcmV?d00001 diff --git a/docs/management/snapshot-restore/index.asciidoc b/docs/management/snapshot-restore/index.asciidoc index f309b2c17e0ed..f19aaa122675e 100644 --- a/docs/management/snapshot-restore/index.asciidoc +++ b/docs/management/snapshot-restore/index.asciidoc @@ -11,11 +11,11 @@ you can restore a snapshot from the repository. You’ll find *Snapshot and Restore* under *Management > Elasticsearch*. With this UI, you can: -* <> -* <> -* <> -* <> -* <> +* Register a repository for storing your snapshots +* View a list of your snapshots and drill down into details +* Restore data into your cluster from a snapshot +* Create a policy to automate snapshot creation and deletion +* Delete a snapshot to free storage space [role="screenshot"] image:management/snapshot-restore/images/snapshot_list.png["Snapshot list"] @@ -27,28 +27,34 @@ more detailed information. [float] [[kib-snapshot-register-repository]] === Register a repository +A repository is where your snapshots live. You must register a snapshot +repository before you can perform snapshot and restore operations. + +If you don't have a repository, Kibana walks you through the process of +registering one. +{kib} supports three repository types +out of the box: shared file system, read-only URL, and source-only. +For more information on these repositories and their settings, +see {ref}/modules-snapshots.html#snapshots-repositories[Repositories]. +To use other repositories, such as S3, see +{ref}/modules-snapshots.html#_repository_plugins[Repository plugins]. -The *Repositories* view provides an overview of your repositories. -Click a repository name to view its type, number of snapshots, and settings, and also to verify status. + +Once you create a repository, it is listed in the *Repositories* +view. +Click a repository name to view its type, number of snapshots, and settings, +and to verify status. [role="screenshot"] image:management/snapshot-restore/images/repository_list.png["Repository list"] -If you don't have a repository, you're prompted to register one. -{es} supports three repository types -out of the box: shared file system, read-only URL, and source-only. -For more information on these repositories and their settings, -see {ref}/modules-snapshots.html#snapshots-repositories[Repositories]. For an example, -see <>. - -To use other repositories, such as S3, you can install plugins. See -{ref}/modules-snapshots.html#_repository_plugins[Repository plugins]. [float] [[kib-view-snapshot]] === View your snapshots -The *Snapshots* view gives an overview of your snapshots. You can drill down +A snapshot is a backup taken from a running {es} cluster. You'll find an overview of +your snapshots in the *Snapshots* view, and you can drill down into each snapshot for further investigation. [role="screenshot"] @@ -68,18 +74,25 @@ the new data. [[kib-restore-snapshot]] === Restore a snapshot -The *Restore* wizard walks you through the process of restoring a snapshot -into a running cluster. To get started, go to the *Snapshots* view, find the -snapshot, and click the restore icon in the *Actions* column. +The information stored in a snapshot is not tied to a specific +cluster or a cluster name. This enables you to +restore a snapshot made from one cluster to another cluster. You might +use the restore operation to: -You’re presented -options for the restore, including which +* Recover data lost due to a failure +* Migrate a current Elasticsearch cluster to a new version +* Move data from one cluster to another cluster + +To get started, go to the *Snapshots* view, find the +snapshot, and click the restore icon in the *Actions* column. +The Restore wizard presents +options for the restore operation, including which indices to restore and whether to modify the index settings. You can restore an existing index only if it’s closed and has the same number of shards as the index in the snapshot. Once you initiate the restore, you're navigated to the *Restore Status* view, -where you can track the progress. +where you can track the current state for each shard in the snapshot. [role="screenshot"] image:management/snapshot-restore/images/snapshot-restore.png["Snapshot details"] @@ -89,23 +102,28 @@ image:management/snapshot-restore/images/snapshot-restore.png["Snapshot details" [[kib-snapshot-policy]] === Create a snapshot lifecycle policy -You can create policies to schedule automatic snapshots of your cluster. -{ref}/snapshot-lifecycle-management-api.html[Snapshot lifecycle policies] are related -to {ref}/index-lifecycle-management.html[index lifecycle policies]. -However, where an index lifecycle policy applies to a single index, -a snapshot lifecycle policy can span multiple indices. - -For an overview of your policies, open the *Policies* view. -You can drill down into each policy to examine its settings and last successful and failed run. - -If you don’t have any policies, use the *Create policy* wizard. -You’ll define the snapshots and repository, when to take snapshots, and -the settings, such as which indices the snapshot should contain. +Use a {ref}/snapshot-lifecycle-management-api.html[snapshot lifecycle policy] +to automate the creation and deletion +of cluster snapshots. Taking automatic snapshots: + +* Ensures your {es} indices and clusters are backed up on a regular basis +* Ensures a recent and relevant snapshot is available if a situation +arises where a cluster needs to be recovered +* Allows you to manage your snapshots in {kib}, instead of using a +third-party tool + +If you don’t have any snapshot policies, follow the +*Create policy* wizard. It walks you through defining +when and where to take snapshots, the settings you want, +and how long to retain snapshots. [role="screenshot"] -image:management/snapshot-restore/images/create-policy.png["Snapshot details"] +image:management/snapshot-restore/images/snapshot-retention.png["Snapshot details"] + +An overview of your policies is on the *Policies* view. +You can drill down into each policy to examine its settings and last successful and failed run. -You can perform the following actions on a policy: +You can perform the following actions on a snapshot policy: * *Run* a policy immediately without waiting for the scheduled time. This action is useful before an upgrade or before performing maintenance on indices. @@ -113,6 +131,9 @@ This action is useful before an upgrade or before performing maintenance on indi * *Delete* a policy to prevent any future snapshots from being taken. This action does not cancel any currently ongoing snapshots or remove any previously taken snapshots. +[role="screenshot"] +image:management/snapshot-restore/images/create-policy.png["Snapshot details"] + [float] [[kib-delete-snapshot]] === Delete a snapshot @@ -123,16 +144,25 @@ Find the snapshot in the *Snapshots* view and click the trash icon in the and then click *Delete snapshots*. [[snapshot-repositories-example]] -[float] -=== Example: Register a shared file system repository -This example shows how to register a shared file system repository -and store snapshots. +[role="xpack"] +[[snapshot-restore-tutorial]] +=== Tutorial: Snapshot and Restore -[float] -==== Register the repository location -You must register the location of the repository in the `path.repo` setting on +Ready to try *Snapshot and Restore*? In this tutorial, you'll learn to: + +* Register a repository +* Add snapshots to the repository +* Create a snapshot lifecycle policy +* Restore a snapshot + +==== Before you begin + +This example shows you how to register a shared file system repository +and store snapshots. +Before you begin, you must register the location of the repository in the +{ref}/modules-snapshots.html#_shared_file_system_repository[path.repo] setting on your master and data nodes. You can do this in one of two ways: * Edit your `elasticsearch.yml` to include the `path.repo` setting. @@ -142,30 +172,26 @@ your master and data nodes. You can do this in one of two ways: `bin/elasticsearch -E path.repo=/tmp/es-backups` [float] -==== Register the repository +[[register-repo-example]] +==== Register a repository Use *Snapshot and Restore* to register the repository where your snapshots will live. . Go to *Management > Elasticsearch > Snapshot and Restore*. -. Open the *Repositories* view. -. Click *Register a repository*. +. Click *Register a repository* in either the introductory message or *Repository view*. . Enter a name for your repository, for example, `my_backup`. -. Set *Repository type* to Shared file system. +. Select *Shared file system*. + [role="screenshot"] image:management/snapshot-restore/images/register_repo.png["Register repository"] . Click *Next*. -. In *Location*, enter the path to the snapshot repository, `/tmp/es-backups`. -. In *Chunk size*, enter 100mb so that snapshot files are not bigger than that size. -. Use the defaults for all other fields. -. Click *Register*. +. In *File system location*, enter the path to the snapshot repository, `/tmp/es-backups`. +. In *Chunk size*, enter `100mb` so that snapshot files are not bigger than that size. +. Use the defaults for all other fields, and then click *Register*. + Your new repository is listed on the *Repositories* view. -+ -. Click the respository and inspect its details. -+ The repository currently doesn’t have any snapshots. @@ -174,19 +200,105 @@ The repository currently doesn’t have any snapshots. Use the {ref}//modules-snapshots.html#snapshots-take-snapshot[snapshot API] to create a snapshot. . Go to *Dev Tools > Console*. -. Create the snapshot. +. Create the snapshot: ++ +[source,js] +PUT /_snapshot/my_backup/2019-04-25_snapshot?wait_for_completion=true + In this example, the snapshot name is `2019-04-25_snapshot`. You can also use {ref}//date-math-index-names.html[date math expression] for the snapshot name. + [role="screenshot"] image:management/snapshot-restore/images/create_snapshot.png["Create snapshot"] -+ -. Open *Snapshot and Restore*. + +. Return to *Snapshot and Restore*. + Your new snapshot is available in the *Snapshots* view. +[[create-policy-example]] +==== Create a snapshot lifecycle policy + +Now you'll automate the creation and deletion of snapshots +using the repository created in the previous example. + +. Open the *Policies* view. +. Click *Create a policy*. ++ +[role="screenshot"] +image:management/snapshot-restore/images/create-policy-example.png["Create policy wizard"] + +. As you walk through the wizard, enter the following values: ++ +|=== +|*Logistics* | + +|Policy name +|`daily-snapshots` + +|Snapshot name +|`` + +|Schedule +|Every day at 1:30 a.m. + +|Repository +|`my_backup` + +|*Snapshot settings* | +|Indices +|Select the indices to back up. By default, all indices, including system indices, are backed up. +|All other settings +|Use the defaults. +|*Snapshot retention* | + +|Expiration +|`30 days` + +|Snapshots to retain +|Minimum count: `5`, Maximum count: `50` +|=== + +. Review your input, and then click *Create policy*. ++ +Your new policy is listed in the *Policies* view, and you see a summary of its details. + +[[restore-snapshot-example]] +==== Restore a snapshot +Finally, you'll restore indices from an existing snapshot. + +. In the *Snapshots* view, find the snapshot you want to restore, for example `2019-04-25_snapshot`. +. Click the restore icon in the *Actions* column. +. As you walk through the wizard, enter the following values: ++ +|=== +|*Logistics* | + +|Indices +|Toggle to choose specific indices to restore, or leave in place to restore all indices. + +|Rename indices +|Toggle to give your restored indices new names, or leave in place to restore under original index names. + +|All other fields +|Use the defaults. + +|*Index settings* | + +|Modify index settings +|Toggle to overwrite index settings when they are restored, +or leave in place to keep existing settings. + +|Reset index settings +|Toggle to reset index settings back to the default when they are restored, +or leave in place to keep existing settings. +|=== + +. Review your restore settings, and then click *Restore snapshot*. ++ +The operation loads for a few seconds, +and then you’re navigated to *Restore Status*, +where you can monitor the status of your restored indices. From ed07fb4c065b0128de3eaf50b4837edc0bd44c7b Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Fri, 25 Oct 2019 16:32:59 -0400 Subject: [PATCH 174/191] [Expressions] [Lens] Implement a loading state and error state in the ExpressionRenderer (#48841) * Add loading indicator to Lens workspace panel * [Expressions] [Lens] Handle loading and errors in ExpressionRenderer * Using loading$ observable and improve tests * Using CSS and to handle layout of expression renderer Added TODO for using chart loader when area is completely empty * Improve error handling and simplify code * Fix cleanup behavior * Fix double render and prevent error cases in xy chart * Fix context for use in dashboards * Remove className from expression rendere component * Improve handling of additional interpreter args * More layout fixes - Hide chart if Empty not Loading - Fix relative positioning for progress bar since className is no longer passed (super hacky) --- src/legacy/core_plugins/expressions/index.ts | 1 + .../expressions/public/index.scss | 13 + .../np_ready/public/_expression_renderer.scss | 20 ++ .../public/np_ready/public/_index.scss | 1 + .../public/np_ready/public/execute.ts | 14 +- .../public/expression_renderer.test.tsx | 141 +++++++++ .../np_ready/public/expression_renderer.tsx | 110 +++++-- .../public/np_ready/public/index.ts | 2 +- .../public/np_ready/public/loader.test.ts | 108 ++++++- .../public/np_ready/public/loader.ts | 118 +++++--- .../np_ready/public/{mocks.ts => mocks.tsx} | 3 +- .../public/np_ready/public/plugin.ts | 5 +- .../public/np_ready/public/render.test.ts | 77 ++++- .../public/np_ready/public/render.ts | 76 +++-- .../public/np_ready/public/types.ts | 11 +- .../expression.tsx | 20 +- .../editor_frame/_expression_renderer.scss | 7 +- .../editor_frame/_suggestion_panel.scss | 13 +- .../_workspace_panel_wrapper.scss | 1 + .../editor_frame/suggestion_panel.tsx | 53 ++-- .../editor_frame/workspace_panel.test.tsx | 277 +++++++----------- .../editor_frame/workspace_panel.tsx | 82 ++++-- .../embeddable/embeddable.test.tsx | 20 -- .../embeddable/expression_wrapper.tsx | 25 +- .../metric_expression.tsx | 12 +- .../xy_visualization_plugin/xy_expression.tsx | 21 +- 26 files changed, 832 insertions(+), 399 deletions(-) create mode 100644 src/legacy/core_plugins/expressions/public/index.scss create mode 100644 src/legacy/core_plugins/expressions/public/np_ready/public/_expression_renderer.scss create mode 100644 src/legacy/core_plugins/expressions/public/np_ready/public/_index.scss create mode 100644 src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.test.tsx rename src/legacy/core_plugins/expressions/public/np_ready/public/{mocks.ts => mocks.tsx} (97%) diff --git a/src/legacy/core_plugins/expressions/index.ts b/src/legacy/core_plugins/expressions/index.ts index b10e9a8dd5442..4ba9a74795d4c 100644 --- a/src/legacy/core_plugins/expressions/index.ts +++ b/src/legacy/core_plugins/expressions/index.ts @@ -34,6 +34,7 @@ export default function DataExpressionsPlugin(kibana: any) { init: (server: Legacy.Server) => ({}), uiExports: { injectDefaultVars: () => ({}), + styleSheetPaths: resolve(__dirname, 'public/index.scss'), }, }; diff --git a/src/legacy/core_plugins/expressions/public/index.scss b/src/legacy/core_plugins/expressions/public/index.scss new file mode 100644 index 0000000000000..6efc552bf319b --- /dev/null +++ b/src/legacy/core_plugins/expressions/public/index.scss @@ -0,0 +1,13 @@ +// Import the EUI global scope so we can use EUI constants +@import 'src/legacy/ui/public/styles/_styling_constants'; + +/* Expressions plugin styles */ + +// Prefix all styles with "exp" to avoid conflicts. +// Examples +// expChart +// expChart__legend +// expChart__legend--small +// expChart__legend-isLoading + +@import './np_ready/public/index'; diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/_expression_renderer.scss b/src/legacy/core_plugins/expressions/public/np_ready/public/_expression_renderer.scss new file mode 100644 index 0000000000000..4f030384ed883 --- /dev/null +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/_expression_renderer.scss @@ -0,0 +1,20 @@ +.expExpressionRenderer { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; +} + +.expExpressionRenderer__expression { + width: 100%; + height: 100%; +} + +.expExpressionRenderer-isEmpty, +.expExpressionRenderer-hasError { + .expExpressionRenderer__expression { + display: none; + } +} diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/_index.scss b/src/legacy/core_plugins/expressions/public/np_ready/public/_index.scss new file mode 100644 index 0000000000000..b9df491cd6e79 --- /dev/null +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/_index.scss @@ -0,0 +1 @@ +@import './expression_renderer'; diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/execute.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/execute.ts index b4b11588b91bf..8043e0fb6e3f9 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/execute.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/execute.ts @@ -61,6 +61,7 @@ export class ExpressionDataHandler { this.promise = interpreter.interpretAst(this.ast, params.context || defaultContext, { getInitialContext, inspectorAdapters: this.inspectorAdapters, + abortSignal: this.abortController.signal, }); } @@ -69,7 +70,18 @@ export class ExpressionDataHandler { }; getData = async () => { - return await this.promise; + try { + return await this.promise; + } catch (e) { + return { + type: 'error', + error: { + type: e.type, + message: e.message, + stack: e.stack, + }, + }; + } }; getExpression = () => { diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.test.tsx b/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.test.tsx new file mode 100644 index 0000000000000..26db8753e6403 --- /dev/null +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.test.tsx @@ -0,0 +1,141 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { Subject } from 'rxjs'; +import { share } from 'rxjs/operators'; +import { ExpressionRendererImplementation } from './expression_renderer'; +import { ExpressionLoader } from './loader'; +import { mount } from 'enzyme'; +import { EuiProgress } from '@elastic/eui'; + +jest.mock('./loader', () => { + return { + ExpressionLoader: jest.fn().mockImplementation(() => { + return {}; + }), + loader: jest.fn(), + }; +}); + +describe('ExpressionRenderer', () => { + it('starts to load, resolves, and goes back to loading', () => { + const dataSubject = new Subject(); + const data$ = dataSubject.asObservable().pipe(share()); + const renderSubject = new Subject(); + const render$ = renderSubject.asObservable().pipe(share()); + const loadingSubject = new Subject(); + const loading$ = loadingSubject.asObservable().pipe(share()); + + (ExpressionLoader as jest.Mock).mockImplementation(() => { + return { + render$, + data$, + loading$, + update: jest.fn(), + }; + }); + + const instance = mount(); + + loadingSubject.next(); + instance.update(); + + expect(instance.find(EuiProgress)).toHaveLength(1); + + renderSubject.next(1); + + instance.update(); + + expect(instance.find(EuiProgress)).toHaveLength(0); + + instance.setProps({ expression: 'something new' }); + loadingSubject.next(); + instance.update(); + + expect(instance.find(EuiProgress)).toHaveLength(1); + + renderSubject.next(1); + instance.update(); + + expect(instance.find(EuiProgress)).toHaveLength(0); + }); + + it('should display an error message when the expression fails', () => { + const dataSubject = new Subject(); + const data$ = dataSubject.asObservable().pipe(share()); + const renderSubject = new Subject(); + const render$ = renderSubject.asObservable().pipe(share()); + const loadingSubject = new Subject(); + const loading$ = loadingSubject.asObservable().pipe(share()); + + (ExpressionLoader as jest.Mock).mockImplementation(() => { + return { + render$, + data$, + loading$, + update: jest.fn(), + }; + }); + + const instance = mount(); + + dataSubject.next('good data'); + renderSubject.next({ + type: 'error', + error: { message: 'render error' }, + }); + instance.update(); + + expect(instance.find(EuiProgress)).toHaveLength(0); + expect(instance.find('[data-test-subj="expression-renderer-error"]')).toHaveLength(1); + }); + + it('should display a custom error message if the user provides one', () => { + const dataSubject = new Subject(); + const data$ = dataSubject.asObservable().pipe(share()); + const renderSubject = new Subject(); + const render$ = renderSubject.asObservable().pipe(share()); + const loadingSubject = new Subject(); + const loading$ = loadingSubject.asObservable().pipe(share()); + + (ExpressionLoader as jest.Mock).mockImplementation(() => { + return { + render$, + data$, + loading$, + update: jest.fn(), + }; + }); + + const renderErrorFn = jest.fn().mockReturnValue(null); + + const instance = mount( + + ); + + renderSubject.next({ + type: 'error', + error: { message: 'render error' }, + }); + instance.update(); + + expect(renderErrorFn).toHaveBeenCalledWith('render error'); + }); +}); diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.tsx b/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.tsx index 9edb5f098ba2e..8359663610f29 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.tsx +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/expression_renderer.tsx @@ -17,49 +17,49 @@ * under the License. */ -import { useRef, useEffect } from 'react'; +import { useRef, useEffect, useState } from 'react'; import React from 'react'; -import { ExpressionAST, IExpressionLoaderParams, IInterpreterResult } from './types'; -import { IExpressionLoader, ExpressionLoader } from './loader'; +import classNames from 'classnames'; +import { EuiLoadingChart, EuiProgress } from '@elastic/eui'; +import { ExpressionAST, IExpressionLoaderParams, IInterpreterErrorResult } from './types'; +import { ExpressionLoader } from './loader'; // Accept all options of the runner as props except for the // dom element which is provided by the component itself export interface ExpressionRendererProps extends IExpressionLoaderParams { - className: string; dataAttrs?: string[]; expression: string | ExpressionAST; - /** - * If an element is specified, but the response of the expression run can't be rendered - * because it isn't a valid response or the specified renderer isn't available, - * this callback is called with the given result. - */ - onRenderFailure?: (result: IInterpreterResult) => void; + renderError?: (error?: string | null) => React.ReactElement | React.ReactElement[]; +} + +interface State { + isEmpty: boolean; + isLoading: boolean; + error: null | Error; } export type ExpressionRenderer = React.FC; -export const createRenderer = (loader: IExpressionLoader): ExpressionRenderer => ({ - className, +const defaultState: State = { + isEmpty: true, + isLoading: false, + error: null, +}; + +export const ExpressionRendererImplementation = ({ dataAttrs, expression, - onRenderFailure, + renderError, ...options }: ExpressionRendererProps) => { const mountpoint: React.MutableRefObject = useRef(null); const handlerRef: React.MutableRefObject = useRef(null); + const [state, setState] = useState({ ...defaultState }); + // Re-fetch data automatically when the inputs change useEffect(() => { - if (mountpoint.current) { - if (!handlerRef.current) { - handlerRef.current = loader(mountpoint.current, expression, options); - } else { - handlerRef.current.update(expression, options); - } - handlerRef.current.data$.toPromise().catch(result => { - if (onRenderFailure) { - onRenderFailure(result); - } - }); + if (handlerRef.current) { + handlerRef.current.update(expression, options); } }, [ expression, @@ -67,8 +67,66 @@ export const createRenderer = (loader: IExpressionLoader): ExpressionRenderer => options.context, options.variables, options.disableCaching, - mountpoint.current, ]); - return
; + // Initialize the loader only once + useEffect(() => { + if (mountpoint.current && !handlerRef.current) { + handlerRef.current = new ExpressionLoader(mountpoint.current, expression, options); + + handlerRef.current.loading$.subscribe(() => { + if (!handlerRef.current) { + return; + } + setState(prevState => ({ ...prevState, isLoading: true })); + }); + handlerRef.current.render$.subscribe((item: number | IInterpreterErrorResult) => { + if (!handlerRef.current) { + return; + } + if (typeof item !== 'number') { + setState(() => ({ + ...defaultState, + isEmpty: false, + error: item.error, + })); + } else { + setState(() => ({ + ...defaultState, + isEmpty: false, + })); + } + }); + } + }, [mountpoint.current]); + + useEffect(() => { + // We only want a clean up to run when the entire component is unloaded, not on every render + return function cleanup() { + if (handlerRef.current) { + handlerRef.current.destroy(); + handlerRef.current = null; + } + }; + }, []); + + const classes = classNames('expExpressionRenderer', { + 'expExpressionRenderer-isEmpty': state.isEmpty, + 'expExpressionRenderer-hasError': !!state.error, + }); + + return ( +
+ {state.isEmpty ? : null} + {state.isLoading ? : null} + {!state.isLoading && state.error ? ( + renderError ? ( + renderError(state.error.message) + ) : ( +
{state.error.message}
+ ) + ) : null} +
+
+ ); }; diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/index.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/index.ts index 428b431d298ad..2ff71a6df60cf 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/index.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/index.ts @@ -22,7 +22,7 @@ import { ExpressionsPublicPlugin } from './plugin'; export * from './plugin'; export { ExpressionRenderer, ExpressionRendererProps } from './expression_renderer'; -export { IInterpreterRenderFunction } from './types'; +export { IInterpreterRenderFunction, IInterpreterRenderHandlers } from './types'; export function plugin(initializerContext: PluginInitializerContext) { return new ExpressionsPublicPlugin(initializerContext); diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts index df695c039e02e..36917bf4e8384 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts @@ -19,6 +19,7 @@ import { first } from 'rxjs/operators'; import { loader, ExpressionLoader } from './loader'; +import { ExpressionDataHandler } from './execute'; import { fromExpression } from '@kbn/interpreter/common'; import { IInterpreterRenderHandlers } from './types'; import { Observable } from 'rxjs'; @@ -48,27 +49,37 @@ jest.mock('./services', () => { }; }); +jest.mock('./execute', () => { + const actual = jest.requireActual('./execute'); + return { + ExpressionDataHandler: jest + .fn() + .mockImplementation((...args) => new actual.ExpressionDataHandler(...args)), + execute: jest.fn().mockReturnValue(actual.execute), + }; +}); + describe('execute helper function', () => { - it('returns ExpressionDataHandler instance', () => { + it('returns ExpressionLoader instance', () => { const response = loader(element, '', {}); expect(response).toBeInstanceOf(ExpressionLoader); }); }); -describe('ExpressionDataHandler', () => { +describe('ExpressionLoader', () => { const expressionString = ''; describe('constructor', () => { it('accepts expression string', () => { - const expressionDataHandler = new ExpressionLoader(element, expressionString, {}); - expect(expressionDataHandler.getExpression()).toEqual(expressionString); + const expressionLoader = new ExpressionLoader(element, expressionString, {}); + expect(expressionLoader.getExpression()).toEqual(expressionString); }); it('accepts expression AST', () => { const expressionAST = fromExpression(expressionString) as ExpressionAST; - const expressionDataHandler = new ExpressionLoader(element, expressionAST, {}); - expect(expressionDataHandler.getExpression()).toEqual(expressionString); - expect(expressionDataHandler.getAst()).toEqual(expressionAST); + const expressionLoader = new ExpressionLoader(element, expressionAST, {}); + expect(expressionLoader.getExpression()).toEqual(expressionString); + expect(expressionLoader.getAst()).toEqual(expressionAST); }); it('creates observables', () => { @@ -117,9 +128,86 @@ describe('ExpressionDataHandler', () => { expect(response).toBe(2); }); - it('cancel() aborts request', () => { - const expressionDataHandler = new ExpressionLoader(element, expressionString, {}); - expressionDataHandler.cancel(); + it('cancels the previous request when the expression is updated', () => { + const cancelMock = jest.fn(); + + (ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({ + getData: () => true, + cancel: cancelMock, + })); + + const expressionLoader = new ExpressionLoader(element, expressionString, {}); + expressionLoader.update('new', {}); + + expect(cancelMock).toHaveBeenCalledTimes(1); + }); + + it('does not send an observable message if a request was aborted', () => { + const cancelMock = jest.fn(); + + const getData = jest + .fn() + .mockResolvedValueOnce({ + type: 'error', + error: { + name: 'AbortError', + }, + }) + .mockResolvedValueOnce({ + type: 'real', + }); + + (ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({ + getData, + cancel: cancelMock, + })); + (ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({ + getData, + cancel: cancelMock, + })); + + const expressionLoader = new ExpressionLoader(element, expressionString, {}); + + expect.assertions(2); + expressionLoader.data$.subscribe({ + next(data) { + expect(data).toEqual({ + type: 'real', + }); + }, + error() { + expect(false).toEqual('Should not be called'); + }, + }); + + expressionLoader.update('new expression', {}); + + expect(getData).toHaveBeenCalledTimes(2); + }); + + it('sends an observable error if the data fetching failed', () => { + const cancelMock = jest.fn(); + + const getData = jest.fn().mockResolvedValue('rejected'); + + (ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({ + getData, + cancel: cancelMock, + })); + + const expressionLoader = new ExpressionLoader(element, expressionString, {}); + + expect.assertions(2); + expressionLoader.data$.subscribe({ + next(data) { + expect(data).toEqual('Should not be called'); + }, + error(error) { + expect(error.message).toEqual('Could not fetch data'); + }, + }); + + expect(getData).toHaveBeenCalledTimes(1); }); it('inspect() returns correct inspector adapters', () => { diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts index b07b0048bfd52..709fbc78a9b52 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts @@ -18,11 +18,11 @@ */ import { Observable, Subject } from 'rxjs'; -import { first, share } from 'rxjs/operators'; +import { share } from 'rxjs/operators'; import { Adapters, InspectorSession } from '../../../../../../plugins/inspector/public'; -import { execute, ExpressionDataHandler } from './execute'; +import { ExpressionDataHandler } from './execute'; import { ExpressionRenderHandler } from './render'; -import { RenderId, Data, IExpressionLoaderParams, ExpressionAST } from './types'; +import { Data, IExpressionLoaderParams, ExpressionAST } from './types'; import { getInspector } from './services'; export class ExpressionLoader { @@ -32,12 +32,12 @@ export class ExpressionLoader { events$: ExpressionRenderHandler['events$']; loading$: Observable; - private dataHandler!: ExpressionDataHandler; + private dataHandler: ExpressionDataHandler | undefined; private renderHandler: ExpressionRenderHandler; private dataSubject: Subject; private loadingSubject: Subject; private data: Data; - private params: IExpressionLoaderParams; + private params: IExpressionLoaderParams = {}; constructor( element: HTMLElement, @@ -63,76 +63,108 @@ export class ExpressionLoader { this.render(data); }); - this.params = { - searchContext: { type: 'kibana_context' }, - extraHandlers: params.extraHandlers, - }; + this.setParams(params); - this.execute(expression, params); + this.loadData(expression, this.params); } - destroy() {} + destroy() { + this.dataSubject.complete(); + this.loadingSubject.complete(); + this.renderHandler.destroy(); + if (this.dataHandler) { + this.dataHandler.cancel(); + } + } cancel() { - this.dataHandler.cancel(); + if (this.dataHandler) { + this.dataHandler.cancel(); + } } - getExpression(): string { - return this.dataHandler.getExpression(); + getExpression(): string | undefined { + if (this.dataHandler) { + return this.dataHandler.getExpression(); + } } - getAst(): ExpressionAST { - return this.dataHandler.getAst(); + getAst(): ExpressionAST | undefined { + if (this.dataHandler) { + return this.dataHandler.getAst(); + } } getElement(): HTMLElement { return this.renderHandler.getElement(); } - openInspector(title: string): InspectorSession { - return getInspector().open(this.inspect(), { - title, - }); + openInspector(title: string): InspectorSession | undefined { + const inspector = this.inspect(); + if (inspector) { + return getInspector().open(inspector, { + title, + }); + } } - inspect(): Adapters { - return this.dataHandler.inspect(); + inspect(): Adapters | undefined { + if (this.dataHandler) { + return this.dataHandler.inspect(); + } } - update(expression?: string | ExpressionAST, params?: IExpressionLoaderParams): Promise { - const promise = this.render$.pipe(first()).toPromise(); - if (params && params.searchContext && this.params.searchContext) { - this.params.searchContext = _.defaults( - {}, - params.searchContext, - this.params.searchContext - ) as any; - } + update(expression?: string | ExpressionAST, params?: IExpressionLoaderParams): void { + this.setParams(params); - this.loadingSubject.next(); if (expression) { - this.execute(expression, this.params); + this.loadData(expression, this.params); } else { this.render(this.data); } - return promise; } - private execute = async ( + private loadData = async ( expression: string | ExpressionAST, - params?: IExpressionLoaderParams - ): Promise => { + params: IExpressionLoaderParams + ): Promise => { + this.loadingSubject.next(); if (this.dataHandler) { this.dataHandler.cancel(); } - this.dataHandler = execute(expression, params); - this.data = await this.dataHandler.getData(); - this.dataSubject.next(this.data); - return this.data; + this.setParams(params); + this.dataHandler = new ExpressionDataHandler(expression, params); + const data = await this.dataHandler.getData(); + this.dataSubject.next(data); }; - private async render(data: Data): Promise { - return this.renderHandler.render(data, this.params.extraHandlers); + private render(data: Data): void { + this.loadingSubject.next(); + this.renderHandler.render(data, this.params.extraHandlers); + } + + private setParams(params?: IExpressionLoaderParams) { + if (!params || !Object.keys(params).length) { + return; + } + + if (params.searchContext && this.params.searchContext) { + this.params.searchContext = _.defaults( + {}, + params.searchContext, + this.params.searchContext + ) as any; + } + if (params.extraHandlers && this.params) { + this.params.extraHandlers = params.extraHandlers; + } + + if (!Object.keys(this.params).length) { + this.params = { + ...params, + searchContext: { type: 'kibana_context', ...(params.searchContext || {}) }, + }; + } } } diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/mocks.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/mocks.tsx similarity index 97% rename from src/legacy/core_plugins/expressions/public/np_ready/public/mocks.ts rename to src/legacy/core_plugins/expressions/public/np_ready/public/mocks.tsx index 6569e8d8d1ec5..1a2f473f4c9a1 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/mocks.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/mocks.tsx @@ -17,6 +17,7 @@ * under the License. */ +import React from 'react'; import { ExpressionsSetup, ExpressionsStart, plugin as pluginInitializer } from '.'; /* eslint-disable */ import { coreMock } from '../../../../../../core/public/mocks'; @@ -44,7 +45,7 @@ const createExpressionsSetupMock = (): ExpressionsSetup => { function createExpressionsStartMock(): ExpressionsStart { return { - ExpressionRenderer: jest.fn(() => null), + ExpressionRenderer: jest.fn(props => <>), execute: jest.fn(), loader: jest.fn(), render: jest.fn(), diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/plugin.ts index 5a0eecc51ef19..ec70248694990 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/plugin.ts @@ -34,7 +34,7 @@ import { } from '../../../../../../plugins/inspector/public'; import { IInterpreter } from './types'; import { setInterpreter, setInspector, setRenderersRegistry } from './services'; -import { createRenderer } from './expression_renderer'; +import { ExpressionRendererImplementation } from './expression_renderer'; import { ExpressionLoader, loader } from './loader'; import { ExpressionDataHandler, execute } from './execute'; import { ExpressionRenderHandler, render } from './render'; @@ -77,17 +77,16 @@ export class ExpressionsPublicPlugin } public start(core: CoreStart, { inspector }: ExpressionsStartDeps) { - const ExpressionRenderer = createRenderer(loader); setInspector(inspector); return { execute, render, loader, + ExpressionRenderer: ExpressionRendererImplementation, ExpressionDataHandler, ExpressionRenderHandler, ExpressionLoader, - ExpressionRenderer, }; } diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/render.test.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/render.test.ts index cf606b8fabec2..9d555f9760ee7 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/render.test.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/render.test.ts @@ -20,6 +20,8 @@ import { render, ExpressionRenderHandler } from './render'; import { Observable } from 'rxjs'; import { IInterpreterRenderHandlers } from './types'; +import { getRenderersRegistry } from './services'; +import { first } from 'rxjs/operators'; const element: HTMLElement = {} as HTMLElement; @@ -31,10 +33,11 @@ jest.mock('./services', () => { }, }, }; + return { - getRenderersRegistry: () => ({ - get: (id: string) => renderers[id], - }), + getRenderersRegistry: jest.fn(() => ({ + get: jest.fn((id: string) => renderers[id]), + })), }; }); @@ -46,8 +49,6 @@ describe('render helper function', () => { }); describe('ExpressionRenderHandler', () => { - const data = { type: 'render', as: 'test' }; - it('constructor creates observers', () => { const expressionRenderHandler = new ExpressionRenderHandler(element); expect(expressionRenderHandler.events$).toBeInstanceOf(Observable); @@ -61,27 +62,71 @@ describe('ExpressionRenderHandler', () => { }); describe('render()', () => { - it('throws if invalid data is provided', async () => { + it('sends an observable error and keeps it open if invalid data is provided', async () => { const expressionRenderHandler = new ExpressionRenderHandler(element); - await expect(expressionRenderHandler.render({})).rejects.toThrow(); + const promise1 = expressionRenderHandler.render$.pipe(first()).toPromise(); + expressionRenderHandler.render(false); + await expect(promise1).resolves.toEqual({ + type: 'error', + error: { + message: 'invalid data provided to the expression renderer', + }, + }); + + const promise2 = expressionRenderHandler.render$.pipe(first()).toPromise(); + expressionRenderHandler.render(false); + await expect(promise2).resolves.toEqual({ + type: 'error', + error: { + message: 'invalid data provided to the expression renderer', + }, + }); }); - it('throws if renderer does not exist', async () => { + it('sends an observable error if renderer does not exist', async () => { const expressionRenderHandler = new ExpressionRenderHandler(element); - await expect( - expressionRenderHandler.render({ type: 'render', as: 'something' }) - ).rejects.toThrow(); + const promise = expressionRenderHandler.render$.pipe(first()).toPromise(); + expressionRenderHandler.render({ type: 'render', as: 'something' }); + await expect(promise).resolves.toEqual({ + type: 'error', + error: { + message: `invalid renderer id 'something'`, + }, + }); }); - it('returns a promise', () => { + it('sends an observable error if the rendering function throws', async () => { + (getRenderersRegistry as jest.Mock).mockReturnValueOnce({ get: () => true }); + (getRenderersRegistry as jest.Mock).mockReturnValueOnce({ + get: () => ({ + render: () => { + throw new Error('renderer error'); + }, + }), + }); + const expressionRenderHandler = new ExpressionRenderHandler(element); - expect(expressionRenderHandler.render(data)).toBeInstanceOf(Promise); + const promise = expressionRenderHandler.render$.pipe(first()).toPromise(); + expressionRenderHandler.render({ type: 'render', as: 'something' }); + await expect(promise).resolves.toEqual({ + type: 'error', + error: { + message: 'renderer error', + }, + }); }); - it('resolves a promise once rendering is complete', async () => { + it('sends a next observable once rendering is complete', () => { const expressionRenderHandler = new ExpressionRenderHandler(element); - const response = await expressionRenderHandler.render(data); - expect(response).toBe(1); + expect.assertions(1); + return new Promise(resolve => { + expressionRenderHandler.render$.subscribe(renderCount => { + expect(renderCount).toBe(1); + resolve(); + }); + + expressionRenderHandler.render({ type: 'render', as: 'test' }); + }); }); }); }); diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/render.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/render.ts index 96f56a4b36202..f67b4c2d8e272 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/render.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/render.ts @@ -19,7 +19,7 @@ import { Observable } from 'rxjs'; import * as Rx from 'rxjs'; -import { share, first } from 'rxjs/operators'; +import { share } from 'rxjs/operators'; import { event, RenderId, Data, IInterpreterRenderHandlers } from './types'; import { getRenderersRegistry } from './services'; @@ -33,19 +33,22 @@ export class ExpressionRenderHandler { private element: HTMLElement; private destroyFn?: any; private renderCount: number = 0; + private renderSubject: Rx.Subject; + private eventsSubject: Rx.Subject; + private updateSubject: Rx.Subject; private handlers: IInterpreterRenderHandlers; constructor(element: HTMLElement) { this.element = element; - const eventsSubject = new Rx.Subject(); - this.events$ = eventsSubject.asObservable().pipe(share()); + this.eventsSubject = new Rx.Subject(); + this.events$ = this.eventsSubject.asObservable().pipe(share()); - const renderSubject = new Rx.Subject(); - this.render$ = renderSubject.asObservable().pipe(share()); + this.renderSubject = new Rx.Subject(); + this.render$ = this.renderSubject.asObservable().pipe(share()); - const updateSubject = new Rx.Subject(); - this.update$ = updateSubject.asObservable().pipe(share()); + this.updateSubject = new Rx.Subject(); + this.update$ = this.updateSubject.asObservable().pipe(share()); this.handlers = { onDestroy: (fn: any) => { @@ -53,39 +56,68 @@ export class ExpressionRenderHandler { }, done: () => { this.renderCount++; - renderSubject.next(this.renderCount); + this.renderSubject.next(this.renderCount); }, reload: () => { - updateSubject.next(null); + this.updateSubject.next(null); }, update: params => { - updateSubject.next(params); + this.updateSubject.next(params); }, event: data => { - eventsSubject.next(data); + this.eventsSubject.next(data); }, }; } - render = async (data: Data, extraHandlers: IExpressionRendererExtraHandlers = {}) => { - if (!data || data.type !== 'render' || !data.as) { - throw new Error('invalid data provided to expression renderer'); + render = (data: Data, extraHandlers: IExpressionRendererExtraHandlers = {}) => { + if (!data || typeof data !== 'object') { + this.renderSubject.next({ + type: 'error', + error: { + message: 'invalid data provided to the expression renderer', + }, + }); + return; } - if (!getRenderersRegistry().get(data.as)) { - throw new Error(`invalid renderer id '${data.as}'`); + if (data.type !== 'render' || !data.as) { + if (data.type === 'error') { + this.renderSubject.next(data); + } else { + this.renderSubject.next({ + type: 'error', + error: { message: 'invalid data provided to the expression renderer' }, + }); + } + return; } - const promise = this.render$.pipe(first()).toPromise(); - - getRenderersRegistry() - .get(data.as) - .render(this.element, data.value, { ...this.handlers, ...extraHandlers }); + if (!getRenderersRegistry().get(data.as)) { + this.renderSubject.next({ + type: 'error', + error: { message: `invalid renderer id '${data.as}'` }, + }); + return; + } - return promise; + try { + // Rendering is asynchronous, completed by handlers.done() + getRenderersRegistry() + .get(data.as) + .render(this.element, data.value, { ...this.handlers, ...extraHandlers }); + } catch (e) { + this.renderSubject.next({ + type: 'error', + error: { type: e.type, message: e.message }, + }); + } }; destroy = () => { + this.renderSubject.complete(); + this.eventsSubject.complete(); + this.updateSubject.complete(); if (this.destroyFn) { this.destroyFn(); } diff --git a/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts b/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts index 09aaa363c9492..0390440298c55 100644 --- a/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts +++ b/src/legacy/core_plugins/expressions/public/np_ready/public/types.ts @@ -52,16 +52,25 @@ export interface IExpressionLoaderParams { export interface IInterpreterHandlers { getInitialContext: IGetInitialContext; inspectorAdapters?: Adapters; + abortSignal?: AbortSignal; } -export interface IInterpreterResult { +export interface IInterpreterErrorResult { + type: 'error'; + error: { message: string; name: string; stack: string }; +} + +export interface IInterpreterSuccessResult { type: string; as?: string; value?: unknown; error?: unknown; } +export type IInterpreterResult = IInterpreterSuccessResult & IInterpreterErrorResult; + export interface IInterpreterRenderHandlers { + // Done increments the number of rendering successes done: () => void; onDestroy: (fn: () => void) => void; reload: () => void; diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/expression.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/expression.tsx index 23b49ecc168cc..e350e36b3bdc0 100644 --- a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/expression.tsx +++ b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/expression.tsx @@ -11,7 +11,10 @@ import { EuiBasicTable } from '@elastic/eui'; import { ExpressionFunction } from '../../../../../../src/plugins/expressions/common'; import { KibanaDatatable } from '../../../../../../src/legacy/core_plugins/interpreter/public'; import { LensMultiTable } from '../types'; -import { IInterpreterRenderFunction } from '../../../../../../src/legacy/core_plugins/expressions/public'; +import { + IInterpreterRenderFunction, + IInterpreterRenderHandlers, +} from '../../../../../../src/legacy/core_plugins/expressions/public'; import { FormatFactory } from '../../../../../../src/legacy/ui/public/visualize/loader/pipeline_helpers/utilities'; import { VisualizationContainer } from '../visualization_container'; @@ -113,8 +116,19 @@ export const getDatatableRenderer = ( help: '', validate: () => {}, reuseDomNode: true, - render: async (domNode: Element, config: DatatableProps, _handlers: unknown) => { - ReactDOM.render(, domNode); + render: async ( + domNode: Element, + config: DatatableProps, + handlers: IInterpreterRenderHandlers + ) => { + ReactDOM.render( + , + domNode, + () => { + handlers.done(); + } + ); + handlers.onDestroy(() => ReactDOM.unmountComponentAtNode(domNode)); }, }); diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_expression_renderer.scss b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_expression_renderer.scss index 5d181b9c06da8..8f8dc2323b0b7 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_expression_renderer.scss +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_expression_renderer.scss @@ -1,11 +1,12 @@ .lnsExpressionRenderer { + position: relative; width: 100%; height: 100%; display: flex; overflow-x: hidden; padding: $euiSize; -} -.lnsExpressionRenderer > * { - flex: 1; + > .expExpressionRenderer { + position: static; // Let the progress indicator position itself against the outer parent + } } diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_suggestion_panel.scss b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_suggestion_panel.scss index 0e89bbe2da968..cb4ca425afc84 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_suggestion_panel.scss +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_suggestion_panel.scss @@ -16,6 +16,7 @@ } .lnsSuggestionPanel__button { + position: relative; // Let the expression progress indicator position itself against the button flex: 0 0 auto; width: $lnsSuggestionWidth !important; // sass-lint:disable-line no-important height: $lnsSuggestionHeight; @@ -45,16 +46,22 @@ .lnsSuggestionPanel__chartWrapper { display: flex; - height: $lnsSuggestionHeight - $euiSize; + height: 100%; + width: 100%; pointer-events: none; - margin: 0 $euiSizeS; + padding: $euiSizeS; + + > .expExpressionRenderer { + position: static; // Let the progress indicator position itself against the button + } } .lnsSuggestionPanel__chartWrapper--withLabel { - height: $lnsSuggestionHeight - $euiSizeL; + height: calc(100% - #{$euiSizeL}); } .lnsSuggestionPanel__buttonLabel { + @include euiTextTruncate; @include euiFontSizeXS; display: block; font-weight: $euiFontWeightBold; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_workspace_panel_wrapper.scss b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_workspace_panel_wrapper.scss index 7811df93ba8ce..3ef387eca1e8b 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_workspace_panel_wrapper.scss +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/_workspace_panel_wrapper.scss @@ -22,6 +22,7 @@ align-items: stretch; justify-content: stretch; overflow: auto; + position: relative; > * { flex: 1 1 100%; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx index e2f9bd84560de..6aee215d11591 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx @@ -63,38 +63,33 @@ const PreviewRenderer = ({ expression: string; ExpressionRendererComponent: ExpressionRenderer; }) => { - const [expressionError, setExpressionError] = useState(false); - - useEffect(() => { - setExpressionError(false); - }, [expression]); - - return expressionError ? ( -
- -
- ) : ( - { - // eslint-disable-next-line no-console - console.error(`Failed to render preview: `, e); - setExpressionError(true); - }} - /> + > + { + return ( +
+ +
+ ); + }} + /> +
); }; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx index ddb82565e4b8b..9cf59f69c0cc2 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx @@ -392,190 +392,135 @@ describe('workspace_panel', () => { expect(expressionRendererMock).toHaveBeenCalledTimes(2); }); - describe('expression failures', () => { - it('should show an error message if the expression fails to parse', () => { - mockDatasource.toExpression.mockReturnValue('|||'); - mockDatasource.getLayers.mockReturnValue(['first']); - const framePublicAPI = createMockFramePublicAPI(); - framePublicAPI.datasourceLayers = { - first: mockDatasource.publicAPIMock, - }; - - instance = mount( - 'vis' }, - }} - visualizationState={{}} - dispatch={() => {}} - ExpressionRenderer={expressionRendererMock} - core={coreMock.createSetup()} - /> - ); - - expect(instance.find('[data-test-subj="expression-failure"]').first()).toBeTruthy(); - expect(instance.find(expressionRendererMock)).toHaveLength(0); - }); - - it('should show an error message if the expression fails to render', async () => { - mockDatasource.toExpression.mockReturnValue('datasource'); - mockDatasource.getLayers.mockReturnValue(['first']); - const framePublicAPI = createMockFramePublicAPI(); - framePublicAPI.datasourceLayers = { - first: mockDatasource.publicAPIMock, - }; - expressionRendererMock = jest.fn(({ onRenderFailure }) => { - Promise.resolve().then(() => onRenderFailure!({ type: 'error' })); - return ; - }); - - instance = mount( - 'vis' }, - }} - visualizationState={{}} - dispatch={() => {}} - ExpressionRenderer={expressionRendererMock} - core={coreMock.createSetup()} - /> - ); - - // "wait" for the expression to execute - await waitForPromises(); + it('should show an error message if the expression fails to parse', () => { + mockDatasource.toExpression.mockReturnValue('|||'); + mockDatasource.getLayers.mockReturnValue(['first']); + const framePublicAPI = createMockFramePublicAPI(); + framePublicAPI.datasourceLayers = { + first: mockDatasource.publicAPIMock, + }; - instance.update(); + instance = mount( + 'vis' }, + }} + visualizationState={{}} + dispatch={() => {}} + ExpressionRenderer={expressionRendererMock} + core={coreMock.createSetup()} + /> + ); - expect(instance.find('EuiFlexItem[data-test-subj="expression-failure"]')).toHaveLength(1); - expect(instance.find(expressionRendererMock)).toHaveLength(0); - }); + expect(instance.find('[data-test-subj="expression-failure"]').first()).toBeTruthy(); + expect(instance.find(expressionRendererMock)).toHaveLength(0); + }); - it('should not attempt to run the expression again if it does not change', async () => { - mockDatasource.toExpression.mockReturnValue('datasource'); - mockDatasource.getLayers.mockReturnValue(['first']); - const framePublicAPI = createMockFramePublicAPI(); - framePublicAPI.datasourceLayers = { - first: mockDatasource.publicAPIMock, - }; - expressionRendererMock = jest.fn(({ onRenderFailure }) => { - Promise.resolve().then(() => onRenderFailure!({ type: 'error' })); - return ; - }); + it('should not attempt to run the expression again if it does not change', async () => { + mockDatasource.toExpression.mockReturnValue('datasource'); + mockDatasource.getLayers.mockReturnValue(['first']); + const framePublicAPI = createMockFramePublicAPI(); + framePublicAPI.datasourceLayers = { + first: mockDatasource.publicAPIMock, + }; - instance = mount( - 'vis' }, - }} - visualizationState={{}} - dispatch={() => {}} - ExpressionRenderer={expressionRendererMock} - core={coreMock.createSetup()} - /> - ); + instance = mount( + 'vis' }, + }} + visualizationState={{}} + dispatch={() => {}} + ExpressionRenderer={expressionRendererMock} + core={coreMock.createSetup()} + /> + ); - // "wait" for the expression to execute - await waitForPromises(); + // "wait" for the expression to execute + await waitForPromises(); - instance.update(); + instance.update(); - expect(expressionRendererMock).toHaveBeenCalledTimes(1); + expect(expressionRendererMock).toHaveBeenCalledTimes(1); - instance.update(); + instance.update(); - expect(expressionRendererMock).toHaveBeenCalledTimes(1); - }); + expect(expressionRendererMock).toHaveBeenCalledTimes(1); + }); - it('should attempt to run the expression again if changes after an error', async () => { - mockDatasource.toExpression.mockReturnValue('datasource'); - mockDatasource.getLayers.mockReturnValue(['first']); - const framePublicAPI = createMockFramePublicAPI(); - framePublicAPI.datasourceLayers = { - first: mockDatasource.publicAPIMock, - }; - expressionRendererMock = jest.fn(({ onRenderFailure }) => { - Promise.resolve().then(() => onRenderFailure!({ type: 'error' })); - return ; - }); + it('should attempt to run the expression again if it changes', async () => { + mockDatasource.toExpression.mockReturnValue('datasource'); + mockDatasource.getLayers.mockReturnValue(['first']); + const framePublicAPI = createMockFramePublicAPI(); + framePublicAPI.datasourceLayers = { + first: mockDatasource.publicAPIMock, + }; - instance = mount( - 'vis' }, - }} - visualizationState={{}} - dispatch={() => {}} - ExpressionRenderer={expressionRendererMock} - core={coreMock.createSetup()} - /> - ); + instance = mount( + 'vis' }, + }} + visualizationState={{}} + dispatch={() => {}} + ExpressionRenderer={expressionRendererMock} + core={coreMock.createSetup()} + /> + ); - // "wait" for the expression to execute - await waitForPromises(); + // "wait" for the expression to execute + await waitForPromises(); - instance.update(); + instance.update(); - expect(expressionRendererMock).toHaveBeenCalledTimes(1); + expect(expressionRendererMock).toHaveBeenCalledTimes(1); - expressionRendererMock.mockImplementation(_ => { - return ; - }); + expressionRendererMock.mockImplementation(_ => { + return ; + }); - instance.setProps({ visualizationState: {} }); - instance.update(); + instance.setProps({ visualizationState: {} }); + instance.update(); - expect(expressionRendererMock).toHaveBeenCalledTimes(2); + expect(expressionRendererMock).toHaveBeenCalledTimes(2); - expect(instance.find(expressionRendererMock)).toHaveLength(1); - }); + expect(instance.find(expressionRendererMock)).toHaveLength(1); }); describe('suggestions from dropping in workspace panel', () => { diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx index 1fb1af46f6f0d..d72bf541fd43e 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx @@ -8,15 +8,14 @@ import React, { useState, useEffect, useMemo, useContext } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { - EuiCodeBlock, EuiFlexGroup, EuiFlexItem, + EuiIcon, EuiImage, EuiText, EuiBetaBadge, EuiButtonEmpty, } from '@elastic/eui'; -import { toExpression } from '@kbn/interpreter/common'; import { CoreStart, CoreSetup } from 'src/core/public'; import { ExpressionRenderer } from '../../../../../../../src/legacy/core_plugins/expressions/public'; import { Action } from './state_management'; @@ -92,7 +91,10 @@ export function InnerWorkspacePanel({ return suggestions.find(s => s.visualizationId === activeVisualizationId) || suggestions[0]; }, [dragDropContext.dragging]); - const [expressionError, setExpressionError] = useState(undefined); + const [localState, setLocalState] = useState({ + expressionBuildError: undefined as string | undefined, + expandError: false, + }); const activeVisualization = activeVisualizationId ? visualizationMap[activeVisualizationId] @@ -107,7 +109,8 @@ export function InnerWorkspacePanel({ framePublicAPI, }); } catch (e) { - setExpressionError(e.toString()); + // Most likely an error in the expression provided by a datasource or visualization + setLocalState(s => ({ ...s, expressionBuildError: e.toString() })); } }, [ activeVisualization, @@ -178,8 +181,11 @@ export function InnerWorkspacePanel({ function renderVisualization() { useEffect(() => { // reset expression error if component attempts to run it again - if (expressionError) { - setExpressionError(undefined); + if (expression && localState.expressionBuildError) { + setLocalState(s => ({ + ...s, + expressionBuildError: undefined, + })); } }, [expression]); @@ -187,37 +193,63 @@ export function InnerWorkspacePanel({ return renderEmptyWorkspace(); } - if (expressionError) { + if (localState.expressionBuildError) { return ( - + + + + - {/* TODO word this differently because expressions should not be exposed at this level */} - {expression && ( - - {toExpression(expression)} - - )} - - {JSON.stringify(expressionError, null, 2)} - + {localState.expressionBuildError} ); - } else { - return ( + } + + return ( +
{ - setExpressionError(e); + renderError={(errorMessage?: string | null) => { + return ( + + + + + + + + {errorMessage ? ( + + { + setLocalState(prevState => ({ + ...prevState, + expandError: !prevState.expandError, + })); + }} + > + {i18n.translate('xpack.lens.editorFrame.expandRenderingErrorButton', { + defaultMessage: 'Show details of error', + })} + + + {localState.expandError ? errorMessage : null} + + ) : null} + + ); }} /> - ); - } +
+ ); } return ( diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.test.tsx index 96624764bb8ca..d728457b7e3a3 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.test.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/embeddable.test.tsx @@ -10,7 +10,6 @@ import { Query } from 'src/legacy/core_plugins/data/public'; import { ExpressionRendererProps } from 'src/legacy/core_plugins/expressions/public'; import { Filter } from '@kbn/es-query'; import { Document } from '../../persistence'; -import { act } from 'react-dom/test-utils'; jest.mock('../../../../../../../src/legacy/ui/public/inspector', () => ({ isAvailable: false, @@ -61,25 +60,6 @@ describe('embeddable', () => { expect(expressionRenderer.mock.calls[0][0]!.expression).toEqual(savedVis.expression); }); - it('should display error if expression renderering fails', () => { - const embeddable = new Embeddable( - expressionRenderer, - { - editUrl: '', - editable: true, - savedVis, - }, - { id: '123' } - ); - embeddable.render(mountpoint); - - act(() => { - expressionRenderer.mock.calls[0][0]!.onRenderFailure!({ type: 'error' }); - }); - - expect(mountpoint.innerHTML).toContain("Visualization couldn't be displayed"); - }); - it('should re-render if new input is pushed', () => { const timeRange: TimeRange = { from: 'now-15d', to: 'now' }; const query: Query = { language: 'kquery', query: '' }; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/expression_wrapper.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/expression_wrapper.tsx index daf5e0c8d0dca..bd7588fcfedae 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/expression_wrapper.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/embeddable/expression_wrapper.tsx @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { I18nProvider } from '@kbn/i18n/react'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -31,16 +31,9 @@ export function ExpressionWrapper({ expression, context, }: ExpressionWrapperProps) { - const [expressionError, setExpressionError] = useState(undefined); - useEffect(() => { - // reset expression error if component attempts to run it again - if (expressionError) { - setExpressionError(undefined); - } - }, [expression, context]); return ( - {expression === '' || expressionError ? ( + {expression === '' ? ( @@ -55,14 +48,12 @@ export function ExpressionWrapper({ ) : ( - { - setExpressionError(e); - }} - searchContext={{ ...context, type: 'kibana_context' }} - /> +
+ +
)}
); diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.tsx index 407c754284671..e70a10576106c 100644 --- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.tsx +++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_expression.tsx @@ -8,7 +8,10 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/types'; import { FormatFactory } from 'ui/visualize/loader/pipeline_helpers/utilities'; -import { IInterpreterRenderFunction } from '../../../../../../src/legacy/core_plugins/expressions/public/expressions'; +import { + IInterpreterRenderFunction, + IInterpreterRenderHandlers, +} from '../../../../../../src/legacy/core_plugins/expressions/public/expressions'; import { MetricConfig } from './types'; import { LensMultiTable } from '../types'; import { AutoScale } from './auto_scale'; @@ -80,8 +83,11 @@ export const getMetricChartRenderer = ( help: 'Metric chart renderer', validate: () => {}, reuseDomNode: true, - render: async (domNode: Element, config: MetricChartProps, _handlers: unknown) => { - ReactDOM.render(, domNode); + render: (domNode: Element, config: MetricChartProps, handlers: IInterpreterRenderHandlers) => { + ReactDOM.render(, domNode, () => { + handlers.done(); + }); + handlers.onDestroy(() => ReactDOM.unmountComponentAtNode(domNode)); }, }); diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx index 3871abcd53c1e..f55cd8f99a213 100644 --- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx +++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_expression.tsx @@ -20,6 +20,7 @@ import { } from '@elastic/charts'; import { I18nProvider } from '@kbn/i18n/react'; import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/types'; +import { IInterpreterRenderHandlers } from 'src/legacy/core_plugins/expressions/public'; import { EuiIcon, EuiText, IconType, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; @@ -104,12 +105,14 @@ export const getXyChartRenderer = (dependencies: { }), validate: () => {}, reuseDomNode: true, - render: async (domNode: Element, config: XYChartProps, _handlers: unknown) => { + render: (domNode: Element, config: XYChartProps, handlers: IInterpreterRenderHandlers) => { + handlers.onDestroy(() => ReactDOM.unmountComponentAtNode(domNode)); ReactDOM.render( , - domNode + domNode, + () => handlers.done() ); }, }); @@ -121,16 +124,18 @@ function getIconForSeriesType(seriesType: SeriesType): IconType { const MemoizedChart = React.memo(XYChart); export function XYChartReportable(props: XYChartRenderProps) { - const [isReady, setIsReady] = useState(false); + const [state, setState] = useState({ + isReady: false, + }); // It takes a cycle for the XY chart to render. This prevents // reporting from printing a blank chart placeholder. useEffect(() => { - setIsReady(true); + setState({ isReady: true }); }, []); return ( - + ); @@ -229,7 +234,11 @@ export function XYChart({ data, args, formatFactory, timeZone }: XYChartRenderPr }, index ) => { - if (!data.tables[layerId] || data.tables[layerId].rows.length === 0) { + if ( + !data.tables[layerId] || + data.tables[layerId].rows.length === 0 || + data.tables[layerId].rows.every(row => typeof row[xAccessor] === 'undefined') + ) { return; } From 7003c2c6d62ee48e6a6d82f013dac5ac73bbf93e Mon Sep 17 00:00:00 2001 From: Michael Marcialis Date: Fri, 25 Oct 2019 17:43:10 -0400 Subject: [PATCH 175/191] [SIEM] Map Docs Link & Intrinsic Ratios (#49267) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * rough out markup and intrinsic ratio poc * reorganize comps * media queries for aspect ratios * disable ratio when error; add translations * unit tests, translations & cleanup * update copy per ben’s suggestions * snapshots and translations * move paddingSize prop inline * change panel selector * fix FormattedMessage id * update snapshots --- .../__snapshots__/embeddable.test.tsx.snap | 11 ++ .../embeddable_header.test.tsx.snap | 9 ++ .../__snapshots__/embedded_map.test.tsx.snap | 25 +++- ...ndex_patterns_missing_prompt.test.tsx.snap | 56 +++++---- .../embeddables/embeddable.test.tsx | 29 +++++ .../components/embeddables/embeddable.tsx | 25 ++++ .../embeddables/embeddable_header.test.tsx | 74 ++++++++++++ .../embeddables/embeddable_header.tsx | 43 +++++++ .../components/embeddables/embedded_map.tsx | 92 +++++++++++---- .../index_patterns_missing_prompt.tsx | 109 ++++++++---------- .../components/embeddables/translations.ts | 24 ++-- .../siem/public/pages/network/network.tsx | 5 +- .../translations/translations/ja-JP.json | 3 +- .../translations/translations/zh-CN.json | 3 +- 14 files changed, 375 insertions(+), 133 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embeddable.test.tsx.snap create mode 100644 x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embeddable_header.test.tsx.snap create mode 100644 x-pack/legacy/plugins/siem/public/components/embeddables/embeddable.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/embeddables/embeddable.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.tsx diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embeddable.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embeddable.test.tsx.snap new file mode 100644 index 0000000000000..f343316d88c46 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embeddable.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Embeddable it renders 1`] = ` + + +

+ Test content +

+
+
+`; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embeddable_header.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embeddable_header.test.tsx.snap new file mode 100644 index 0000000000000..e88693b292a5d --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embeddable_header.test.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`EmbeddableHeader it renders 1`] = ` + + + +`; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embedded_map.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embedded_map.test.tsx.snap index 1f23686adca0e..bf0dfd9417875 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embedded_map.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/embedded_map.test.tsx.snap @@ -1,19 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`EmbeddedMap renders correctly against snapshot 1`] = ` - + + + + + Map configuration help + + + } > - + - - - + + `; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap index 1aa3b087ac0d0..fb896059460b9 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/__snapshots__/index_patterns_missing_prompt.test.tsx.snap @@ -15,43 +15,41 @@ exports[`IndexPatternsMissingPrompt renders correctly against snapshot 1`] = ` body={

- An ECS compliant Kibana index pattern must be configured to view event data on the map. When using beats, you can run the following setup commands to create the required Kibana index patterns, otherwise you can configure them manually within Kibana settings. + + beats + , + "example": + ./packetbeat setup + , + "setup": + setup + , + } + } + />

- - auditbeat-* - - , - - filebeat-* - - , - - packetbeat-* - - , - - winlogbeat-* - +

} iconType="gisApp" title={

- Required Index Patterns Not Configured + Required index patterns not configured

} titleSize="xs" diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable.test.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable.test.tsx new file mode 100644 index 0000000000000..49f5306dc1b60 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable.test.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { shallow } from 'enzyme'; +import toJson from 'enzyme-to-json'; +import React from 'react'; + +import '../../mock/ui_settings'; +import { TestProviders } from '../../mock'; +import { Embeddable } from './embeddable'; + +jest.mock('../../lib/settings/use_kibana_ui_setting'); + +describe('Embeddable', () => { + test('it renders', () => { + const wrapper = shallow( + + +

{'Test content'}

+
+
+ ); + + expect(toJson(wrapper)).toMatchSnapshot(); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable.tsx new file mode 100644 index 0000000000000..b9a2d01ee0a70 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable.tsx @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiPanel } from '@elastic/eui'; +import React from 'react'; +import styled from 'styled-components'; + +const Panel = styled(EuiPanel)` + overflow: hidden; +`; +Panel.displayName = 'Panel'; + +export interface EmbeddableProps { + children: React.ReactNode; +} + +export const Embeddable = React.memo(({ children }) => ( +
+ {children} +
+)); +Embeddable.displayName = 'Embeddable'; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.test.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.test.tsx new file mode 100644 index 0000000000000..4536da3ba7b97 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.test.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { mount, shallow } from 'enzyme'; +import toJson from 'enzyme-to-json'; +import React from 'react'; + +import '../../mock/ui_settings'; +import { TestProviders } from '../../mock'; +import { EmbeddableHeader } from './embeddable_header'; + +jest.mock('../../lib/settings/use_kibana_ui_setting'); + +describe('EmbeddableHeader', () => { + test('it renders', () => { + const wrapper = shallow( + + + + ); + + expect(toJson(wrapper)).toMatchSnapshot(); + }); + + test('it renders the title', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper + .find('[data-test-subj="header-embeddable-title"]') + .first() + .exists() + ).toBe(true); + }); + + test('it renders supplements when children provided', () => { + const wrapper = mount( + + +

{'Test children'}

+
+
+ ); + + expect( + wrapper + .find('[data-test-subj="header-embeddable-supplements"]') + .first() + .exists() + ).toBe(true); + }); + + test('it DOES NOT render supplements when children not provided', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper + .find('[data-test-subj="header-embeddable-supplements"]') + .first() + .exists() + ).toBe(false); + }); +}); diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.tsx new file mode 100644 index 0000000000000..dbd9e3f763f92 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embeddable_header.tsx @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; +import React from 'react'; +import styled, { css } from 'styled-components'; + +const Header = styled.header.attrs({ + className: 'siemEmbeddable__header', +})` + ${({ theme }) => css` + border-bottom: ${theme.eui.euiBorderThin}; + padding: ${theme.eui.paddingSizes.m}; + `} +`; +Header.displayName = 'Header'; + +export interface EmbeddableHeaderProps { + children?: React.ReactNode; + title: string | React.ReactNode; +} + +export const EmbeddableHeader = React.memo(({ children, title }) => ( +
+ + + +
{title}
+
+
+ + {children && ( + + {children} + + )} +
+
+)); +EmbeddableHeader.displayName = 'EmbeddableHeader'; diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx index 87e38e0fac2e1..1c712f874969c 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/embedded_map.tsx @@ -4,41 +4,74 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGroup, EuiSpacer } from '@elastic/eui'; +import { EuiLink, EuiText } from '@elastic/eui'; import { Filter } from '@kbn/es-query'; import React, { useEffect, useState } from 'react'; -import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder'; import { createPortalNode, InPortal } from 'react-reverse-portal'; import { Query } from 'src/plugins/data/common'; +import styled, { css } from 'styled-components'; +import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; +import { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder'; -import styled from 'styled-components'; -import { start } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy'; import { EmbeddablePanel } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public'; - +import { start } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public/legacy'; +import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { getIndexPatternTitleIdMapping } from '../../hooks/api/helpers'; import { useIndexPatterns } from '../../hooks/use_index_patterns'; -import { useKibanaUiSetting } from '../../lib/settings/use_kibana_ui_setting'; -import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { useKibanaPlugins } from '../../lib/compose/kibana_plugins'; import { useKibanaCore } from '../../lib/compose/kibana_core'; -import { useStateToaster } from '../toasters'; +import { useKibanaPlugins } from '../../lib/compose/kibana_plugins'; +import { useKibanaUiSetting } from '../../lib/settings/use_kibana_ui_setting'; import { Loader } from '../loader'; +import { useStateToaster } from '../toasters'; +import { Embeddable } from './embeddable'; +import { EmbeddableHeader } from './embeddable_header'; +import { createEmbeddable, displayErrorToast, setupEmbeddablesAPI } from './embedded_map_helpers'; import { IndexPatternsMissingPrompt } from './index_patterns_missing_prompt'; -import { MapEmbeddable, SetQuery } from './types'; +import { MapToolTip } from './map_tool_tip/map_tool_tip'; import * as i18n from './translations'; +import { MapEmbeddable, SetQuery } from './types'; -import { createEmbeddable, displayErrorToast, setupEmbeddablesAPI } from './embedded_map_helpers'; -import { MapToolTip } from './map_tool_tip/map_tool_tip'; +interface EmbeddableMapProps { + maintainRatio?: boolean; +} -const EmbeddableWrapper = styled(EuiFlexGroup)` - position: relative; - height: 400px; - margin: 0; +const EmbeddableMap = styled.div.attrs({ + className: 'siemEmbeddable__map', +})` + ${({ maintainRatio, theme }) => css` + .embPanel { + border: none; + box-shadow: none; + } + + .mapToolbarOverlay__button { + display: none; + } + + ${maintainRatio && + css` + padding-top: calc(3 / 4 * 100%); //4:3 (standard) ratio + position: relative; + + @media only screen and (min-width: ${theme.eui.euiBreakpoints.m}) { + padding-top: calc(9 / 32 * 100%); //32:9 (ultra widescreen) ratio + } - .mapToolbarOverlay__button { - display: none; - } + @media only screen and (min-width: 1441px) and (min-height: 901px) { + padding-top: calc(9 / 21 * 100%); //21:9 (ultrawide) ratio + } + + .embPanel { + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; + } + `} + `} `; +EmbeddableMap.displayName = 'EmbeddableMap'; export interface EmbeddedMapProps { query: Query; @@ -152,11 +185,23 @@ export const EmbeddedMap = React.memo( }, [startDate, endDate]); return isError ? null : ( - <> + + + + + {i18n.EMBEDDABLE_HEADER_HELP} + + + + - + + {embeddable != null ? ( ( ) : ( )} - - - + + ); } ); diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/index_patterns_missing_prompt.tsx b/x-pack/legacy/plugins/siem/public/components/embeddables/index_patterns_missing_prompt.tsx index 709725b853dd2..e71398455ee88 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/index_patterns_missing_prompt.tsx +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/index_patterns_missing_prompt.tsx @@ -4,69 +4,58 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; -import { EuiButton, EuiEmptyPrompt, EuiLink } from '@elastic/eui'; - +import { EuiButton, EuiCode, EuiEmptyPrompt } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; import * as React from 'react'; import chrome from 'ui/chrome'; +import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; import * as i18n from './translations'; -interface DocMapping { - beat: string; - docLink: string; -} - -export const IndexPatternsMissingPrompt = React.memo(() => { - const beatsSetupDocMapping: DocMapping[] = [ - { - beat: 'auditbeat', - docLink: `${ELASTIC_WEBSITE_URL}/guide/en/beats/auditbeat/${DOC_LINK_VERSION}/load-kibana-dashboards.html`, - }, - { - beat: 'filebeat', - docLink: `${ELASTIC_WEBSITE_URL}/guide/en/beats/filebeat/${DOC_LINK_VERSION}/load-kibana-dashboards.html`, - }, - { - beat: 'packetbeat', - docLink: `${ELASTIC_WEBSITE_URL}/guide/en/beats/packetbeat/${DOC_LINK_VERSION}/load-kibana-dashboards.html`, - }, - { - beat: 'winlogbeat', - docLink: `${ELASTIC_WEBSITE_URL}/guide/en/beats/winlogbeat/${DOC_LINK_VERSION}/load-kibana-dashboards.html`, - }, - ]; - - return ( - {i18n.ERROR_TITLE}

} - titleSize="xs" - body={ - <> -

{i18n.ERROR_DESCRIPTION}

+export const IndexPatternsMissingPrompt = React.memo(() => ( + {i18n.ERROR_TITLE}

} + titleSize="xs" + body={ + <> +

+ + {'beats'} + + ), + setup: {'setup'}, + example: {'./packetbeat setup'}, + }} + /> +

-

- {beatsSetupDocMapping - .map(v => ( - - {`${v.beat}-*`} - - )) - .reduce((acc, v) => [acc, ', ', v])} -

- - } - actions={ - - {i18n.ERROR_BUTTON} - - } - /> - ); -}); +

+ +

+ + } + actions={ + + {i18n.ERROR_BUTTON} + + } + /> +)); diff --git a/x-pack/legacy/plugins/siem/public/components/embeddables/translations.ts b/x-pack/legacy/plugins/siem/public/components/embeddables/translations.ts index 373bd1d054a43..958619bee19d3 100644 --- a/x-pack/legacy/plugins/siem/public/components/embeddables/translations.ts +++ b/x-pack/legacy/plugins/siem/public/components/embeddables/translations.ts @@ -6,6 +6,20 @@ import { i18n } from '@kbn/i18n'; +export const EMBEDDABLE_HEADER_TITLE = i18n.translate( + 'xpack.siem.components.embeddables.embeddedMap.embeddableHeaderTitle', + { + defaultMessage: 'Network map', + } +); + +export const EMBEDDABLE_HEADER_HELP = i18n.translate( + 'xpack.siem.components.embeddables.embeddedMap.embeddableHeaderHelp', + { + defaultMessage: 'Map configuration help', + } +); + export const MAP_TITLE = i18n.translate( 'xpack.siem.components.embeddables.embeddedMap.embeddablePanelTitle', { @@ -51,15 +65,7 @@ export const ERROR_CREATING_EMBEDDABLE = i18n.translate( export const ERROR_TITLE = i18n.translate( 'xpack.siem.components.embeddables.indexPatternsMissingPrompt.errorTitle', { - defaultMessage: 'Required Index Patterns Not Configured', - } -); - -export const ERROR_DESCRIPTION = i18n.translate( - 'xpack.siem.components.embeddables.indexPatternsMissingPrompt.errorDescription', - { - defaultMessage: - 'An ECS compliant Kibana index pattern must be configured to view event data on the map. When using beats, you can run the following setup commands to create the required Kibana index patterns, otherwise you can configure them manually within Kibana settings.', + defaultMessage: 'Required index patterns not configured', } ); diff --git a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx index b10c09d65426b..f7b3cfb4962fc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx @@ -14,9 +14,9 @@ import { EmbeddedMap } from '../../components/embeddables/embedded_map'; import { FiltersGlobal } from '../../components/filters_global'; import { HeaderPage } from '../../components/header_page'; import { LastEventTime } from '../../components/last_event_time'; +import { SiemNavigation } from '../../components/navigation'; import { manageQuery } from '../../components/page/manage_query'; import { KpiNetworkComponent } from '../../components/page/network'; -import { SiemNavigation } from '../../components/navigation'; import { SiemSearchBar } from '../../components/search_bar'; import { KpiNetworkQuery } from '../../containers/kpi_network'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; @@ -26,7 +26,6 @@ import { convertToBuildEsQuery } from '../../lib/keury'; import { networkModel, State, inputsSelectors } from '../../store'; import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { SpyRoute } from '../../utils/route/spy_routes'; - import { navTabsNetwork, NetworkRoutes, NetworkRoutesLoading } from './navigation'; import { NetworkEmptyPage } from './network_empty_page'; import * as i18n from './translations'; @@ -78,6 +77,8 @@ const NetworkComponent = React.memo( setQuery={setQuery} /> + + Date: Fri, 25 Oct 2019 17:22:34 -0500 Subject: [PATCH 176/191] Update dependency @elastic/charts to ^13.5.9 (#49390) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7aaf2573cc8de..289c2e8b0a8d0 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "dependencies": { "@babel/core": "^7.5.5", "@babel/register": "^7.5.5", - "@elastic/charts": "^13.5.8", + "@elastic/charts": "^13.5.9", "@elastic/datemath": "5.0.2", "@elastic/ems-client": "1.0.5", "@elastic/eui": "14.7.0", diff --git a/yarn.lock b/yarn.lock index a3752df9b024c..0c37018bdd596 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1064,10 +1064,10 @@ debug "^3.1.0" lodash.once "^4.1.1" -"@elastic/charts@^13.5.8": - version "13.5.8" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-13.5.8.tgz#ae26371e373d79cb7fe5e7394711013e1416cb81" - integrity sha512-wXz5vVKwdbOhNZwRyd1py9YdVOGHmMJ4K+PERMIJ4VwAfjHimN1qieIVAKun9vfomt/j25tDhF3Kxq3XA9W0+g== +"@elastic/charts@^13.5.9": + version "13.5.9" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-13.5.9.tgz#8e27ec7de934e20a9b853921cd453a372be99ef4" + integrity sha512-H5xsW/tEpjZhm0FpZThMyjuVBWlcXF2ImpfTWYv13p8GKmorCyQWbePau9Ya8N3lMmkHUMH2e95ifd3K3g9RgA== dependencies: "@types/d3-shape" "^1.3.1" classnames "^2.2.6" From e7d82f29d9ee651ff199c4f7feff21864f25fc6a Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 25 Oct 2019 18:42:31 -0400 Subject: [PATCH 177/191] [Uptime] Do not drop edge buckets (#48157) * Checkpoint first uptime bucket * Add code to specify interval for histogram chart, delete obsolete formatting code. * Revert file to master version. * Update usages of modified helper function. * Delete obslete snapshot. * Modify outdated tests and refresh snapshots. * Update API test fixtures and several tests to avoid flakiness. * Remove unneeded size field. * Rename a type. * Split concerns to two separate functions. * Update chart formatting label stops and casing to fit latest charts. * Remove addition of interval to x domain. * Update tests to accommodate new changes. --- .../common/constants/chart_format_limits.ts | 10 +- .../uptime/common/domain_types/monitors.ts | 7 + .../functional/charts/snapshot_histogram.tsx | 19 +- .../charts/__tests__/get_label_format.test.ts | 18 +- .../lib/helper/charts/get_chart_date_label.ts | 2 +- .../lib/helper/charts/get_label_format.ts | 15 +- .../queries/snapshot_histogram_query.ts | 5 +- .../server/graphql/monitors/resolvers.ts | 6 +- .../server/graphql/monitors/schema.gql.ts | 7 +- .../search/enrich_monitor_groups.ts | 4 +- ...lasticsearch_monitors_adapter.test.ts.snap | 14 + .../elasticsearch_monitors_adapter.ts | 14 +- .../elasticsearch_pings_adapter.test.ts.snap | 177 +++++---- .../elasticsearch_pings_adapter.test.ts | 4 +- .../lib/adapters/pings/adapter_types.ts | 5 +- .../pings/elasticsearch_pings_adapter.ts | 29 +- .../drop_latest_buckets.test.ts.snap | 9 - ...rmat_es_buckets_for_histogram.test.ts.snap | 42 -- .../__test__/drop_latest_buckets.test.ts | 25 -- .../format_es_buckets_for_histogram.test.ts | 29 -- .../__test__/get_histogram_interval.test.ts | 23 +- .../get_histogram_interval_formatted.test.ts | 35 ++ .../server/lib/helper/drop_latest_bucket.ts | 14 - .../helper/format_es_buckets_for_histogram.ts | 42 -- .../lib/helper/get_histogram_interval.ts | 6 +- .../get_histogram_interval_formatted.ts | 13 + .../plugins/uptime/server/lib/helper/index.ts | 3 +- .../graphql/fixtures/monitor_charts.json | 10 + .../graphql/fixtures/snapshot_histogram.json | 363 +++++++++--------- .../snapshot_histogram_by_filter.json | 363 +++++++++--------- .../fixtures/snapshot_histogram_by_id.json | 363 +++++++++--------- .../apis/uptime/graphql/snapshot_histogram.ts | 11 + 32 files changed, 849 insertions(+), 838 deletions(-) delete mode 100644 x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/drop_latest_buckets.test.ts.snap delete mode 100644 x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/format_es_buckets_for_histogram.test.ts.snap delete mode 100644 x-pack/legacy/plugins/uptime/server/lib/helper/__test__/drop_latest_buckets.test.ts delete mode 100644 x-pack/legacy/plugins/uptime/server/lib/helper/__test__/format_es_buckets_for_histogram.test.ts create mode 100644 x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts delete mode 100644 x-pack/legacy/plugins/uptime/server/lib/helper/drop_latest_bucket.ts delete mode 100644 x-pack/legacy/plugins/uptime/server/lib/helper/format_es_buckets_for_histogram.ts create mode 100644 x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts diff --git a/x-pack/legacy/plugins/uptime/common/constants/chart_format_limits.ts b/x-pack/legacy/plugins/uptime/common/constants/chart_format_limits.ts index 1e691b45e1792..f291450ab2a7a 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/chart_format_limits.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/chart_format_limits.ts @@ -4,8 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ +const MINUTE = 1000 * 60; +const HOUR = MINUTE * 60; const DAY = 24 * 60 * 60 * 1000; const WEEK = DAY * 7; +const MONTH = WEEK * 4; /** * These contsants are used by the charting code to determine @@ -14,9 +17,10 @@ const WEEK = DAY * 7; */ export const CHART_FORMAT_LIMITS = { DAY, - FIFTEEN_DAYS: 1000 * 60 * 60 * 24 * 15, - EIGHT_MINUTES: 1000 * 60 * 8, + EIGHT_MINUTES: MINUTE * 8, FOUR_YEARS: 4 * 12 * 4 * WEEK, - THIRTY_SIX_HOURS: 1000 * 60 * 60 * 36, + THIRTY_SIX_HOURS: HOUR * 36, THREE_WEEKS: WEEK * 3, + SIX_MONTHS: MONTH * 7, + NINE_DAYS: DAY * 9, }; diff --git a/x-pack/legacy/plugins/uptime/common/domain_types/monitors.ts b/x-pack/legacy/plugins/uptime/common/domain_types/monitors.ts index 7f5699eb7e8a4..296df279b8eec 100644 --- a/x-pack/legacy/plugins/uptime/common/domain_types/monitors.ts +++ b/x-pack/legacy/plugins/uptime/common/domain_types/monitors.ts @@ -4,7 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import { HistogramDataPoint } from '../graphql/types'; + export interface UMGqlRange { dateRangeStart: string; dateRangeEnd: string; } + +export interface HistogramResult { + histogram: HistogramDataPoint[]; + interval: number; +} diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/snapshot_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/snapshot_histogram.tsx index e39adc2868c84..a5d2d9cfc27f2 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/snapshot_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/snapshot_histogram.tsx @@ -20,13 +20,13 @@ import React, { useContext } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment'; import styled from 'styled-components'; -import { HistogramDataPoint } from '../../../../common/graphql/types'; import { getColorsMap } from './get_colors_map'; import { getChartDateLabel } from '../../../lib/helper'; import { withUptimeGraphQL, UptimeGraphQLQueryProps } from '../../higher_order'; import { snapshotHistogramQuery } from '../../../queries/snapshot_histogram_query'; import { ChartWrapper } from './chart_wrapper'; import { UptimeSettingsContext } from '../../../contexts'; +import { HistogramResult } from '../../../../common/domain_types'; const SnapshotHistogramWrapper = styled.div` margin-left: 120px; @@ -56,7 +56,7 @@ export interface SnapshotHistogramProps { } interface SnapshotHistogramQueryResult { - histogram?: HistogramDataPoint[]; + queryResult?: HistogramResult; } type Props = UptimeGraphQLQueryProps & SnapshotHistogramProps; @@ -68,7 +68,7 @@ export const SnapshotHistogramComponent = ({ loading = false, height, }: Props) => { - if (!data || !data.histogram) + if (!data || !data.queryResult) /** * TODO: the Fragment, EuiTitle, and EuiPanel should be extracted to a dumb component * that we can reuse in the subsequent return statement at the bottom of this function. @@ -107,7 +107,9 @@ export const SnapshotHistogramComponent = ({ ); - const { histogram } = data; + const { + queryResult: { histogram, interval }, + } = data; const { colors: { danger, gray }, @@ -145,7 +147,14 @@ export const SnapshotHistogramComponent = ({ })} > - + { it('creates a label with month/day and hour/minute for time between 36 hours and 4 days', () => { // Sun, 15 Jul 2001 17:53:10 GMT -> Thu, 19 Jul 2001 17:52:59 GMT - expect(getChartDateLabel(995219590000, 995565179000)).toBe('MM-dd HH:mm'); + expect(getChartDateLabel(995219590000, 995565179000)).toBe('MM-DD HH:mm'); }); it('creates a format without day/month string for delta within same day local time', () => { @@ -34,17 +34,25 @@ describe('getChartLabelFormatter', () => { it('creates a format with date/month string for delta crossing dates', () => { // Wed, 18 Jul 2001 11:06:19 GMT -> Thu, 19 Jul 2001 17:52:59 GMT - expect(getChartDateLabel(995454379000, 995565179000)).toBe('MM-dd HH:mm'); + expect(getChartDateLabel(995454379000, 995565179000)).toBe('MM-DD HH:mm'); }); it('creates a format with only month/day for delta between to eight days and two weeks', () => { // Sun, 01 Jul 2001 23:28:15 GMT -> Thu, 19 Jul 2001 17:52:59 GMT - expect(getChartDateLabel(994030095000, 995565179000)).toBe('MM-dd'); + expect(getChartDateLabel(994030095000, 995565179000)).toBe('MM-DD'); }); - it('creates a format with the year/month for range exceeding a week', () => { + it('creates a format with the date and hour/min for 36h < range < 9d', () => { + expect(getChartDateLabel(1003752000000, 1004270400000)).toBe('MM-DD HH:mm'); + }); + + it('creates a format with month/day for range between nine days and three weeks', () => { + expect(getChartDateLabel(1003752000000, 1004875200000)).toBe('MM-DD'); + }); + + it('creates a format with the year/month/day for range exceeding three weeks', () => { // Sun, 15 Jul 2001 12:27:59 GMT -> Fri, 28 Dec 2001 18:46:19 GMT - expect(getChartDateLabel(995200079000, 1009565179000)).toBe('yyyy-MM'); + expect(getChartDateLabel(995200079000, 1009565179000)).toBe('YYYY-MM-DD'); }); it('creates a format of only year for timespan > 4 years', () => { diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_chart_date_label.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_chart_date_label.ts index 3533f2667b66c..126b1d85f749f 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_chart_date_label.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_chart_date_label.ts @@ -34,7 +34,7 @@ export const getChartDateLabel = (dateRangeStart: number, dateRangeEnd: number) delta < CHART_FORMAT_LIMITS.THIRTY_SIX_HOURS && !isWithinCurrentDate(dateRangeStart, dateRangeEnd) ) { - formatString = 'MM-dd '; + formatString = 'MM-DD '; } return formatString + getLabelFormat(delta); }; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_label_format.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_label_format.ts index ad3e04f403640..668147fee8055 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_label_format.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_label_format.ts @@ -7,11 +7,12 @@ import { CHART_FORMAT_LIMITS } from '../../../../common/constants'; const { - FIFTEEN_DAYS, EIGHT_MINUTES, FOUR_YEARS, THIRTY_SIX_HOURS, THREE_WEEKS, + SIX_MONTHS, + NINE_DAYS, } = CHART_FORMAT_LIMITS; /** @@ -30,16 +31,20 @@ const dateStops: Array<{ key: number; value: string }> = [ value: 'HH:mm', }, { - key: FIFTEEN_DAYS, - value: 'MM-dd HH:mm', + key: NINE_DAYS, + value: 'MM-DD HH:mm', }, { key: THREE_WEEKS, - value: 'MM-dd', + value: 'MM-DD', + }, + { + key: SIX_MONTHS, + value: 'YYYY-MM-DD', }, { key: FOUR_YEARS, - value: 'yyyy-MM', + value: 'YYYY-MM', }, ]; diff --git a/x-pack/legacy/plugins/uptime/public/queries/snapshot_histogram_query.ts b/x-pack/legacy/plugins/uptime/public/queries/snapshot_histogram_query.ts index 37f7178d23630..7eb56ea4e9dd1 100644 --- a/x-pack/legacy/plugins/uptime/public/queries/snapshot_histogram_query.ts +++ b/x-pack/legacy/plugins/uptime/public/queries/snapshot_histogram_query.ts @@ -14,18 +14,21 @@ export const snapshotHistogramQueryString = ` $monitorId: String $statusFilter: String ) { - histogram: getSnapshotHistogram( + queryResult: getSnapshotHistogram( dateRangeStart: $dateRangeStart dateRangeEnd: $dateRangeEnd filters: $filters statusFilter: $statusFilter monitorId: $monitorId ) { + histogram { upCount downCount x x0 y + } + interval } } `; diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts b/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts index 287e80a6291ca..96a386b6a6848 100644 --- a/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts +++ b/x-pack/legacy/plugins/uptime/server/graphql/monitors/resolvers.ts @@ -17,11 +17,11 @@ import { MonitorPageTitle, Ping, Snapshot, - HistogramDataPoint, GetSnapshotHistogramQueryArgs, } from '../../../common/graphql/types'; import { UMServerLibs } from '../../lib/lib'; import { CreateUMGraphQLResolvers, UMContext } from '../types'; +import { HistogramResult } from '../../../common/domain_types'; export type UMSnapshotResolver = UMResolver< Snapshot | Promise, @@ -61,7 +61,7 @@ export type UMGetMontiorPageTitleResolver = UMResolver< >; export type UMGetSnapshotHistogram = UMResolver< - HistogramDataPoint[] | Promise, + HistogramResult | Promise, any, GetSnapshotHistogramQueryArgs, UMContext @@ -101,7 +101,7 @@ export const createMonitorsResolvers: CreateUMGraphQLResolvers = ( resolver, { dateRangeStart, dateRangeEnd, filters, monitorId, statusFilter }, { req } - ): Promise { + ): Promise { return await libs.pings.getPingHistogram( req, dateRangeStart, diff --git a/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts b/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts index d406be2e8b15b..97dcbd12fff2e 100644 --- a/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts +++ b/x-pack/legacy/plugins/uptime/server/graphql/monitors/schema.gql.ts @@ -120,6 +120,11 @@ export const monitorsSchema = gql` monitors: [LatestMonitor!] } + type HistogramResult { + histogram: [HistogramDataPoint]! + interval: UnsignedInteger! + } + type MonitorPageTitle { id: String! url: String @@ -147,7 +152,7 @@ export const monitorsSchema = gql` filters: String statusFilter: String monitorId: String - ): [HistogramDataPoint!]! + ): HistogramResult getMonitorChartsData( monitorId: String! diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/search/enrich_monitor_groups.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/search/enrich_monitor_groups.ts index 2518264292cbd..6b594d8b49118 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/search/enrich_monitor_groups.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitor_states/search/enrich_monitor_groups.ts @@ -6,7 +6,7 @@ import { get, sortBy } from 'lodash'; import { QueryContext } from '../elasticsearch_monitor_states_adapter'; -import { getHistogramInterval } from '../../../helper'; +import { getHistogramIntervalFormatted } from '../../../helper'; import { INDEX_NAMES, STATES } from '../../../../../common/constants'; import { MonitorSummary, @@ -324,7 +324,7 @@ const getHistogramForMonitors = async ( histogram: { date_histogram: { field: '@timestamp', - fixed_interval: getHistogramInterval( + fixed_interval: getHistogramIntervalFormatted( queryContext.dateRangeStart, queryContext.dateRangeEnd ), diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/__tests__/__snapshots__/elasticsearch_monitors_adapter.test.ts.snap b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/__tests__/__snapshots__/elasticsearch_monitors_adapter.test.ts.snap index 75b19d7381a62..99349f42d5750 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/__tests__/__snapshots__/elasticsearch_monitors_adapter.test.ts.snap +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/__tests__/__snapshots__/elasticsearch_monitors_adapter.test.ts.snap @@ -221,6 +221,10 @@ Object { "x": 1568412432000, "y": 1972483.25, }, + Object { + "x": 1568412468000, + "y": 1020490, + }, ], "name": "us-east-2", }, @@ -302,6 +306,10 @@ Object { "x": 1568412432000, "y": 1543307.5, }, + Object { + "x": 1568412468000, + "y": null, + }, ], "name": "us-west-4", }, @@ -421,6 +429,12 @@ Object { "up": null, "x": 1568412432000, }, + Object { + "down": null, + "total": 1, + "up": null, + "x": 1568412468000, + }, ], "statusMaxCount": 0, } diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts index c14e3dab987d7..f2d84d149344b 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/monitors/elasticsearch_monitors_adapter.ts @@ -13,12 +13,7 @@ import { Ping, LocationDurationLine, } from '../../../../common/graphql/types'; -import { - dropLatestBucket, - getFilterClause, - getHistogramInterval, - parseFilterQuery, -} from '../../helper'; +import { getFilterClause, parseFilterQuery, getHistogramIntervalFormatted } from '../../helper'; import { DatabaseAdapter } from '../database'; import { UMMonitorsAdapter } from './adapter_types'; @@ -80,7 +75,7 @@ export class ElasticsearchMonitorsAdapter implements UMMonitorsAdapter { timeseries: { date_histogram: { field: '@timestamp', - fixed_interval: getHistogramInterval(dateRangeStart, dateRangeEnd), + fixed_interval: getHistogramIntervalFormatted(dateRangeStart, dateRangeEnd), min_doc_count: 0, }, aggs: { @@ -102,10 +97,7 @@ export class ElasticsearchMonitorsAdapter implements UMMonitorsAdapter { const result = await this.database.search(request, params); - const dateHistogramBuckets = dropLatestBucket( - get(result, 'aggregations.timeseries.buckets', []) - ); - + const dateHistogramBuckets = get(result, 'aggregations.timeseries.buckets', []); /** * The code below is responsible for formatting the aggregation data we fetched above in a way * that the chart components used by the client understands. diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap index a7526739c95ac..b73595d539e93 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/__snapshots__/elasticsearch_pings_adapter.test.ts.snap @@ -1,82 +1,127 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`ElasticsearchPingsAdapter class getPingHistogram handles simple_text_query without issues 1`] = ` -Array [ - Object { - "downCount": 1, - "key": 1, - "upCount": 2, - "x": 2, - "x0": 1, - "y": 1, - }, - Object { - "downCount": 2, - "key": 2, - "upCount": 1, - "x": 3, - "x0": 2, - "y": 1, - }, -] +Object { + "histogram": Array [ + Object { + "downCount": 1, + "upCount": 2, + "x": 1, + "y": 1, + }, + Object { + "downCount": 2, + "upCount": 1, + "x": 2, + "y": 1, + }, + Object { + "downCount": 1, + "upCount": 3, + "x": 3, + "y": 1, + }, + ], + "interval": 36000, +} `; exports[`ElasticsearchPingsAdapter class getPingHistogram handles status + additional user queries 1`] = ` -Array [ - Object { - "downCount": 1, - "key": 1, - "upCount": 0, - "x": 2, - "x0": 1, - "y": 1, - }, - Object { - "downCount": 2, - "key": 2, - "upCount": 0, - "x": 3, - "x0": 2, - "y": 1, - }, -] +Object { + "histogram": Array [ + Object { + "downCount": 1, + "upCount": 0, + "x": 1, + "y": 1, + }, + Object { + "downCount": 2, + "upCount": 0, + "x": 2, + "y": 1, + }, + Object { + "downCount": 1, + "upCount": 0, + "x": 3, + "y": 1, + }, + ], + "interval": 5609564928000, +} `; exports[`ElasticsearchPingsAdapter class getPingHistogram returns a down-filtered array for when filtered by down status 1`] = ` -Array [ - Object { - "downCount": 1, - "key": 1, - "upCount": 0, - "x": 2, - "x0": 1, - "y": 1, - }, -] +Object { + "histogram": Array [ + Object { + "downCount": 1, + "upCount": 0, + "x": 1, + "y": 1, + }, + Object { + "downCount": undefined, + "upCount": 0, + "x": 2, + "y": 1, + }, + ], + "interval": 5609564928000, +} `; exports[`ElasticsearchPingsAdapter class getPingHistogram returns a down-filtered array for when filtered by up status 1`] = ` -Array [ - Object { - "downCount": 0, - "key": 1, - "upCount": 2, - "x": 2, - "x0": 1, - "y": 1, - }, -] +Object { + "histogram": Array [ + Object { + "downCount": 0, + "upCount": 2, + "x": 1, + "y": 1, + }, + Object { + "downCount": 0, + "upCount": 2, + "x": 2, + "y": 1, + }, + ], + "interval": 5609564928000, +} +`; + +exports[`ElasticsearchPingsAdapter class getPingHistogram returns a single bucket if array has 1 1`] = ` +Object { + "histogram": Array [ + Object { + "downCount": 1, + "upCount": 2, + "x": 1, + "y": 1, + }, + ], + "interval": 36000, +} `; exports[`ElasticsearchPingsAdapter class getPingHistogram returns expected result for no status filter 1`] = ` -Array [ - Object { - "downCount": 1, - "key": 1, - "upCount": 2, - "x": 2, - "x0": 1, - "y": 1, - }, -] +Object { + "histogram": Array [ + Object { + "downCount": 1, + "upCount": 2, + "x": 1, + "y": 1, + }, + Object { + "downCount": undefined, + "upCount": 2, + "x": 2, + "y": 1, + }, + ], + "interval": 36000, +} `; diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts index ec414cda7d811..5c481cd147c61 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/__tests__/elasticsearch_pings_adapter.test.ts @@ -88,7 +88,7 @@ describe('ElasticsearchPingsAdapter class', () => { }); describe('getPingHistogram', () => { - it('returns an empty array for <= 1 bucket', async () => { + it('returns a single bucket if array has 1', async () => { expect.assertions(2); const search = jest.fn(); search.mockReturnValue({ @@ -116,7 +116,7 @@ describe('ElasticsearchPingsAdapter class', () => { const pingAdapter = new ElasticsearchPingsAdapter(pingDatabase); const result = await pingAdapter.getPingHistogram(serverRequest, 'now-15m', 'now', null); expect(pingDatabase.search).toHaveBeenCalledTimes(1); - expect(result).toEqual([]); + expect(result).toMatchSnapshot(); }); it('returns expected result for no status filter', async () => { diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/adapter_types.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/adapter_types.ts index bb26e04f2fc9e..1e0cf7ec40646 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/adapter_types.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/adapter_types.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { DocCount, HistogramDataPoint, Ping, PingResults } from '../../../../common/graphql/types'; +import { DocCount, Ping, PingResults } from '../../../../common/graphql/types'; +import { HistogramResult } from '../../../../common/domain_types'; export interface UMPingsAdapter { getAll( @@ -33,7 +34,7 @@ export interface UMPingsAdapter { filters?: string | null, monitorId?: string | null, statusFilter?: string | null - ): Promise; + ): Promise; getDocCount(request: any): Promise; } diff --git a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts index 822441449a774..cad8b412f3e58 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/adapters/pings/elasticsearch_pings_adapter.ts @@ -6,17 +6,12 @@ import { get } from 'lodash'; import { INDEX_NAMES } from '../../../../common/constants'; -import { - DocCount, - HistogramDataPoint, - HttpBody, - Ping, - PingResults, -} from '../../../../common/graphql/types'; -import { formatEsBucketsForHistogram, parseFilterQuery, getFilterClause } from '../../helper'; +import { DocCount, HttpBody, Ping, PingResults } from '../../../../common/graphql/types'; +import { parseFilterQuery, getFilterClause, getHistogramIntervalFormatted } from '../../helper'; import { DatabaseAdapter, HistogramQueryResult } from '../database'; import { UMPingsAdapter } from './adapter_types'; import { getHistogramInterval } from '../../helper/get_histogram_interval'; +import { HistogramResult } from '../../../../common/domain_types'; export class ElasticsearchPingsAdapter implements UMPingsAdapter { private database: DatabaseAdapter; @@ -195,7 +190,7 @@ export class ElasticsearchPingsAdapter implements UMPingsAdapter { filters?: string | null, monitorId?: string | null, statusFilter?: string | null - ): Promise { + ): Promise { const boolFilters = parseFilterQuery(filters); const additionaFilters = []; if (monitorId) { @@ -205,6 +200,8 @@ export class ElasticsearchPingsAdapter implements UMPingsAdapter { additionaFilters.push(boolFilters); } const filter = getFilterClause(dateRangeStart, dateRangeEnd, additionaFilters); + const interval = getHistogramInterval(dateRangeStart, dateRangeEnd); + const intervalFormatted = getHistogramIntervalFormatted(dateRangeStart, dateRangeEnd); const params = { index: INDEX_NAMES.HEARTBEAT, @@ -219,7 +216,7 @@ export class ElasticsearchPingsAdapter implements UMPingsAdapter { timeseries: { date_histogram: { field: '@timestamp', - fixed_interval: getHistogramInterval(dateRangeStart, dateRangeEnd), + fixed_interval: intervalFormatted, }, aggs: { down: { @@ -244,19 +241,21 @@ export class ElasticsearchPingsAdapter implements UMPingsAdapter { const result = await this.database.search(request, params); const buckets: HistogramQueryResult[] = get(result, 'aggregations.timeseries.buckets', []); - const mappedBuckets = buckets.map(bucket => { - const key: number = get(bucket, 'key'); + const histogram = buckets.map(bucket => { + const x: number = get(bucket, 'key'); const downCount: number = get(bucket, 'down.doc_count'); const upCount: number = get(bucket, 'up.doc_count'); return { - key, + x, downCount: statusFilter && statusFilter !== 'down' ? 0 : downCount, upCount: statusFilter && statusFilter !== 'up' ? 0 : upCount, y: 1, }; }); - - return formatEsBucketsForHistogram(mappedBuckets); + return { + histogram, + interval, + }; } /** diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/drop_latest_buckets.test.ts.snap b/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/drop_latest_buckets.test.ts.snap deleted file mode 100644 index db05bb02be8a9..0000000000000 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/drop_latest_buckets.test.ts.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`dropLatestBucket drops the last of a list with greater length than 1 1`] = ` -Array [ - Object { - "prop": "val", - }, -] -`; diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/format_es_buckets_for_histogram.test.ts.snap b/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/format_es_buckets_for_histogram.test.ts.snap deleted file mode 100644 index 1b30ee1549273..0000000000000 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/__snapshots__/format_es_buckets_for_histogram.test.ts.snap +++ /dev/null @@ -1,42 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`formatEsBucketsForHistogram returns properly formatted buckets 1`] = ` -Array [ - Object { - "key": 1000, - "x": 2000, - "x0": 1000, - }, - Object { - "key": 2000, - "x": 3000, - "x0": 2000, - }, - Object { - "key": 3000, - "x": 4000, - "x0": 3000, - }, -] -`; - -exports[`formatEsBucketsForHistogram returns properly formatted object for generic call 1`] = ` -Array [ - Object { - "key": 1000, - "name": "something", - "value": 150, - "x": 2000, - "x0": 1000, - }, - Object { - "key": 2000, - "name": "something", - "value": 120, - "x": 3000, - "x0": 2000, - }, -] -`; - -exports[`formatEsBucketsForHistogram returns the provided buckets if length is below min threshold 1`] = `Array []`; diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/drop_latest_buckets.test.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/drop_latest_buckets.test.ts deleted file mode 100644 index 57ae48f0c7b63..0000000000000 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/drop_latest_buckets.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { dropLatestBucket } from '../drop_latest_bucket'; - -describe('dropLatestBucket', () => { - it('drops the last of a list with greater length than 1', () => { - const testData = [{ prop: 'val' }, { prop: 'val' }]; - const result = dropLatestBucket(testData); - expect(result).toMatchSnapshot(); - }); - it('returns an empty list when length === 1', () => { - const testData = [{ prop: 'val' }]; - const result = dropLatestBucket(testData); - expect(result).toEqual([]); - }); - it('returns an empty list when length === 0', () => { - const testData: any[] = []; - const result = dropLatestBucket(testData); - expect(result).toEqual([]); - }); -}); diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/format_es_buckets_for_histogram.test.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/format_es_buckets_for_histogram.test.ts deleted file mode 100644 index 87c6aad5da032..0000000000000 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/format_es_buckets_for_histogram.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { formatEsBucketsForHistogram } from '../format_es_buckets_for_histogram'; - -describe('formatEsBucketsForHistogram', () => { - it('returns the provided buckets if length is below min threshold', () => { - const buckets = [{ key: 1000 }]; - const result = formatEsBucketsForHistogram(buckets); - expect(result).toMatchSnapshot(); - }); - it('returns properly formatted buckets', () => { - const buckets = [{ key: 1000 }, { key: 2000 }, { key: 3000 }, { key: 4000 }]; - const result = formatEsBucketsForHistogram(buckets); - expect(result).toMatchSnapshot(); - }); - it('returns properly formatted object for generic call', () => { - const buckets = [ - { key: 1000, name: 'something', value: 150 }, - { key: 2000, name: 'something', value: 120 }, - { key: 3000, name: 'something', value: 180 }, - ]; - const result = formatEsBucketsForHistogram(buckets); - expect(result).toMatchSnapshot(); - }); -}); diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts index 83f861d3fb467..bddca1b863ce4 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval.test.ts @@ -5,29 +5,16 @@ */ import { getHistogramInterval } from '../get_histogram_interval'; +import { assertCloseTo } from '../assert_close_to'; describe('getHistogramInterval', () => { it('specifies the interval necessary to divide a given timespan into equal buckets, rounded to the nearest integer, expressed in ms', () => { - const result = getHistogramInterval('now-15m', 'now', 10); - /** - * These assertions were verbatim comparisons but that introduced - * some flakiness at the ms resolution, sometimes values like "9001ms" - * are returned. - */ - expect(result.startsWith('9000')).toBeTruthy(); - expect(result.endsWith('ms')).toBeTruthy(); - expect(result).toHaveLength(7); + const interval = getHistogramInterval('now-15m', 'now', 10); + assertCloseTo(interval, 90000, 10); }); it('will supply a default constant value for bucketCount when none is provided', () => { - const result = getHistogramInterval('now-15m', 'now'); - /** - * These assertions were verbatim comparisons but that introduced - * some flakiness at the ms resolution, sometimes values like "9001ms" - * are returned. - */ - expect(result.startsWith('3600')).toBeTruthy(); - expect(result.endsWith('ms')).toBeTruthy(); - expect(result).toHaveLength(7); + const interval = getHistogramInterval('now-15m', 'now'); + assertCloseTo(interval, 36000, 10); }); }); diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts new file mode 100644 index 0000000000000..e67a93f24b3ca --- /dev/null +++ b/x-pack/legacy/plugins/uptime/server/lib/helper/__test__/get_histogram_interval_formatted.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getHistogramIntervalFormatted } from '../get_histogram_interval_formatted'; + +describe('getHistogramIntervalFormatted', () => { + it('specifies the interval necessary to divide a given timespan into equal buckets, rounded to the nearest integer, expressed in ms', () => { + const intervalFormatted = getHistogramIntervalFormatted('now-15m', 'now', 10); + /** + * Expected result is 90000. + * These assertions were verbatim comparisons but that introduced + * some flakiness at the ms resolution, sometimes values like "9001ms" + * are returned. + */ + expect(intervalFormatted.startsWith('9000')).toBeTruthy(); + expect(intervalFormatted.endsWith('ms')).toBeTruthy(); + expect(intervalFormatted).toHaveLength(7); + }); + + it('will supply a default constant value for bucketCount when none is provided', () => { + const intervalFormatted = getHistogramIntervalFormatted('now-15m', 'now'); + /** + * Expected result is 36000. + * These assertions were verbatim comparisons but that introduced + * some flakiness at the ms resolution, sometimes values like "9001ms" + * are returned. + */ + expect(intervalFormatted.startsWith('3600')).toBeTruthy(); + expect(intervalFormatted.endsWith('ms')).toBeTruthy(); + expect(intervalFormatted).toHaveLength(7); + }); +}); diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/drop_latest_bucket.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/drop_latest_bucket.ts deleted file mode 100644 index 4d072266fa4ea..0000000000000 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/drop_latest_bucket.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -/** - * We've had numerous requests to not display semi-full buckets (i.e. it is 13:01 and the - * bounds of our bucket are 13:00-13:05). If the first bucket isn't done filling, we'll - * start out with nothing returned, otherwise we drop the most recent bucket. - * @param buckets The bucket list - */ -export const dropLatestBucket = (buckets: any[]) => - buckets.length > 1 ? buckets.slice(0, buckets.length - 1) : []; diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/format_es_buckets_for_histogram.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/format_es_buckets_for_histogram.ts deleted file mode 100644 index 1b0a2bfdfc5c0..0000000000000 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/format_es_buckets_for_histogram.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { UMESBucket, UMESHistogramBucket } from '../adapters/database'; -import { dropLatestBucket } from './drop_latest_bucket'; - -/** - * The charting library we're currently using requires histogram data points have an - * x and an x0 property, where x0 is the beginning of a data point and x provides - * the size of the point from the start. This function attempts to generalize the - * concept so any bucket that has a numeric value as its key can be put into this format. - * - * Additionally, histograms that stack horizontally instead of vertically need to have - * a y and a y0 value. We're not doing this currently but with some minor modification - * this function could provide formatting for those buckets as well. - * @param buckets The ES data to format. - */ -export function formatEsBucketsForHistogram( - buckets: T[] -): Array { - // wait for first bucket to fill up - if (buckets.length < 2) { - return []; - } - const TERMINAL_INDEX = buckets.length - 1; - const { key: terminalBucketTime } = buckets[TERMINAL_INDEX]; - // drop the most recent bucket to avoid returning incomplete bucket - return dropLatestBucket(buckets).map((item, index, array) => { - const { key } = item; - const nextItem = array[index + 1]; - const bucketSize = nextItem ? Math.abs(nextItem.key - key) : Math.abs(terminalBucketTime - key); - - return { - x: key + bucketSize, - x0: key, - ...item, - }; - }); -} diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval.ts index 107a635366a0b..0dedc3e456f51 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval.ts @@ -11,7 +11,7 @@ export const getHistogramInterval = ( dateRangeStart: string, dateRangeEnd: string, bucketCount?: number -): string => { +): number => { const from = DateMath.parse(dateRangeStart); const to = DateMath.parse(dateRangeEnd); if (from === undefined) { @@ -20,7 +20,5 @@ export const getHistogramInterval = ( if (to === undefined) { throw Error('Invalid dateRangeEnd value'); } - return `${Math.round( - (to.valueOf() - from.valueOf()) / (bucketCount || QUERY.DEFAULT_BUCKET_COUNT) - )}ms`; + return Math.round((to.valueOf() - from.valueOf()) / (bucketCount || QUERY.DEFAULT_BUCKET_COUNT)); }; diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts new file mode 100644 index 0000000000000..29af862611ca4 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/server/lib/helper/get_histogram_interval_formatted.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getHistogramInterval } from './get_histogram_interval'; + +export const getHistogramIntervalFormatted = ( + dateRangeStart: string, + dateRangeEnd: string, + bucketCount?: number +): string => `${getHistogramInterval(dateRangeStart, dateRangeEnd, bucketCount)}ms`; diff --git a/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts b/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts index a2a72825c6b98..4c88da7eca85a 100644 --- a/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts +++ b/x-pack/legacy/plugins/uptime/server/lib/helper/index.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export { dropLatestBucket } from './drop_latest_bucket'; -export { formatEsBucketsForHistogram } from './format_es_buckets_for_histogram'; export { getFilterClause } from './get_filter_clause'; export { getHistogramInterval } from './get_histogram_interval'; +export { getHistogramIntervalFormatted } from './get_histogram_interval_formatted'; export { parseFilterQuery } from './parse_filter_query'; export { assertCloseTo } from './assert_close_to'; diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_charts.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_charts.json index f5368ad7ecf0c..dbfc17a468796 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_charts.json +++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/monitor_charts.json @@ -103,6 +103,10 @@ { "x": 1568173204510, "y": null + }, + { + "x": 1568173227311, + "y": 24627 } ] } @@ -257,6 +261,12 @@ "up": null, "down": null, "total": 0 + }, + { + "x": 1568173227311, + "up": null, + "down": null, + "total": 1 } ], "statusMaxCount": 0, diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram.json index c12ec7f3847c3..cf88ccae9cb99 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram.json +++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram.json @@ -1,179 +1,188 @@ { - "histogram": [ - { - "upCount": 93, - "downCount": 7, - "x": 1568172680087, - "x0": 1568172657286, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172702888, - "x0": 1568172680087, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172725689, - "x0": 1568172702888, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172748490, - "x0": 1568172725689, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172771291, - "x0": 1568172748490, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172794092, - "x0": 1568172771291, - "y": 1 - }, - { - "upCount": 92, - "downCount": 8, - "x": 1568172816893, - "x0": 1568172794092, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172839694, - "x0": 1568172816893, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172862495, - "x0": 1568172839694, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172885296, - "x0": 1568172862495, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172908097, - "x0": 1568172885296, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172930898, - "x0": 1568172908097, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172953699, - "x0": 1568172930898, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172976500, - "x0": 1568172953699, - "y": 1 - }, - { - "upCount": 92, - "downCount": 8, - "x": 1568172999301, - "x0": 1568172976500, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173022102, - "x0": 1568172999301, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173044903, - "x0": 1568173022102, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173067704, - "x0": 1568173044903, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173090505, - "x0": 1568173067704, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173113306, - "x0": 1568173090505, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173136107, - "x0": 1568173113306, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173158908, - "x0": 1568173136107, - "y": 1 - }, - { - "upCount": 92, - "downCount": 8, - "x": 1568173181709, - "x0": 1568173158908, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173204510, - "x0": 1568173181709, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173227311, - "x0": 1568173204510, - "y": 1 - } - ] + "queryResult": { + "histogram": [ + { + "upCount": 93, + "downCount": 7, + "x": 1568172657286, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172680087, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172702888, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172725689, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172748490, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172771291, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 8, + "x": 1568172794092, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172816893, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172839694, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172862495, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172885296, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172908097, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172930898, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172953699, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 8, + "x": 1568172976500, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172999301, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173022102, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173044903, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173067704, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568173090505, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173113306, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173136107, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 8, + "x": 1568173158908, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173181709, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568173204510, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173227311, + "x0": null, + "y": 1 + } + ] + } } \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_filter.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_filter.json index f61a101ce4462..383d4acd96340 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_filter.json +++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_filter.json @@ -1,179 +1,188 @@ { - "histogram": [ - { - "upCount": 93, - "downCount": 0, - "x": 1568172680087, - "x0": 1568172657286, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172702888, - "x0": 1568172680087, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172725689, - "x0": 1568172702888, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172748490, - "x0": 1568172725689, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172771291, - "x0": 1568172748490, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172794092, - "x0": 1568172771291, - "y": 1 - }, - { - "upCount": 92, - "downCount": 0, - "x": 1568172816893, - "x0": 1568172794092, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172839694, - "x0": 1568172816893, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172862495, - "x0": 1568172839694, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172885296, - "x0": 1568172862495, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172908097, - "x0": 1568172885296, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172930898, - "x0": 1568172908097, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172953699, - "x0": 1568172930898, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568172976500, - "x0": 1568172953699, - "y": 1 - }, - { - "upCount": 92, - "downCount": 0, - "x": 1568172999301, - "x0": 1568172976500, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173022102, - "x0": 1568172999301, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568173044903, - "x0": 1568173022102, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568173067704, - "x0": 1568173044903, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568173090505, - "x0": 1568173067704, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173113306, - "x0": 1568173090505, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568173136107, - "x0": 1568173113306, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568173158908, - "x0": 1568173136107, - "y": 1 - }, - { - "upCount": 92, - "downCount": 0, - "x": 1568173181709, - "x0": 1568173158908, - "y": 1 - }, - { - "upCount": 93, - "downCount": 0, - "x": 1568173204510, - "x0": 1568173181709, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173227311, - "x0": 1568173204510, - "y": 1 - } - ] + "queryResult": { + "histogram": [ + { + "upCount": 93, + "downCount": 0, + "x": 1568172657286, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172680087, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172702888, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172725689, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172748490, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172771291, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 0, + "x": 1568172794092, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172816893, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172839694, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172862495, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172885296, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172908097, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172930898, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568172953699, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 0, + "x": 1568172976500, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172999301, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568173022102, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568173044903, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568173067704, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568173090505, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568173113306, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568173136107, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 0, + "x": 1568173158908, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568173181709, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568173204510, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 0, + "x": 1568173227311, + "x0": null, + "y": 1 + } + ] + } } \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_id.json b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_id.json index c12ec7f3847c3..cf88ccae9cb99 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_id.json +++ b/x-pack/test/api_integration/apis/uptime/graphql/fixtures/snapshot_histogram_by_id.json @@ -1,179 +1,188 @@ { - "histogram": [ - { - "upCount": 93, - "downCount": 7, - "x": 1568172680087, - "x0": 1568172657286, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172702888, - "x0": 1568172680087, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172725689, - "x0": 1568172702888, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172748490, - "x0": 1568172725689, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172771291, - "x0": 1568172748490, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172794092, - "x0": 1568172771291, - "y": 1 - }, - { - "upCount": 92, - "downCount": 8, - "x": 1568172816893, - "x0": 1568172794092, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172839694, - "x0": 1568172816893, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172862495, - "x0": 1568172839694, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172885296, - "x0": 1568172862495, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172908097, - "x0": 1568172885296, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568172930898, - "x0": 1568172908097, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172953699, - "x0": 1568172930898, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568172976500, - "x0": 1568172953699, - "y": 1 - }, - { - "upCount": 92, - "downCount": 8, - "x": 1568172999301, - "x0": 1568172976500, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173022102, - "x0": 1568172999301, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173044903, - "x0": 1568173022102, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173067704, - "x0": 1568173044903, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173090505, - "x0": 1568173067704, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173113306, - "x0": 1568173090505, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173136107, - "x0": 1568173113306, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173158908, - "x0": 1568173136107, - "y": 1 - }, - { - "upCount": 92, - "downCount": 8, - "x": 1568173181709, - "x0": 1568173158908, - "y": 1 - }, - { - "upCount": 93, - "downCount": 7, - "x": 1568173204510, - "x0": 1568173181709, - "y": 1 - }, - { - "upCount": 0, - "downCount": 0, - "x": 1568173227311, - "x0": 1568173204510, - "y": 1 - } - ] + "queryResult": { + "histogram": [ + { + "upCount": 93, + "downCount": 7, + "x": 1568172657286, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172680087, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172702888, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172725689, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172748490, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172771291, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 8, + "x": 1568172794092, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172816893, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172839694, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172862495, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172885296, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172908097, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172930898, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568172953699, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 8, + "x": 1568172976500, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568172999301, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173022102, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173044903, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173067704, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568173090505, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173113306, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173136107, + "x0": null, + "y": 1 + }, + { + "upCount": 92, + "downCount": 8, + "x": 1568173158908, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173181709, + "x0": null, + "y": 1 + }, + { + "upCount": 0, + "downCount": 0, + "x": 1568173204510, + "x0": null, + "y": 1 + }, + { + "upCount": 93, + "downCount": 7, + "x": 1568173227311, + "x0": null, + "y": 1 + } + ] + } } \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/graphql/snapshot_histogram.ts b/x-pack/test/api_integration/apis/uptime/graphql/snapshot_histogram.ts index 7af9de99d8327..02fd3fd630d4b 100644 --- a/x-pack/test/api_integration/apis/uptime/graphql/snapshot_histogram.ts +++ b/x-pack/test/api_integration/apis/uptime/graphql/snapshot_histogram.ts @@ -7,6 +7,7 @@ import { snapshotHistogramQueryString } from '../../../../../legacy/plugins/uptime/public/queries/snapshot_histogram_query'; import { expectFixtureEql } from './helpers/expect_fixture_eql'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { assertCloseTo } from '../../../../../legacy/plugins/uptime/server/lib/helper'; export default function({ getService }: FtrProviderContext) { describe('snapshotHistogram', () => { @@ -31,6 +32,10 @@ export default function({ getService }: FtrProviderContext) { .post('/api/uptime/graphql') .set('kbn-xsrf', 'foo') .send({ ...getSnapshotHistogramQuery }); + // manually testing this value and then removing it to avoid flakiness + const { interval } = data.queryResult; + assertCloseTo(interval, 22801, 100); + delete data.queryResult.interval; expectFixtureEql(data, 'snapshot_histogram'); }); @@ -50,6 +55,9 @@ export default function({ getService }: FtrProviderContext) { .post('/api/uptime/graphql') .set('kbn-xsrf', 'foo') .send({ ...getSnapshotHistogramQuery }); + const { interval } = data.queryResult; + assertCloseTo(interval, 22801, 100); + delete data.queryResult.interval; expectFixtureEql(data, 'snapshot_histogram_by_id'); }); @@ -71,6 +79,9 @@ export default function({ getService }: FtrProviderContext) { .post('/api/uptime/graphql') .set('kbn-xsrf', 'foo') .send({ ...getSnapshotHistogramQuery }); + const { interval } = data.queryResult; + assertCloseTo(interval, 22801, 100); + delete data.queryResult.interval; expectFixtureEql(data, 'snapshot_histogram_by_filter'); }); }); From 11d3445b5da225e18a92dbb1836875c4ece36bf3 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Sat, 26 Oct 2019 02:06:50 +0200 Subject: [PATCH 178/191] watch ignores resolved to plugins internals (#48629) --- src/cli/cluster/cluster_manager.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/cli/cluster/cluster_manager.js b/src/cli/cluster/cluster_manager.js index 8d56f6406ef59..a67593c02a593 100644 --- a/src/cli/cluster/cluster_manager.js +++ b/src/cli/cluster/cluster_manager.js @@ -113,7 +113,7 @@ export default class ClusterManager { ...scanDirs, ]; - const extraIgnores = scanDirs + const pluginInternalDirsIgnore = scanDirs .map(scanDir => resolve(scanDir, '*')) .concat(pluginPaths) .reduce( @@ -124,16 +124,11 @@ export default class ClusterManager { resolve(path, 'target'), resolve(path, 'scripts'), resolve(path, 'docs'), - resolve(path, 'src/legacy/server/sass/__tmp__'), - resolve(path, 'legacy/plugins/reporting/.chromium'), - resolve(path, 'legacy/plugins/siem/cypress'), - resolve(path, 'legacy/plugins/apm/cypress'), - resolve(path, 'x-pack/legacy/plugins/canvas/canvas_plugin_src') // prevents server from restarting twice for Canvas plugin changes ), [] ); - this.setupWatching(extraPaths, extraIgnores); + this.setupWatching(extraPaths, pluginInternalDirsIgnore); } else this.startCluster(); } @@ -170,7 +165,7 @@ export default class ClusterManager { .then(() => opn(openUrl)); } - setupWatching(extraPaths, extraIgnores) { + setupWatching(extraPaths, pluginInternalDirsIgnore) { const chokidar = require('chokidar'); const { fromRoot } = require('../../legacy/utils'); @@ -187,12 +182,21 @@ export default class ClusterManager { ...extraPaths, ].map(path => resolve(path)); + const ignorePaths = [ + fromRoot('src/legacy/server/sass/__tmp__'), + fromRoot('x-pack/legacy/plugins/reporting/.chromium'), + fromRoot('x-pack/legacy/plugins/siem/cypress'), + fromRoot('x-pack/legacy/plugins/apm/cypress'), + fromRoot('x-pack/legacy/plugins/canvas/canvas_plugin_src') // prevents server from restarting twice for Canvas plugin changes + ]; + this.watcher = chokidar.watch(uniq(watchPaths), { cwd: fromRoot('.'), ignored: [ /[\\\/](\..*|node_modules|bower_components|public|__[a-z0-9_]+__|coverage)[\\\/]/, /\.test\.(js|ts)$/, - ...extraIgnores, + ...pluginInternalDirsIgnore, + ...ignorePaths, 'plugins/java_languageserver' ], }); From 3e89cb54ded6a8c302bae9e40a8a70a4d4ced6a9 Mon Sep 17 00:00:00 2001 From: Nick Peihl Date: Fri, 25 Oct 2019 17:35:16 -0700 Subject: [PATCH 179/191] Remove mapping type from example url (#49425) --- docs/getting-started/tutorial-full-experience.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/tutorial-full-experience.asciidoc b/docs/getting-started/tutorial-full-experience.asciidoc index 08f65b0a24091..eafbb7d8f7c91 100644 --- a/docs/getting-started/tutorial-full-experience.asciidoc +++ b/docs/getting-started/tutorial-full-experience.asciidoc @@ -183,7 +183,7 @@ At this point, you're ready to use the Elasticsearch {ref}/docs-bulk.html[bulk] API to load the data sets: [source,shell] -curl -u elastic -H 'Content-Type: application/x-ndjson' -XPOST ':/bank/account/_bulk?pretty' --data-binary @accounts.json +curl -u elastic -H 'Content-Type: application/x-ndjson' -XPOST ':/bank/_bulk?pretty' --data-binary @accounts.json curl -u elastic -H 'Content-Type: application/x-ndjson' -XPOST ':/shakespeare/_bulk?pretty' --data-binary @shakespeare.json curl -u elastic -H 'Content-Type: application/x-ndjson' -XPOST ':/_bulk?pretty' --data-binary @logs.jsonl From 9482ba576508ab74a1da42760e7213c2c88a7147 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Sat, 26 Oct 2019 06:25:09 -0700 Subject: [PATCH 180/191] Fixed typo in formatnumber example (#49379) --- docs/canvas/canvas-function-reference.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/canvas/canvas-function-reference.asciidoc b/docs/canvas/canvas-function-reference.asciidoc index 2b437728b2d01..07f3cf028dc0e 100644 --- a/docs/canvas/canvas-function-reference.asciidoc +++ b/docs/canvas/canvas-function-reference.asciidoc @@ -1355,7 +1355,7 @@ Formats a `number` into a formatted `string` using NumeralJS. See http://numeral [source,js] ---- formatnumber format=”$0,0.00” -fortmatnumber “0.0a” +formatnumber “0.0a” ---- *Code example* From f9b0a46dfdfbbacada1f9e6c0ae024d405437641 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Sat, 26 Oct 2019 15:51:45 +0200 Subject: [PATCH 181/191] [kbn-expect] add optional error message (#48895) * [kbn-expect] add optional error message * review feedback: replace error message with provided one * add optional message for contain/string --- packages/kbn-expect/expect.js | 43 ++++++++++++++++++++++++------ packages/kbn-expect/expect.js.d.ts | 26 +++++++++--------- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/packages/kbn-expect/expect.js b/packages/kbn-expect/expect.js index 8dc8af4cab894..bc75d19d2ab1f 100644 --- a/packages/kbn-expect/expect.js +++ b/packages/kbn-expect/expect.js @@ -98,6 +98,9 @@ Assertion.prototype.assert = function (truth, msg, error, expected) { if (!ok) { err = new Error(msg.call(this)); + if (this.customMsg) { + err.message = this.customMsg; + } if (arguments.length > 3) { err.actual = this.obj; err.expected = expected; @@ -217,7 +220,10 @@ Assertion.prototype.empty = function () { */ Assertion.prototype.be = -Assertion.prototype.equal = function (obj) { +Assertion.prototype.equal = function (obj, msg) { + if (typeof(msg) === 'string') { + this.customMsg = msg; + } this.assert( obj === this.obj , function(){ return 'expected ' + i(this.obj) + ' to equal ' + i(obj) } @@ -231,7 +237,10 @@ Assertion.prototype.equal = function (obj) { * @api public */ -Assertion.prototype.eql = function (obj) { +Assertion.prototype.eql = function (obj, msg) { + if (typeof(msg) === 'string') { + this.customMsg = msg; + } this.assert( expect.eql(this.obj, obj) , function(){ return 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) } @@ -248,7 +257,10 @@ Assertion.prototype.eql = function (obj) { * @api public */ -Assertion.prototype.within = function (start, finish) { +Assertion.prototype.within = function (start, finish, msg) { + if (typeof(msg) === 'string') { + this.customMsg = msg; + } var range = start + '..' + finish; this.assert( this.obj >= start && this.obj <= finish @@ -298,7 +310,10 @@ Assertion.prototype.an = function (type) { */ Assertion.prototype.greaterThan = -Assertion.prototype.above = function (n) { +Assertion.prototype.above = function (n, msg) { + if (typeof(msg) === 'string') { + this.customMsg = msg; + } this.assert( this.obj > n , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n } @@ -314,7 +329,10 @@ Assertion.prototype.above = function (n) { */ Assertion.prototype.lessThan = -Assertion.prototype.below = function (n) { +Assertion.prototype.below = function (n, msg) { + if (typeof(msg) === 'string') { + this.customMsg = msg; + } this.assert( this.obj < n , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n } @@ -329,7 +347,10 @@ Assertion.prototype.below = function (n) { * @api public */ -Assertion.prototype.match = function (regexp) { +Assertion.prototype.match = function (regexp, msg) { + if (typeof(msg) === 'string') { + this.customMsg = msg; + } this.assert( regexp.exec(this.obj) , function(){ return 'expected ' + i(this.obj) + ' to match ' + regexp } @@ -344,7 +365,10 @@ Assertion.prototype.match = function (regexp) { * @api public */ -Assertion.prototype.length = function (n) { +Assertion.prototype.length = function (n, msg) { + if (typeof(msg) === 'string') { + this.customMsg = msg; + } expect(this.obj).to.have.property('length'); var len = this.obj.length; this.assert( @@ -410,7 +434,10 @@ Assertion.prototype.property = function (name, val) { */ Assertion.prototype.string = -Assertion.prototype.contain = function (obj) { +Assertion.prototype.contain = function (obj, msg) { + if (typeof(msg) === 'string') { + this.customMsg = msg; + } if ('string' == typeof this.obj) { this.assert( ~this.obj.indexOf(obj) diff --git a/packages/kbn-expect/expect.js.d.ts b/packages/kbn-expect/expect.js.d.ts index 2062dea686500..b957a1f9ab109 100644 --- a/packages/kbn-expect/expect.js.d.ts +++ b/packages/kbn-expect/expect.js.d.ts @@ -59,12 +59,12 @@ interface Assertion { /** * Checks if the obj exactly equals another. */ - equal(obj: any): Assertion; + equal(obj: any, msg?: string): Assertion; /** * Checks if the obj sortof equals another. */ - eql(obj: any): Assertion; + eql(obj: any, msg?: string): Assertion; /** * Assert within start to finish (inclusive). @@ -72,7 +72,7 @@ interface Assertion { * @param start * @param finish */ - within(start: number, finish: number): Assertion; + within(start: number, finish: number, msg?: string): Assertion; /** * Assert typeof. @@ -87,36 +87,36 @@ interface Assertion { /** * Assert numeric value above n. */ - greaterThan(n: number): Assertion; + greaterThan(n: number, msg?: string): Assertion; /** * Assert numeric value above n. */ - above(n: number): Assertion; + above(n: number, msg?: string): Assertion; /** * Assert numeric value below n. */ - lessThan(n: number): Assertion; + lessThan(n: number, msg?: string): Assertion; /** * Assert numeric value below n. */ - below(n: number): Assertion; + below(n: number, msg?: string): Assertion; /** * Assert string value matches regexp. * * @param regexp */ - match(regexp: RegExp): Assertion; + match(regexp: RegExp, msg?: string): Assertion; /** * Assert property "length" exists and has value of n. * * @param n */ - length(n: number): Assertion; + length(n: number, msg?: string): Assertion; /** * Assert property name exists, with optional val. @@ -129,14 +129,14 @@ interface Assertion { /** * Assert that string contains str. */ - contain(str: string): Assertion; - string(str: string): Assertion; + contain(str: string, msg?: string): Assertion; + string(str: string, msg?: string): Assertion; /** * Assert that the array contains obj. */ - contain(obj: any): Assertion; - string(obj: any): Assertion; + contain(obj: any, msg?: string): Assertion; + string(obj: any, msg?: string): Assertion; /** * Assert exact keys or inclusion of keys by using the `.own` modifier. From 795d1caa5a9644bdca68290e5c048d4bd0557c68 Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Sun, 27 Oct 2019 06:23:51 -0700 Subject: [PATCH 182/191] [SIEM] Fix host details page redirect (#48720) --- .../legacy/plugins/siem/public/pages/hosts/index.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx index 6596d4c65c00e..72b19dbbb13b2 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx @@ -229,12 +229,12 @@ export const HostsContainer = React.memo(({ url }) => ( /> ( - - )} + render={({ + match: { + params: { detailName }, + }, + location: { search = '' }, + }) => } /> Date: Mon, 28 Oct 2019 10:40:21 +0200 Subject: [PATCH 183/191] Allow plugins to register top nav menu items (regression fix) (#48542) * Move top nav menu to its own plugin Allow registering additional options from other plugins Added demo plugin * Added functional test to validate top nav registration * Improved names * Rename array * Fixed lens tests * Deleted old NavBarExtensionsRegistryProvider * Fixed top nav menu test * Attempt fixing test by clearing ui_actions on stop * temporary disable test --- .github/CODEOWNERS | 1 + .github/labeler.yml | 1 + .i18nrc.json | 1 + src/core/MIGRATION.md | 2 +- .../kibana_react/public/index.scss | 2 - .../core_plugins/kibana_react/public/index.ts | 2 - src/legacy/core_plugins/navigation/index.ts | 42 +++++++++++ .../core_plugins/navigation/package.json | 4 + .../core_plugins/navigation/public/index.scss | 3 + .../core_plugins/navigation/public/index.ts | 32 ++++++++ .../core_plugins/navigation/public/legacy.ts | 30 ++++++++ .../core_plugins/navigation/public/plugin.ts | 74 +++++++++++++++++++ .../public/top_nav_menu/_index.scss | 0 .../top_nav_menu/create_top_nav_menu.tsx | 31 ++++++++ .../public/top_nav_menu/index.ts | 1 + .../public/top_nav_menu/top_nav_menu.test.tsx | 25 +++---- .../public/top_nav_menu/top_nav_menu.tsx | 12 +-- .../public/top_nav_menu/top_nav_menu_data.tsx | 0 .../top_nav_menu_extensions_registry.ts | 46 ++++++++++++ .../top_nav_menu/top_nav_menu_item.test.tsx | 0 .../public/top_nav_menu/top_nav_menu_item.tsx | 0 .../ui/public/kbn_top_nav/kbn_top_nav.js | 3 +- src/plugins/ui_actions/public/plugin.ts | 5 +- .../plugins/kbn_tp_top_nav/index.js | 20 ++--- .../plugins/kbn_tp_top_nav/package.json | 9 +++ .../plugins/kbn_tp_top_nav/public/app.js | 54 ++++++++++++++ .../plugins/kbn_tp_top_nav/public/top_nav.tsx | 54 ++++++++++++++ .../plugins/kbn_tp_top_nav/tsconfig.json | 15 ++++ .../test_suites/core_plugins/index.js | 1 + .../test_suites/core_plugins/top_nav.js | 40 ++++++++++ .../lens/public/app_plugin/app.test.tsx | 17 +++-- .../plugins/lens/public/app_plugin/app.tsx | 4 +- 32 files changed, 487 insertions(+), 44 deletions(-) create mode 100644 src/legacy/core_plugins/navigation/index.ts create mode 100644 src/legacy/core_plugins/navigation/package.json create mode 100644 src/legacy/core_plugins/navigation/public/index.scss create mode 100644 src/legacy/core_plugins/navigation/public/index.ts create mode 100644 src/legacy/core_plugins/navigation/public/legacy.ts create mode 100644 src/legacy/core_plugins/navigation/public/plugin.ts rename src/legacy/core_plugins/{kibana_react => navigation}/public/top_nav_menu/_index.scss (100%) create mode 100644 src/legacy/core_plugins/navigation/public/top_nav_menu/create_top_nav_menu.tsx rename src/legacy/core_plugins/{kibana_react => navigation}/public/top_nav_menu/index.ts (94%) rename src/legacy/core_plugins/{kibana_react => navigation}/public/top_nav_menu/top_nav_menu.test.tsx (88%) rename src/legacy/core_plugins/{kibana_react => navigation}/public/top_nav_menu/top_nav_menu.tsx (89%) rename src/legacy/core_plugins/{kibana_react => navigation}/public/top_nav_menu/top_nav_menu_data.tsx (100%) create mode 100644 src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_extensions_registry.ts rename src/legacy/core_plugins/{kibana_react => navigation}/public/top_nav_menu/top_nav_menu_item.test.tsx (100%) rename src/legacy/core_plugins/{kibana_react => navigation}/public/top_nav_menu/top_nav_menu_item.tsx (100%) rename src/legacy/ui/public/registry/navbar_extensions.js => test/plugin_functional/plugins/kbn_tp_top_nav/index.js (74%) create mode 100644 test/plugin_functional/plugins/kbn_tp_top_nav/package.json create mode 100644 test/plugin_functional/plugins/kbn_tp_top_nav/public/app.js create mode 100644 test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx create mode 100644 test/plugin_functional/plugins/kbn_tp_top_nav/tsconfig.json create mode 100644 test/plugin_functional/test_suites/core_plugins/top_nav.js diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4ae7b27a58ee4..7001e32754abb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -10,6 +10,7 @@ /src/plugins/data/ @elastic/kibana-app-arch /src/plugins/kibana_utils/ @elastic/kibana-app-arch /src/plugins/kibana_react/ @elastic/kibana-app-arch +/src/plugins/navigation/ @elastic/kibana-app-arch # APM /x-pack/legacy/plugins/apm/ @elastic/apm-ui diff --git a/.github/labeler.yml b/.github/labeler.yml index 8a776a909cd9e..57b299912ae9e 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -2,6 +2,7 @@ - src/plugins/data/**/* - src/plugins/embeddable/**/* - src/plugins/kibana_react/**/* +- src/plugins/navigation/**/* - src/plugins/kibana_utils/**/* - src/legacy/core_plugins/dashboard_embeddable_container/**/* - src/legacy/core_plugins/data/**/* diff --git a/.i18nrc.json b/.i18nrc.json index 0ea51fe8212c4..d77293e3dc8f7 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -4,6 +4,7 @@ "data": ["src/legacy/core_plugins/data", "src/plugins/data"], "expressions": "src/legacy/core_plugins/expressions", "kibana_react": "src/legacy/core_plugins/kibana_react", + "navigation": "src/legacy/core_plugins/navigation", "server": "src/legacy/server", "console": "src/legacy/core_plugins/console", "core": "src/core", diff --git a/src/core/MIGRATION.md b/src/core/MIGRATION.md index b5942cc82941f..018a91be4c3d1 100644 --- a/src/core/MIGRATION.md +++ b/src/core/MIGRATION.md @@ -1132,7 +1132,7 @@ import { setup, start } from '../core_plugins/visualizations/public/legacy'; | `import 'ui/filter_bar'` | `import { FilterBar } from '../data/public'` | `import '../data/public/legacy` should be called to load legacy directives | | `import 'ui/query_bar'` | `import { QueryBar, QueryBarInput } from '../data/public'` | Directives are deprecated. | | `import 'ui/search_bar'` | `import { SearchBar } from '../data/public'` | Directive is deprecated. | -| `import 'ui/kbn_top_nav'` | `import { TopNavMenu } from '../kibana_react/public'` | Directive is still available in `ui/kbn_top_nav`. | +| `import 'ui/kbn_top_nav'` | `import { TopNavMenu } from '../navigation/public'` | Directive is still available in `ui/kbn_top_nav`. | | `ui/saved_objects/components/saved_object_finder` | `import { SavedObjectFinder } from '../kibana_react/public'` | | | `core_plugins/interpreter` | `data.expressions` | still in progress | | `ui/courier` | `data.search` | still in progress | diff --git a/src/legacy/core_plugins/kibana_react/public/index.scss b/src/legacy/core_plugins/kibana_react/public/index.scss index 14922ca8ee8eb..14b4687c459e1 100644 --- a/src/legacy/core_plugins/kibana_react/public/index.scss +++ b/src/legacy/core_plugins/kibana_react/public/index.scss @@ -1,5 +1,3 @@ @import 'src/legacy/ui/public/styles/styling_constants'; -@import './top_nav_menu/index'; - @import './markdown/index'; diff --git a/src/legacy/core_plugins/kibana_react/public/index.ts b/src/legacy/core_plugins/kibana_react/public/index.ts index 2497671ca98d2..7e68b6c3886ff 100644 --- a/src/legacy/core_plugins/kibana_react/public/index.ts +++ b/src/legacy/core_plugins/kibana_react/public/index.ts @@ -23,6 +23,4 @@ // of the ExpressionExectorService /** @public types */ -export { TopNavMenu, TopNavMenuData } from './top_nav_menu'; - export { Markdown, MarkdownSimple } from './markdown'; diff --git a/src/legacy/core_plugins/navigation/index.ts b/src/legacy/core_plugins/navigation/index.ts new file mode 100644 index 0000000000000..32d5f040760c6 --- /dev/null +++ b/src/legacy/core_plugins/navigation/index.ts @@ -0,0 +1,42 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { resolve } from 'path'; +import { Legacy } from '../../../../kibana'; + +// eslint-disable-next-line import/no-default-export +export default function NavigationPlugin(kibana: any) { + const config: Legacy.PluginSpecOptions = { + id: 'navigation', + require: [], + publicDir: resolve(__dirname, 'public'), + config: (Joi: any) => { + return Joi.object({ + enabled: Joi.boolean().default(true), + }).default(); + }, + init: (server: Legacy.Server) => ({}), + uiExports: { + injectDefaultVars: () => ({}), + styleSheetPaths: resolve(__dirname, 'public/index.scss'), + }, + }; + + return new kibana.Plugin(config); +} diff --git a/src/legacy/core_plugins/navigation/package.json b/src/legacy/core_plugins/navigation/package.json new file mode 100644 index 0000000000000..8fddb8e6aeced --- /dev/null +++ b/src/legacy/core_plugins/navigation/package.json @@ -0,0 +1,4 @@ +{ + "name": "navigation", + "version": "kibana" +} diff --git a/src/legacy/core_plugins/navigation/public/index.scss b/src/legacy/core_plugins/navigation/public/index.scss new file mode 100644 index 0000000000000..4c969b1a37e8c --- /dev/null +++ b/src/legacy/core_plugins/navigation/public/index.scss @@ -0,0 +1,3 @@ +@import 'src/legacy/ui/public/styles/styling_constants'; + +@import './top_nav_menu/index'; diff --git a/src/legacy/core_plugins/navigation/public/index.ts b/src/legacy/core_plugins/navigation/public/index.ts new file mode 100644 index 0000000000000..439405cc90b57 --- /dev/null +++ b/src/legacy/core_plugins/navigation/public/index.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// TODO these are imports from the old plugin world. +// Once the new platform is ready, they can get removed +// and handled by the platform itself in the setup method +// of the ExpressionExectorService + +/** @public types */ +export { TopNavMenu, TopNavMenuData } from './top_nav_menu'; +export { NavigationSetup, NavigationStart } from './plugin'; + +import { NavigationPlugin as Plugin } from './plugin'; +export function plugin() { + return new Plugin(); +} diff --git a/src/legacy/core_plugins/navigation/public/legacy.ts b/src/legacy/core_plugins/navigation/public/legacy.ts new file mode 100644 index 0000000000000..1783514e6fbdc --- /dev/null +++ b/src/legacy/core_plugins/navigation/public/legacy.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { npSetup, npStart } from 'ui/new_platform'; +import { start as dataShim } from '../../data/public/legacy'; +import { plugin } from '.'; + +const navPlugin = plugin(); + +export const setup = navPlugin.setup(npSetup.core); + +export const start = navPlugin.start(npStart.core, { + data: dataShim, +}); diff --git a/src/legacy/core_plugins/navigation/public/plugin.ts b/src/legacy/core_plugins/navigation/public/plugin.ts new file mode 100644 index 0000000000000..65a0902dec986 --- /dev/null +++ b/src/legacy/core_plugins/navigation/public/plugin.ts @@ -0,0 +1,74 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; +import { TopNavMenuExtensionsRegistry, TopNavMenuExtensionsRegistrySetup } from './top_nav_menu'; +import { createTopNav } from './top_nav_menu/create_top_nav_menu'; +import { TopNavMenuProps } from './top_nav_menu/top_nav_menu'; +import { DataStart } from '../../data/public'; + +/** + * Interface for this plugin's returned `setup` contract. + * + * @public + */ +export interface NavigationSetup { + registerMenuItem: TopNavMenuExtensionsRegistrySetup['register']; +} + +/** + * Interface for this plugin's returned `start` contract. + * + * @public + */ +export interface NavigationStart { + ui: { + TopNavMenu: React.ComponentType; + }; +} + +export interface NavigationPluginStartDependencies { + data: DataStart; +} + +export class NavigationPlugin implements Plugin { + private readonly topNavMenuExtensionsRegistry: TopNavMenuExtensionsRegistry = new TopNavMenuExtensionsRegistry(); + + public setup(core: CoreSetup): NavigationSetup { + return { + registerMenuItem: this.topNavMenuExtensionsRegistry.register.bind( + this.topNavMenuExtensionsRegistry + ), + }; + } + + public start(core: CoreStart, { data }: NavigationPluginStartDependencies): NavigationStart { + const extensions = this.topNavMenuExtensionsRegistry.getAll(); + + return { + ui: { + TopNavMenu: createTopNav(data, extensions), + }, + }; + } + + public stop() { + this.topNavMenuExtensionsRegistry.clear(); + } +} diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/_index.scss b/src/legacy/core_plugins/navigation/public/top_nav_menu/_index.scss similarity index 100% rename from src/legacy/core_plugins/kibana_react/public/top_nav_menu/_index.scss rename to src/legacy/core_plugins/navigation/public/top_nav_menu/_index.scss diff --git a/src/legacy/core_plugins/navigation/public/top_nav_menu/create_top_nav_menu.tsx b/src/legacy/core_plugins/navigation/public/top_nav_menu/create_top_nav_menu.tsx new file mode 100644 index 0000000000000..fa0e5fcac7407 --- /dev/null +++ b/src/legacy/core_plugins/navigation/public/top_nav_menu/create_top_nav_menu.tsx @@ -0,0 +1,31 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { TopNavMenuProps, TopNavMenu } from './top_nav_menu'; +import { TopNavMenuData } from './top_nav_menu_data'; +import { DataStart } from '../../../../core_plugins/data/public'; + +export function createTopNav(data: DataStart, extraConfig: TopNavMenuData[]) { + return (props: TopNavMenuProps) => { + const config = (props.config || []).concat(extraConfig); + + return ; + }; +} diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/index.ts b/src/legacy/core_plugins/navigation/public/top_nav_menu/index.ts similarity index 94% rename from src/legacy/core_plugins/kibana_react/public/top_nav_menu/index.ts rename to src/legacy/core_plugins/navigation/public/top_nav_menu/index.ts index b45baaf0e4711..dd139bbd6410f 100644 --- a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/index.ts +++ b/src/legacy/core_plugins/navigation/public/top_nav_menu/index.ts @@ -19,3 +19,4 @@ export { TopNavMenu } from './top_nav_menu'; export { TopNavMenuData } from './top_nav_menu_data'; +export * from './top_nav_menu_extensions_registry'; diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.test.tsx b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx similarity index 88% rename from src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.test.tsx rename to src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx index 21c5cef4ae925..803119bdac119 100644 --- a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.test.tsx +++ b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.test.tsx @@ -27,21 +27,11 @@ const timefilterSetupMock = timefilterServiceMock.createSetupContract(); jest.mock('ui/new_platform'); -jest.mock('../../../../../../src/legacy/core_plugins/data/public/legacy', () => ({ - start: { - ui: { - SearchBar: () => {}, - }, - }, - setup: {}, -})); - -jest.mock('../../../../core_plugins/data/public', () => { - return { +const dataShim = { + ui: { SearchBar: () =>
, - SearchBarProps: {}, - }; -}); + }, +}; describe('TopNavMenu', () => { const TOP_NAV_ITEM_SELECTOR = 'TopNavMenuItem'; @@ -84,7 +74,12 @@ describe('TopNavMenu', () => { it('Should render search bar', () => { const component = shallowWithIntl( - + ); expect(component.find(TOP_NAV_ITEM_SELECTOR).length).toBe(0); diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.tsx b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.tsx similarity index 89% rename from src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.tsx rename to src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.tsx index aec91c2aa6bc6..14599e76470c0 100644 --- a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu.tsx +++ b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu.tsx @@ -24,13 +24,13 @@ import { I18nProvider } from '@kbn/i18n/react'; import { TopNavMenuData } from './top_nav_menu_data'; import { TopNavMenuItem } from './top_nav_menu_item'; -import { SearchBarProps } from '../../../../core_plugins/data/public'; -import { start as data } from '../../../data/public/legacy'; +import { SearchBarProps, DataStart } from '../../../../core_plugins/data/public'; -type Props = Partial & { +export type TopNavMenuProps = Partial & { appName: string; config?: TopNavMenuData[]; showSearchBar?: boolean; + data?: DataStart; }; /* @@ -42,8 +42,7 @@ type Props = Partial & { * **/ -export function TopNavMenu(props: Props) { - const { SearchBar } = data.ui; +export function TopNavMenu(props: TopNavMenuProps) { const { config, showSearchBar, ...searchBarProps } = props; function renderItems() { if (!config) return; @@ -58,7 +57,8 @@ export function TopNavMenu(props: Props) { function renderSearchBar() { // Validate presense of all required fields - if (!showSearchBar) return; + if (!showSearchBar || !props.data) return; + const { SearchBar } = props.data.ui; return ; } diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu_data.tsx b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx similarity index 100% rename from src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu_data.tsx rename to src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_data.tsx diff --git a/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_extensions_registry.ts b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_extensions_registry.ts new file mode 100644 index 0000000000000..c3eab3cce18e6 --- /dev/null +++ b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_extensions_registry.ts @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { TopNavMenuData } from './top_nav_menu_data'; + +export class TopNavMenuExtensionsRegistry { + private menuItems: TopNavMenuData[]; + + constructor() { + this.menuItems = []; + } + + /** @public **/ + // Items registered into this registry will be appended to any TopNavMenu rendered in any application. + public register(menuItem: TopNavMenuData) { + this.menuItems.push(menuItem); + } + + /** @internal **/ + public getAll() { + return this.menuItems; + } + + /** @internal **/ + public clear() { + this.menuItems.length = 0; + } +} + +export type TopNavMenuExtensionsRegistrySetup = Pick; diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu_item.test.tsx b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_item.test.tsx similarity index 100% rename from src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu_item.test.tsx rename to src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_item.test.tsx diff --git a/src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu_item.tsx b/src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx similarity index 100% rename from src/legacy/core_plugins/kibana_react/public/top_nav_menu/top_nav_menu_item.tsx rename to src/legacy/core_plugins/navigation/public/top_nav_menu/top_nav_menu_item.tsx diff --git a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js index 72fa6bc4c1182..9c4cee6b05db0 100644 --- a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js +++ b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js @@ -20,7 +20,7 @@ import 'ngreact'; import { wrapInI18nContext } from 'ui/i18n'; import { uiModules } from 'ui/modules'; -import { TopNavMenu } from '../../../core_plugins/kibana_react/public'; +import { start as navigation } from '../../../core_plugins/navigation/public/legacy'; const module = uiModules.get('kibana'); @@ -76,6 +76,7 @@ export function createTopNavDirective() { module.directive('kbnTopNav', createTopNavDirective); export function createTopNavHelper(reactDirective) { + const { TopNavMenu } = navigation.ui; return reactDirective( wrapInI18nContext(TopNavMenu), [ diff --git a/src/plugins/ui_actions/public/plugin.ts b/src/plugins/ui_actions/public/plugin.ts index fda25659d1226..374acaaab3999 100644 --- a/src/plugins/ui_actions/public/plugin.ts +++ b/src/plugins/ui_actions/public/plugin.ts @@ -52,5 +52,8 @@ export class UiActionsPlugin implements Plugin return this.api; } - public stop() {} + public stop() { + this.actions.clear(); + this.triggers.clear(); + } } diff --git a/src/legacy/ui/public/registry/navbar_extensions.js b/test/plugin_functional/plugins/kbn_tp_top_nav/index.js similarity index 74% rename from src/legacy/ui/public/registry/navbar_extensions.js rename to test/plugin_functional/plugins/kbn_tp_top_nav/index.js index 6c7911c6f0f52..144050beb7868 100644 --- a/src/legacy/ui/public/registry/navbar_extensions.js +++ b/test/plugin_functional/plugins/kbn_tp_top_nav/index.js @@ -17,12 +17,14 @@ * under the License. */ -import { uiRegistry } from './_registry'; - -export const NavBarExtensionsRegistryProvider = uiRegistry({ - name: 'navbarExtensions', - index: ['name'], - group: ['appName'], - order: ['order'] -}); - +export default function (kibana) { + return new kibana.Plugin({ + uiExports: { + app: { + title: 'Top Nav Menu test', + description: 'This is a sample plugin for the functional tests.', + main: 'plugins/kbn_tp_top_nav/app', + } + } + }); +} diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/package.json b/test/plugin_functional/plugins/kbn_tp_top_nav/package.json new file mode 100644 index 0000000000000..7102d24d3292d --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_top_nav/package.json @@ -0,0 +1,9 @@ +{ + "name": "kbn_tp_top_nav", + "version": "1.0.0", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "Apache-2.0" +} diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/public/app.js b/test/plugin_functional/plugins/kbn_tp_top_nav/public/app.js new file mode 100644 index 0000000000000..e7f97e68c086d --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_top_nav/public/app.js @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { uiModules } from 'ui/modules'; +import chrome from 'ui/chrome'; + +// This is required so some default styles and required scripts/Angular modules are loaded, +// or the timezone setting is correctly applied. +import 'ui/autoload/all'; + +import { AppWithTopNav } from './top_nav'; + +const app = uiModules.get('apps/topnavDemoPlugin', ['kibana']); + +app.config($locationProvider => { + $locationProvider.html5Mode({ + enabled: false, + requireBase: false, + rewriteLinks: false, + }); +}); + +function RootController($scope, $element) { + const domNode = $element[0]; + + // render react to DOM + render(, domNode); + + // unmount react on controller destroy + $scope.$on('$destroy', () => { + unmountComponentAtNode(domNode); + }); +} + +chrome.setRootController('topnavDemoPlugin', RootController); diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx b/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx new file mode 100644 index 0000000000000..d56ac5f92db88 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_top_nav/public/top_nav.tsx @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { Component } from 'react'; +import { + setup as navSetup, + start as navStart, +} from '../../../../../src/legacy/core_plugins/navigation/public/legacy'; + +const customExtension = { + id: 'registered-prop', + label: 'Registered Button', + description: 'Registered Demo', + run() {}, + testId: 'demoRegisteredNewButton', +}; + +navSetup.registerMenuItem(customExtension); + +export class AppWithTopNav extends Component { + public render() { + const { TopNavMenu } = navStart.ui; + const config = [ + { + id: 'new', + label: 'New Button', + description: 'New Demo', + run() {}, + testId: 'demoNewButton', + }, + ]; + return ( + + Hey + + ); + } +} diff --git a/test/plugin_functional/plugins/kbn_tp_top_nav/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_top_nav/tsconfig.json new file mode 100644 index 0000000000000..1ba21f11b7de2 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_top_nav/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "../../../../typings/**/*", + ], + "exclude": [] +} diff --git a/test/plugin_functional/test_suites/core_plugins/index.js b/test/plugin_functional/test_suites/core_plugins/index.js index eeb81f67751ed..376c6f1ebadb1 100644 --- a/test/plugin_functional/test_suites/core_plugins/index.js +++ b/test/plugin_functional/test_suites/core_plugins/index.js @@ -23,5 +23,6 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./legacy_plugins')); loadTestFile(require.resolve('./server_plugins')); loadTestFile(require.resolve('./ui_plugins')); + loadTestFile(require.resolve('./top_nav')); }); } diff --git a/test/plugin_functional/test_suites/core_plugins/top_nav.js b/test/plugin_functional/test_suites/core_plugins/top_nav.js new file mode 100644 index 0000000000000..5c46e3d7f76db --- /dev/null +++ b/test/plugin_functional/test_suites/core_plugins/top_nav.js @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import expect from '@kbn/expect'; + +export default function ({ getService, getPageObjects }) { + const PageObjects = getPageObjects(['common']); + + const browser = getService('browser'); + const testSubjects = getService('testSubjects'); + + describe.skip('top nav', function describeIndexTests() { + before(async () => { + const url = `${PageObjects.common.getHostPort()}/app/kbn_tp_top_nav/`; + await browser.get(url); + }); + + it('Shows registered menu items', async () => { + const ownMenuItem = await testSubjects.find('demoNewButton'); + expect(await ownMenuItem.getVisibleText()).to.be('New Button'); + const demoRegisteredNewButton = await testSubjects.find('demoRegisteredNewButton'); + expect(await demoRegisteredNewButton.getVisibleText()).to.be('Registered Button'); + }); + }); +} diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx index 0e3e6b0381309..ea4f8edf508e1 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx @@ -17,17 +17,22 @@ import { mount } from 'enzyme'; import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; const dataStartMock = dataPluginMock.createStartContract(); -import { - TopNavMenu, - TopNavMenuData, -} from '../../../../../../src/legacy/core_plugins/kibana_react/public'; +import { TopNavMenuData } from '../../../../../../src/legacy/core_plugins/navigation/public'; import { DataStart } from '../../../../../../src/legacy/core_plugins/data/public'; import { coreMock } from 'src/core/public/mocks'; -jest.mock('../../../../../../src/legacy/core_plugins/kibana_react/public', () => ({ - TopNavMenu: jest.fn(() => null), +jest.mock('../../../../../../src/legacy/core_plugins/navigation/public/legacy', () => ({ + start: { + ui: { + TopNavMenu: jest.fn(() => null), + }, + }, })); +import { start as navigation } from '../../../../../../src/legacy/core_plugins/navigation/public/legacy'; + +const { TopNavMenu } = navigation.ui; + jest.mock('ui/new_platform'); jest.mock('../persistence'); jest.mock('src/core/public'); diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx index 1152a3de77181..375ab3aad1eaf 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx @@ -20,7 +20,7 @@ import { Query, } from 'src/legacy/core_plugins/data/public'; import { Filter } from '@kbn/es-query'; -import { TopNavMenu } from '../../../../../../src/legacy/core_plugins/kibana_react/public'; +import { start as navigation } from '../../../../../../src/legacy/core_plugins/navigation/public/legacy'; import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; import { Document, SavedObjectStore } from '../persistence'; import { EditorFrameInstance } from '../types'; @@ -163,6 +163,8 @@ export function App({ [] ); + const { TopNavMenu } = navigation.ui; + return ( Date: Mon, 28 Oct 2019 09:39:53 +0000 Subject: [PATCH 184/191] [DOCS] Changes to support the split of the Metrics Guide and the Logs Guide (#48633) * Linking to new Metrics and Logs documents * Linking to new Metrics and Logs documents --- docs/infrastructure/getting-started.asciidoc | 2 +- docs/logs/getting-started.asciidoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/infrastructure/getting-started.asciidoc b/docs/infrastructure/getting-started.asciidoc index 151a8e2928cf8..1c5645f5a6e4e 100644 --- a/docs/infrastructure/getting-started.asciidoc +++ b/docs/infrastructure/getting-started.asciidoc @@ -5,7 +5,7 @@ To get started with the Metrics app in Kibana, you need to start collecting metrics data for your infrastructure. Kibana provides step-by-step instructions to help you add metrics data. -The {infra-guide}[Infrastructure Monitoring Guide] is a good source for more detailed information and instructions. +The {metrics-guide}[Metrics Monitoring Guide] is a good source for more detailed information and instructions. [role="screenshot"] image::infrastructure/images/metrics-add-data.png[Screenshot showing Add metric data to Kibana UI] diff --git a/docs/logs/getting-started.asciidoc b/docs/logs/getting-started.asciidoc index 1ed8798a4b87f..ca09bb34c0e56 100644 --- a/docs/logs/getting-started.asciidoc +++ b/docs/logs/getting-started.asciidoc @@ -5,7 +5,7 @@ To get started with the Logs app in Kibana, you need to start collecting logs data for your infrastructure. Kibana provides step-by-step instructions to help you add logs data. -The {infra-guide}[Infrastructure Monitoring Guide] is a good source for more detailed information and instructions. +The {logs-guide}[Logs Monitoring Guide] is a good source for more detailed information and instructions. [role="screenshot"] image::logs/images/logs-add-data.png[Screenshot showing Add logging data in Kibana] From f868fa66fa40d146dc1831a8bb185d7e28f9b144 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 28 Oct 2019 11:47:59 +0100 Subject: [PATCH 185/191] [Console][Legacy Editor] Ace Range implementation not being used (#49352) * Use ace Range implementation, not interface, for instantiating * Add simple smoke test for use of Ace ranges * Update test title --- .../application/models/legacy_editor.test.ts | 69 +++++++++++++++++++ .../application/models/legacy_editor.ts | 9 ++- 2 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/legacy/core_plugins/console/np_ready/public/application/models/legacy_editor.test.ts diff --git a/src/legacy/core_plugins/console/np_ready/public/application/models/legacy_editor.test.ts b/src/legacy/core_plugins/console/np_ready/public/application/models/legacy_editor.test.ts new file mode 100644 index 0000000000000..0dc1bcc96ddee --- /dev/null +++ b/src/legacy/core_plugins/console/np_ready/public/application/models/legacy_editor.test.ts @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Range as AceRange } from 'brace'; +import { LegacyEditor } from './legacy_editor'; + +describe('Legacy Editor', () => { + const aceMock: any = { + getValue() { + return 'ok'; + }, + + getCursorPosition() { + return { + row: 1, + column: 1, + }; + }, + + getSession() { + return { + replace(range: AceRange, value: string) {}, + getLine(n: number) { + return 'line'; + }, + doc: { + getTextRange(r: any) { + return ''; + }, + }, + getState(n: number) { + return n; + }, + }; + }, + }; + + // This is to ensure that we are correctly importing Ace's Range component + it('smoke tests for updates to ranges', () => { + const legacyEditor = new LegacyEditor(aceMock); + legacyEditor.getValueInRange({ + start: { lineNumber: 1, column: 1 }, + end: { lineNumber: 2, column: 2 }, + }); + legacyEditor.replace( + { + start: { lineNumber: 1, column: 1 }, + end: { lineNumber: 2, column: 2 }, + }, + 'test!' + ); + }); +}); diff --git a/src/legacy/core_plugins/console/np_ready/public/application/models/legacy_editor.ts b/src/legacy/core_plugins/console/np_ready/public/application/models/legacy_editor.ts index 1b083adcfea76..f8c3f425a1032 100644 --- a/src/legacy/core_plugins/console/np_ready/public/application/models/legacy_editor.ts +++ b/src/legacy/core_plugins/console/np_ready/public/application/models/legacy_editor.ts @@ -17,10 +17,13 @@ * under the License. */ -import { Editor as IAceEditor, Range as AceRange } from 'brace'; +import ace from 'brace'; +import { Editor as IAceEditor } from 'brace'; import { CoreEditor, Position, Range, Token, TokensProvider } from '../../types'; import { AceTokensProvider } from '../../lib/ace_token_provider'; +const _AceRange = ace.acequire('ace/range').Range; + export class LegacyEditor implements CoreEditor { constructor(private readonly editor: IAceEditor) {} @@ -31,7 +34,7 @@ export class LegacyEditor implements CoreEditor { getValueInRange({ start, end }: Range): string { const session = this.editor.getSession(); - const aceRange = new AceRange( + const aceRange = new _AceRange( start.lineNumber - 1, start.column - 1, end.lineNumber - 1, @@ -90,7 +93,7 @@ export class LegacyEditor implements CoreEditor { } replace({ start, end }: Range, value: string): void { - const aceRange = new AceRange( + const aceRange = new _AceRange( start.lineNumber - 1, start.column - 1, end.lineNumber - 1, From d9d8398fb125ade50ac29541aed6af432e843d4b Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 28 Oct 2019 16:52:33 +0500 Subject: [PATCH 186/191] [Uptime] Issue/48845 Disable filter and Add link to location docs when no location exists (#49175) * disable search text if no item exists * update snaps --- .../__tests__/__snapshots__/filter_popover.test.tsx.snap | 2 ++ .../components/functional/filter_group/filter_popover.tsx | 3 +++ 2 files changed, 5 insertions(+) diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap index e54129015b3e9..6efce389b72f7 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap @@ -25,6 +25,7 @@ exports[`FilterPopover component does not show item list when loading 1`] = ` setSearchQuery(query)} placeholder={ isLoading @@ -98,6 +100,7 @@ export const FilterPopover = ({ {item} ))} + {id === 'location' && items.length === 0 && } ); }; From 17464f8612fdff0801cfb5e1637ad8ddfa5e5383 Mon Sep 17 00:00:00 2001 From: Maryia Lapata Date: Mon, 28 Oct 2019 15:23:18 +0300 Subject: [PATCH 187/191] [Vis: Default editor] Fix validation for bounds margin (#48216) * Fix validation for bounds margin * Update custom_extents_options.tsx * Rename isValid property * Revert boundsMargin type --- .../components/common/validation_wrapper.tsx | 23 ++++++++---------- .../custom_extents_options.test.tsx | 19 ++++++++------- .../metrics_axes/custom_extents_options.tsx | 24 ++++++++++--------- .../options/metrics_axes/y_extents.tsx | 2 +- 4 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/validation_wrapper.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/validation_wrapper.tsx index a3a41d2249b32..1dd1ab49d9a47 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/validation_wrapper.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/validation_wrapper.tsx @@ -29,7 +29,7 @@ interface ValidationWrapperProps extends VisOptionsProps { } interface Item { - valid: boolean; + isValid: boolean; } function ValidationWrapper({ @@ -37,20 +37,17 @@ function ValidationWrapper({ ...rest }: ValidationWrapperProps) { const [panelState, setPanelState] = useState({} as { [key: string]: Item }); - const isPanelValid = Object.values(panelState).every(item => item.valid); + const isPanelValid = Object.values(panelState).every(item => item.isValid); const { setValidity } = rest; - const setValidityHandler = useCallback( - (paramName: string, isValid: boolean) => { - setPanelState({ - ...panelState, - [paramName]: { - valid: isValid, - }, - }); - }, - [panelState] - ); + const setValidityHandler = useCallback((paramName: string, isValid: boolean) => { + setPanelState(state => ({ + ...state, + [paramName]: { + isValid, + }, + })); + }, []); useEffect(() => { setValidity(isPanelValid); diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.test.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.test.tsx index b55d363fa56c8..5f1779ad35304 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.test.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.test.tsx @@ -18,7 +18,7 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, mount } from 'enzyme'; import { CustomExtentsOptions, CustomExtentsOptionsProps } from './custom_extents_options'; import { YExtents } from './y_extents'; import { valueAxis } from './mocks'; @@ -55,23 +55,27 @@ describe('CustomExtentsOptions component', () => { describe('boundsMargin', () => { it('should set validity as true when value is positive', () => { - const comp = shallow(); - comp.find({ paramName: BOUNDS_MARGIN }).prop('setValue')(BOUNDS_MARGIN, 5); + defaultProps.axis.scale.boundsMargin = 5; + mount(); expect(setMultipleValidity).toBeCalledWith(BOUNDS_MARGIN, true); }); it('should set validity as true when value is empty', () => { - const comp = shallow(); - comp.find({ paramName: BOUNDS_MARGIN }).prop('setValue')(BOUNDS_MARGIN, ''); + const comp = mount(); + comp.setProps({ + axis: { ...valueAxis, scale: { ...valueAxis.scale, boundsMargin: undefined } }, + }); expect(setMultipleValidity).toBeCalledWith(BOUNDS_MARGIN, true); }); it('should set validity as false when value is negative', () => { defaultProps.axis.scale.defaultYExtents = true; - const comp = shallow(); - comp.find({ paramName: BOUNDS_MARGIN }).prop('setValue')(BOUNDS_MARGIN, -1); + const comp = mount(); + comp.setProps({ + axis: { ...valueAxis, scale: { ...valueAxis.scale, boundsMargin: -1 } }, + }); expect(setMultipleValidity).toBeCalledWith(BOUNDS_MARGIN, false); }); @@ -103,7 +107,6 @@ describe('CustomExtentsOptions component', () => { const comp = shallow(); comp.find({ paramName: DEFAULT_Y_EXTENTS }).prop('setValue')(DEFAULT_Y_EXTENTS, false); - expect(setMultipleValidity).toBeCalledWith(BOUNDS_MARGIN, true); const newScale = { ...defaultProps.axis.scale, boundsMargin: undefined, diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.tsx index e04d8e646160e..df7eedd2c0ea1 100644 --- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.tsx +++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/options/metrics_axes/custom_extents_options.tsx @@ -17,7 +17,7 @@ * under the License. */ -import React, { useState, useCallback } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { ValueAxis } from '../../../types'; @@ -38,21 +38,18 @@ function CustomExtentsOptions({ setValueAxis, setValueAxisScale, }: CustomExtentsOptionsProps) { - const [isBoundsMarginValid, setIsBoundsMarginValid] = useState(true); const invalidBoundsMarginMessage = i18n.translate( 'kbnVislibVisTypes.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin', { defaultMessage: 'Bounds margin must be greater than or equal to 0.' } ); - const setBoundsMargin = useCallback( - (paramName: 'boundsMargin', value: number | '') => { - const isValid = value === '' ? true : value >= 0; - setIsBoundsMarginValid(isValid); - setMultipleValidity('boundsMargin', isValid); + const isBoundsMarginValid = + !axis.scale.defaultYExtents || !axis.scale.boundsMargin || axis.scale.boundsMargin >= 0; - setValueAxisScale(paramName, value); - }, - [setMultipleValidity, setValueAxisScale] + const setBoundsMargin = useCallback( + (paramName: 'boundsMargin', value: number | '') => + setValueAxisScale(paramName, value === '' ? undefined : value), + [setValueAxisScale] ); const onDefaultYExtentsChange = useCallback( @@ -60,7 +57,6 @@ function CustomExtentsOptions({ const scale = { ...axis.scale, [paramName]: value }; if (!scale.defaultYExtents) { delete scale.boundsMargin; - setMultipleValidity('boundsMargin', true); } setValueAxis('scale', scale); }, @@ -79,6 +75,12 @@ function CustomExtentsOptions({ [setValueAxis, axis.scale] ); + useEffect(() => { + setMultipleValidity('boundsMargin', isBoundsMarginValid); + + return () => setMultipleValidity('boundsMargin', true); + }, [isBoundsMarginValid, setMultipleValidity]); + return ( <> setMultipleValidity('yExtents', true); - }, [isValid]); + }, [isValid, setMultipleValidity]); return ( From fb903f4f9f4686caa2824537045269385095ba76 Mon Sep 17 00:00:00 2001 From: Maryia Lapata Date: Mon, 28 Oct 2019 15:50:39 +0300 Subject: [PATCH 188/191] [Vis: Default editor] Unit tests for number list (#48412) * Add unit tests for number list * Remove unused dependency * Fix code review comments * Refactor NumberList to set model validity in one place --- .../__snapshots__/number_list.test.tsx.snap | 77 +++++++ .../__snapshots__/number_row.test.tsx.snap | 38 +++ .../number_list/number_list.test.tsx | 147 ++++++++++++ .../components/number_list/number_list.tsx | 119 +++++----- .../number_list/number_row.test.tsx | 69 ++++++ .../components/number_list/number_row.tsx | 26 ++- .../components/number_list/utils.test.ts | 218 ++++++++++++++++++ .../controls/components/number_list/utils.ts | 57 +++-- .../default/controls/percentile_ranks.tsx | 4 +- .../editors/default/controls/percentiles.tsx | 4 +- 10 files changed, 653 insertions(+), 106 deletions(-) create mode 100644 src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_list.test.tsx.snap create mode 100644 src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_row.test.tsx.snap create mode 100644 src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_list.test.tsx create mode 100644 src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.test.tsx create mode 100644 src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_list.test.tsx.snap b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_list.test.tsx.snap new file mode 100644 index 0000000000000..ab192e6fd3cbb --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_list.test.tsx.snap @@ -0,0 +1,77 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NumberList should be rendered with default set of props 1`] = ` + + + + + + + + + + + +`; diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_row.test.tsx.snap b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_row.test.tsx.snap new file mode 100644 index 0000000000000..3882425594cf3 --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/__snapshots__/number_row.test.tsx.snap @@ -0,0 +1,38 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NumberRow should be rendered with default set of props 1`] = ` + + + + + + + + +`; diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_list.test.tsx b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_list.test.tsx new file mode 100644 index 0000000000000..3faf164c365d9 --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_list.test.tsx @@ -0,0 +1,147 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; +import { mountWithIntl } from 'test_utils/enzyme_helpers'; + +import { NumberList, NumberListProps } from './number_list'; +import { NumberRow } from './number_row'; + +jest.mock('./number_row', () => ({ + NumberRow: () => 'NumberRow', +})); + +jest.mock('@elastic/eui', () => ({ + htmlIdGenerator: jest.fn(() => { + let counter = 1; + return () => `12${counter++}`; + }), + EuiSpacer: require.requireActual('@elastic/eui').EuiSpacer, + EuiFlexItem: require.requireActual('@elastic/eui').EuiFlexItem, + EuiButtonEmpty: require.requireActual('@elastic/eui').EuiButtonEmpty, + EuiFormErrorText: require.requireActual('@elastic/eui').EuiFormErrorText, +})); + +describe('NumberList', () => { + let defaultProps: NumberListProps; + + beforeEach(() => { + defaultProps = { + labelledbyId: 'numberList', + numberArray: [1, 2], + range: '[1, 10]', + showValidation: false, + unitName: 'value', + onChange: jest.fn(), + setTouched: jest.fn(), + setValidity: jest.fn(), + }; + }); + + test('should be rendered with default set of props', () => { + const comp = shallow(); + + expect(comp).toMatchSnapshot(); + }); + + test('should show an order error', () => { + defaultProps.numberArray = [3, 1]; + defaultProps.showValidation = true; + const comp = mountWithIntl(); + + expect(comp.find('EuiFormErrorText').length).toBe(1); + }); + + test('should set validity as true', () => { + mountWithIntl(); + + expect(defaultProps.setValidity).lastCalledWith(true); + }); + + test('should set validity as false when the order is invalid', () => { + defaultProps.numberArray = [3, 2]; + const comp = mountWithIntl(); + + expect(defaultProps.setValidity).lastCalledWith(false); + + comp.setProps({ numberArray: [1, 2] }); + expect(defaultProps.setValidity).lastCalledWith(true); + }); + + test('should set validity as false when there is an empty field', () => { + defaultProps.numberArray = [1, 2]; + const comp = mountWithIntl(); + + comp.setProps({ numberArray: [1, undefined] }); + expect(defaultProps.setValidity).lastCalledWith(false); + }); + + test('should set 0 when number array is empty', () => { + defaultProps.numberArray = []; + mountWithIntl(); + + expect(defaultProps.onChange).lastCalledWith([0]); + }); + + test('should add a number', () => { + const comp = shallow(); + comp.find('EuiButtonEmpty').simulate('click'); + + expect(defaultProps.onChange).lastCalledWith([1, 2, 3]); + }); + + test('should remove a number', () => { + const comp = shallow(); + const row = comp.find(NumberRow).first(); + row.prop('onDelete')(row.prop('model').id); + + expect(defaultProps.onChange).lastCalledWith([2]); + }); + + test('should disable remove button if there is one number', () => { + defaultProps.numberArray = [1]; + const comp = shallow(); + + expect( + comp + .find(NumberRow) + .first() + .prop('disableDelete') + ).toEqual(true); + }); + + test('should change value', () => { + const comp = shallow(); + const row = comp.find(NumberRow).first(); + row.prop('onChange')({ id: row.prop('model').id, value: '3' }); + + expect(defaultProps.onChange).lastCalledWith([3, 2]); + }); + + test('should call setTouched', () => { + const comp = shallow(); + comp + .find(NumberRow) + .first() + .prop('onBlur')(); + + expect(defaultProps.setTouched).toBeCalled(); + }); +}); diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_list.tsx b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_list.tsx index 54040814028f7..4aae217c1bc8d 100644 --- a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_list.tsx +++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_list.tsx @@ -17,7 +17,7 @@ * under the License. */ -import React, { Fragment, useState, useEffect } from 'react'; +import React, { Fragment, useState, useEffect, useMemo, useCallback } from 'react'; import { EuiSpacer, EuiButtonEmpty, EuiFlexItem, EuiFormErrorText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -34,16 +34,15 @@ import { getUpdatedModels, hasInvalidValues, } from './utils'; +import { useValidation } from '../../agg_utils'; -interface NumberListProps { +export interface NumberListProps { labelledbyId: string; numberArray: Array; range?: string; showValidation: boolean; unitName: string; validateAscendingOrder?: boolean; - onBlur?(): void; - onFocus?(): void; onChange(list: Array): void; setTouched(): void; setValidity(isValid: boolean): void; @@ -56,81 +55,84 @@ function NumberList({ showValidation, unitName, validateAscendingOrder = true, - onBlur, - onFocus, onChange, setTouched, setValidity, }: NumberListProps) { - const numberRange = getRange(range); + const numberRange = useMemo(() => getRange(range), [range]); const [models, setModels] = useState(getInitModelList(numberArray)); const [ascendingError, setAscendingError] = useState(EMPTY_STRING); - // responsible for discarding changes + // set up validity for each model useEffect(() => { - const updatedModels = getUpdatedModels(numberArray, models, numberRange); + let id: number | undefined; if (validateAscendingOrder) { - const isOrderValid = validateOrder(updatedModels); + const { isValidOrder, modelIndex } = validateOrder(numberArray); + id = isValidOrder ? undefined : modelIndex; setAscendingError( - isOrderValid - ? i18n.translate('common.ui.aggTypes.numberList.invalidAscOrderErrorMessage', { + isValidOrder + ? EMPTY_STRING + : i18n.translate('common.ui.aggTypes.numberList.invalidAscOrderErrorMessage', { defaultMessage: 'The values should be in ascending order.', }) - : EMPTY_STRING ); } - setModels(updatedModels); - }, [numberArray]); + setModels(state => getUpdatedModels(numberArray, state, numberRange, id)); + }, [numberArray, numberRange, validateAscendingOrder]); + // responsible for setting up an initial value ([0]) when there is no default value useEffect(() => { - setValidity(!hasInvalidValues(models)); - }, [models]); - - // resposible for setting up an initial value ([0]) when there is no default value - useEffect(() => { - onChange(models.map(({ value }) => (value === EMPTY_STRING ? undefined : value))); + if (!numberArray.length) { + onChange([models[0].value as number]); + } }, []); - const onChangeValue = ({ id, value }: { id: string; value: string }) => { - const parsedValue = parse(value); - const { isValid, errors } = validateValue(parsedValue, numberRange); - setValidity(isValid); + const isValid = !hasInvalidValues(models); + useValidation(setValidity, isValid); - const currentModel = models.find(model => model.id === id); - if (currentModel) { - currentModel.value = parsedValue; - currentModel.isInvalid = !isValid; - currentModel.errors = errors; - } + const onUpdate = useCallback( + (modelList: NumberRowModel[]) => { + setModels(modelList); + onChange(modelList.map(({ value }) => (value === EMPTY_STRING ? undefined : value))); + }, + [onChange] + ); - onUpdate(models); - }; + const onChangeValue = useCallback( + ({ id, value }: { id: string; value: string }) => { + const parsedValue = parse(value); + + onUpdate( + models.map(model => { + if (model.id === id) { + const { isInvalid, error } = validateValue(parsedValue, numberRange); + return { + id, + value: parsedValue, + isInvalid, + error, + }; + } + return model; + }) + ); + }, + [numberRange, models, onUpdate] + ); // Add an item to the end of the list - const onAdd = () => { + const onAdd = useCallback(() => { const newArray = [...models, getNextModel(models, numberRange)]; onUpdate(newArray); - }; - - const onDelete = (id: string) => { - const newArray = models.filter(model => model.id !== id); - onUpdate(newArray); - }; - - const onBlurFn = (model: NumberRowModel) => { - if (model.value === EMPTY_STRING) { - model.isInvalid = true; - } - setTouched(); - if (onBlur) { - onBlur(); - } - }; - - const onUpdate = (modelList: NumberRowModel[]) => { - setModels(modelList); - onChange(modelList.map(({ value }) => (value === EMPTY_STRING ? undefined : value))); - }; + }, [models, numberRange, onUpdate]); + + const onDelete = useCallback( + (id: string) => { + const newArray = models.filter(model => model.id !== id); + onUpdate(newArray); + }, + [models, onUpdate] + ); return ( <> @@ -143,13 +145,12 @@ function NumberList({ labelledbyId={labelledbyId} range={numberRange} onDelete={onDelete} - onFocus={onFocus} onChange={onChangeValue} - onBlur={() => onBlurFn(model)} + onBlur={setTouched} autoFocus={models.length !== 1 && arrayIndex === models.length - 1} /> - {showValidation && model.isInvalid && model.errors && model.errors.length > 0 && ( - {model.errors.join('\n')} + {showValidation && model.isInvalid && model.error && ( + {model.error} )} {models.length - 1 !== arrayIndex && } diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.test.tsx b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.test.tsx new file mode 100644 index 0000000000000..2173d92819e3d --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.test.tsx @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { NumberRow, NumberRowProps } from './number_row'; + +describe('NumberRow', () => { + let defaultProps: NumberRowProps; + + beforeEach(() => { + defaultProps = { + autoFocus: false, + disableDelete: false, + isInvalid: false, + labelledbyId: 'numberList', + model: { value: 1, id: '1', isInvalid: false }, + range: { + min: 1, + max: 10, + minInclusive: true, + maxInclusive: true, + within: jest.fn(() => true), + }, + onChange: jest.fn(), + onBlur: jest.fn(), + onDelete: jest.fn(), + }; + }); + + test('should be rendered with default set of props', () => { + const comp = shallow(); + + expect(comp).toMatchSnapshot(); + }); + + test('should call onDelete', () => { + const comp = shallow(); + comp.find('EuiButtonIcon').simulate('click'); + + expect(defaultProps.onDelete).lastCalledWith(defaultProps.model.id); + }); + + test('should call onChange', () => { + const comp = shallow(); + comp.find('EuiFieldNumber').prop('onChange')!({ target: { value: '5' } } as React.ChangeEvent< + HTMLInputElement + >); + + expect(defaultProps.onChange).lastCalledWith({ id: defaultProps.model.id, value: '5' }); + }); +}); diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.tsx b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.tsx index cef574e806e01..23e671180e980 100644 --- a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.tsx +++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/number_row.tsx @@ -17,13 +17,13 @@ * under the License. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { EuiFieldNumber, EuiFlexGroup, EuiFlexItem, EuiButtonIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Range } from '../../../../../../utils/range'; -interface NumberRowProps { +export interface NumberRowProps { autoFocus: boolean; disableDelete: boolean; isInvalid: boolean; @@ -31,7 +31,6 @@ interface NumberRowProps { model: NumberRowModel; range: Range; onBlur(): void; - onFocus?(): void; onChange({ id, value }: { id: string; value: string }): void; onDelete(index: string): void; } @@ -40,7 +39,7 @@ export interface NumberRowModel { id: string; isInvalid: boolean; value: number | ''; - errors?: string[]; + error?: string; } function NumberRow({ @@ -52,7 +51,6 @@ function NumberRow({ range, onBlur, onDelete, - onFocus, onChange, }: NumberRowProps) { const deleteBtnAriaLabel = i18n.translate( @@ -63,11 +61,16 @@ function NumberRow({ } ); - const onValueChanged = (event: React.ChangeEvent) => - onChange({ - value: event.target.value, - id: model.id, - }); + const onValueChanged = useCallback( + (event: React.ChangeEvent) => + onChange({ + value: event.target.value, + id: model.id, + }), + [onChange, model.id] + ); + + const onDeleteFn = useCallback(() => onDelete(model.id), [onDelete, model.id]); return ( @@ -81,7 +84,6 @@ function NumberRow({ defaultMessage: 'Enter a value', })} onChange={onValueChanged} - onFocus={onFocus} value={model.value} fullWidth={true} min={range.min} @@ -95,7 +97,7 @@ function NumberRow({ title={deleteBtnAriaLabel} color="danger" iconType="trash" - onClick={() => onDelete(model.id)} + onClick={onDeleteFn} disabled={disableDelete} />
diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts new file mode 100644 index 0000000000000..3928c0a62eeaa --- /dev/null +++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.test.ts @@ -0,0 +1,218 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { + getInitModelList, + getUpdatedModels, + validateOrder, + hasInvalidValues, + parse, + validateValue, + getNextModel, + getRange, +} from './utils'; +import { Range } from '../../../../../../utils/range'; +import { NumberRowModel } from './number_row'; + +describe('NumberList utils', () => { + let modelList: NumberRowModel[]; + let range: Range; + + beforeEach(() => { + modelList = [{ value: 1, id: '1', isInvalid: false }, { value: 2, id: '2', isInvalid: false }]; + range = { + min: 1, + max: 10, + minInclusive: true, + maxInclusive: true, + within: jest.fn(() => true), + }; + }); + + describe('getInitModelList', () => { + test('should return list with default model when number list is empty', () => { + const models = getInitModelList([]); + + expect(models).toEqual([{ value: 0, id: expect.any(String), isInvalid: false }]); + }); + + test('should return model list', () => { + const models = getInitModelList([1, undefined]); + + expect(models).toEqual([ + { value: 1, id: expect.any(String), isInvalid: false }, + { value: '', id: expect.any(String), isInvalid: false }, + ]); + }); + }); + + describe('getUpdatedModels', () => { + test('should return model list when number list is empty', () => { + const updatedModelList = getUpdatedModels([], modelList, range); + + expect(updatedModelList).toEqual([{ value: 0, id: expect.any(String), isInvalid: false }]); + }); + + test('should not update model list when number list is the same', () => { + const updatedModelList = getUpdatedModels([1, 2], modelList, range); + + expect(updatedModelList).toEqual(modelList); + }); + + test('should update model list when number list was changed', () => { + const updatedModelList = getUpdatedModels([1, 3], modelList, range); + modelList[1].value = 3; + expect(updatedModelList).toEqual(modelList); + }); + + test('should update model list when number list increased', () => { + const updatedModelList = getUpdatedModels([1, 2, 3], modelList, range); + expect(updatedModelList).toEqual([ + ...modelList, + { value: 3, id: expect.any(String), isInvalid: false }, + ]); + }); + + test('should update model list when number list decreased', () => { + const updatedModelList = getUpdatedModels([2], modelList, range); + expect(updatedModelList).toEqual([{ value: 2, id: '1', isInvalid: false }]); + }); + + test('should update model list when number list has undefined value', () => { + const updatedModelList = getUpdatedModels([1, undefined], modelList, range); + modelList[1].value = ''; + modelList[1].isInvalid = true; + expect(updatedModelList).toEqual(modelList); + }); + + test('should update model list when number order is invalid', () => { + const updatedModelList = getUpdatedModels([1, 3, 2], modelList, range, 2); + expect(updatedModelList).toEqual([ + modelList[0], + { ...modelList[1], value: 3 }, + { value: 2, id: expect.any(String), isInvalid: true }, + ]); + }); + }); + + describe('validateOrder', () => { + test('should return true when order is valid', () => { + expect(validateOrder([1, 2])).toEqual({ + isValidOrder: true, + }); + }); + + test('should return true when a number is undefined', () => { + expect(validateOrder([1, undefined])).toEqual({ + isValidOrder: true, + }); + }); + + test('should return false when order is invalid', () => { + expect(validateOrder([2, 1])).toEqual({ + isValidOrder: false, + modelIndex: 1, + }); + }); + }); + + describe('hasInvalidValues', () => { + test('should return false when there are no invalid models', () => { + expect(hasInvalidValues(modelList)).toBeFalsy(); + }); + + test('should return true when there is an invalid model', () => { + modelList[1].isInvalid = true; + expect(hasInvalidValues(modelList)).toBeTruthy(); + }); + }); + + describe('parse', () => { + test('should return a number', () => { + expect(parse('3')).toBe(3); + }); + + test('should return an empty string when value is invalid', () => { + expect(parse('')).toBe(''); + expect(parse('test')).toBe(''); + expect(parse('NaN')).toBe(''); + }); + }); + + describe('validateValue', () => { + test('should return valid', () => { + expect(validateValue(3, range)).toEqual({ isInvalid: false }); + }); + + test('should return invalid', () => { + range.within = jest.fn(() => false); + expect(validateValue(11, range)).toEqual({ isInvalid: true, error: expect.any(String) }); + }); + }); + + describe('getNextModel', () => { + test('should return 3 as next value', () => { + expect(getNextModel(modelList, range)).toEqual({ + value: 3, + id: expect.any(String), + isInvalid: false, + }); + }); + + test('should return 1 as next value', () => { + expect(getNextModel([{ value: '', id: '2', isInvalid: false }], range)).toEqual({ + value: 1, + id: expect.any(String), + isInvalid: false, + }); + }); + + test('should return 9 as next value', () => { + expect(getNextModel([{ value: 11, id: '2', isInvalid: false }], range)).toEqual({ + value: 9, + id: expect.any(String), + isInvalid: false, + }); + }); + }); + + describe('getRange', () => { + test('should return default range', () => { + expect(getRange()).toEqual({ + min: 0, + max: Infinity, + maxInclusive: false, + minInclusive: true, + }); + }); + + test('should return parsed range', () => { + expect(getRange('(-Infinity, 100]')).toEqual({ + min: -Infinity, + max: 100, + maxInclusive: true, + minInclusive: false, + }); + }); + + test('should throw an error', () => { + expect(() => getRange('test')).toThrowError(); + }); + }); +}); diff --git a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.ts b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.ts index f90f545aeffba..563e8f0a6a9b7 100644 --- a/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.ts +++ b/src/legacy/ui/public/vis/editors/default/controls/components/number_list/utils.ts @@ -27,6 +27,7 @@ import { NumberRowModel } from './number_row'; const EMPTY_STRING = ''; const defaultRange = parseRange('[0,Infinity)'); const generateId = htmlIdGenerator(); +const defaultModel = { value: 0, id: generateId(), isInvalid: false }; function parse(value: string) { const parsedValue = parseFloat(value); @@ -42,44 +43,37 @@ function getRange(range?: string): Range { } function validateValue(value: number | '', numberRange: Range) { - const result = { - isValid: true, - errors: [] as string[], + const result: { isInvalid: boolean; error?: string } = { + isInvalid: false, }; if (value === EMPTY_STRING) { - result.isValid = false; + result.isInvalid = true; } else if (!numberRange.within(value)) { - result.isValid = false; - result.errors.push( - i18n.translate('common.ui.aggTypes.numberList.invalidRangeErrorMessage', { - defaultMessage: 'The value should be in the range of {min} to {max}.', - values: { min: numberRange.min, max: numberRange.max }, - }) - ); + result.isInvalid = true; + result.error = i18n.translate('common.ui.aggTypes.numberList.invalidRangeErrorMessage', { + defaultMessage: 'The value should be in the range of {min} to {max}.', + values: { min: numberRange.min, max: numberRange.max }, + }); } return result; } -function validateOrder(list: NumberRowModel[]) { - let isInvalidOrder = false; - list.forEach((model, index, array) => { - const previousModel = array[index - 1]; - if (previousModel && model.value !== EMPTY_STRING) { - const isInvalidOrderOfItem = model.value <= previousModel.value; - - if (!model.isInvalid && isInvalidOrderOfItem) { - model.isInvalid = true; - } +function validateOrder(list: Array) { + const result: { isValidOrder: boolean; modelIndex?: number } = { + isValidOrder: true, + }; - if (isInvalidOrderOfItem) { - isInvalidOrder = true; - } + list.forEach((inputValue, index, array) => { + const previousModel = array[index - 1]; + if (previousModel !== undefined && inputValue !== undefined && inputValue <= previousModel) { + result.isValidOrder = false; + result.modelIndex = index; } }); - return isInvalidOrder; + return result; } function getNextModel(list: NumberRowModel[], range: Range): NumberRowModel { @@ -104,26 +98,27 @@ function getInitModelList(list: Array): NumberRowModel[] { id: generateId(), isInvalid: false, })) - : [{ value: 0, id: generateId(), isInvalid: false }]; + : [defaultModel]; } function getUpdatedModels( numberList: Array, modelList: NumberRowModel[], - numberRange: Range + numberRange: Range, + invalidOrderModelIndex?: number ): NumberRowModel[] { if (!numberList.length) { - return modelList; + return [defaultModel]; } return numberList.map((number, index) => { const model = modelList[index] || { id: generateId() }; const newValue: NumberRowModel['value'] = number === undefined ? EMPTY_STRING : number; - const { isValid, errors } = validateValue(newValue, numberRange); + const { isInvalid, error } = validateValue(newValue, numberRange); return { ...model, value: newValue, - isInvalid: !isValid, - errors, + isInvalid: invalidOrderModelIndex === index ? true : isInvalid, + error, }; }); } diff --git a/src/legacy/ui/public/vis/editors/default/controls/percentile_ranks.tsx b/src/legacy/ui/public/vis/editors/default/controls/percentile_ranks.tsx index 8b63bb23475b2..420bf8a87c3d5 100644 --- a/src/legacy/ui/public/vis/editors/default/controls/percentile_ranks.tsx +++ b/src/legacy/ui/public/vis/editors/default/controls/percentile_ranks.tsx @@ -37,7 +37,7 @@ function PercentileRanksEditor({ }); const [isValid, setIsValid] = useState(true); - const setModelValidy = (isListValid: boolean) => { + const setModelValidity = (isListValid: boolean) => { setIsValid(isListValid); setValidity(isListValid); }; @@ -62,7 +62,7 @@ function PercentileRanksEditor({ showValidation={showValidation} onChange={setValue} setTouched={setTouched} - setValidity={setModelValidy} + setValidity={setModelValidity} /> ); diff --git a/src/legacy/ui/public/vis/editors/default/controls/percentiles.tsx b/src/legacy/ui/public/vis/editors/default/controls/percentiles.tsx index 158ae3442ff0c..b8ad212edead9 100644 --- a/src/legacy/ui/public/vis/editors/default/controls/percentiles.tsx +++ b/src/legacy/ui/public/vis/editors/default/controls/percentiles.tsx @@ -37,7 +37,7 @@ function PercentilesEditor({ }); const [isValid, setIsValid] = useState(true); - const setModelValidy = (isListValid: boolean) => { + const setModelValidity = (isListValid: boolean) => { setIsValid(isListValid); setValidity(isListValid); }; @@ -62,7 +62,7 @@ function PercentilesEditor({ showValidation={showValidation} onChange={setValue} setTouched={setTouched} - setValidity={setModelValidy} + setValidity={setModelValidity} /> ); From 49804a264579f3034510661f2200f30e3a14ca31 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 28 Oct 2019 13:54:47 +0100 Subject: [PATCH 189/191] [Console] Restore completer behaviour (#49422) * Restore completer behaviour * Move ace logic into shim and update getCursor -> getCursorPosition --- .../public/quarantined/src/autocomplete.ts | 15 +++++++-------- .../console/public/quarantined/src/input.ts | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/legacy/core_plugins/console/public/quarantined/src/autocomplete.ts b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete.ts index 41869f41c222f..47edf42f0eec5 100644 --- a/src/legacy/core_plugins/console/public/quarantined/src/autocomplete.ts +++ b/src/legacy/core_plugins/console/public/quarantined/src/autocomplete.ts @@ -317,16 +317,16 @@ export default function({ coreEditor: editor, parser, execCommand, - getCursor, - isCompleteActive, + getCursorPosition, + isCompleterActive, addChangeListener, removeChangeListener, }: { coreEditor: LegacyEditor; parser: any; execCommand: (cmd: string) => void; - getCursor: () => any; - isCompleteActive: () => boolean; + getCursorPosition: () => Position | null; + isCompleterActive: () => boolean; addChangeListener: (fn: any) => void; removeChangeListener: (fn: any) => void; }) { @@ -969,11 +969,10 @@ export default function({ 100); function editorChangeListener() { - const cursor = getCursor(); - if (isCompleteActive()) { - return; + const position = getCursorPosition(); + if (position && !isCompleterActive()) { + evaluateCurrentTokenAfterAChange(position); } - evaluateCurrentTokenAfterAChange(cursor); } function getCompletions( diff --git a/src/legacy/core_plugins/console/public/quarantined/src/input.ts b/src/legacy/core_plugins/console/public/quarantined/src/input.ts index a5e38e7a06e0e..eb93f8e165cb5 100644 --- a/src/legacy/core_plugins/console/public/quarantined/src/input.ts +++ b/src/legacy/core_plugins/console/public/quarantined/src/input.ts @@ -24,6 +24,7 @@ import { LegacyEditor } from '../../../np_ready/public/application/models'; // @ts-ignore import SenseEditor from './sense_editor/editor'; +import { Position } from '../../../np_ready/public/types'; let input: any; export function initializeEditor($el: JQuery, $actionsEl: JQuery) { @@ -35,8 +36,18 @@ export function initializeEditor($el: JQuery, $actionsEl: JQuery input.execCommand(cmd), - getCursor: () => input.selection.lead, - isCompleteActive: () => input.__ace.completer && input.__ace.completer.activated, + getCursorPosition: (): Position | null => { + if (input.selection && input.selection.lead) { + return { + lineNumber: input.selection.lead.row + 1, + column: input.selection.lead.column + 1, + }; + } + return null; + }, + isCompleterActive: () => { + return Boolean(input.__ace.completer && input.__ace.completer.activated); + }, addChangeListener: (fn: any) => input.on('changeSelection', fn), removeChangeListener: (fn: any) => input.off('changeSelection', fn), }; From d01099778bc454e9d6a6b6c2b010bee9715406a7 Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Mon, 28 Oct 2019 14:16:49 +0100 Subject: [PATCH 190/191] [SIEM] Refactor hosts routing (#47459) --- .../details/__snapshots__/body.test.tsx.snap | 15 -- .../public/pages/hosts/details/body.test.tsx | 99 -------- .../siem/public/pages/hosts/details/body.tsx | 106 --------- .../pages/hosts/details/details_tabs.test.tsx | 108 +++++++++ .../pages/hosts/details/details_tabs.tsx | 100 +++++++++ .../siem/public/pages/hosts/details/index.tsx | 204 +++++++++-------- .../siem/public/pages/hosts/details/types.ts | 33 ++- .../siem/public/pages/hosts/details/utils.ts | 11 +- .../siem/public/pages/hosts/hosts.test.tsx | 4 +- .../plugins/siem/public/pages/hosts/hosts.tsx | 143 ++++++------ .../siem/public/pages/hosts/hosts_body.tsx | 96 -------- .../siem/public/pages/hosts/hosts_tabs.tsx | 87 +++++++ .../plugins/siem/public/pages/hosts/index.tsx | 212 ++---------------- .../plugins/siem/public/pages/hosts/types.ts | 45 ++++ 14 files changed, 581 insertions(+), 682 deletions(-) delete mode 100644 x-pack/legacy/plugins/siem/public/pages/hosts/details/__snapshots__/body.test.tsx.snap delete mode 100644 x-pack/legacy/plugins/siem/public/pages/hosts/details/body.test.tsx delete mode 100644 x-pack/legacy/plugins/siem/public/pages/hosts/details/body.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.test.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx delete mode 100644 x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx create mode 100644 x-pack/legacy/plugins/siem/public/pages/hosts/types.ts diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/__snapshots__/body.test.tsx.snap b/x-pack/legacy/plugins/siem/public/pages/hosts/details/__snapshots__/body.test.tsx.snap deleted file mode 100644 index 3815b319820ef..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/__snapshots__/body.test.tsx.snap +++ /dev/null @@ -1,15 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`body render snapshot 1`] = ` - - - - - -`; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.test.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.test.tsx deleted file mode 100644 index 83af0a616a660..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.test.tsx +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { shallow, mount } from 'enzyme'; -import toJson from 'enzyme-to-json'; -import React from 'react'; -import { StaticIndexPattern } from 'ui/index_patterns'; - -import { mockIndexPattern } from '../../../mock/index_pattern'; -import { TestProviders } from '../../../mock/test_providers'; -import { mockUiSettings } from '../../../mock/ui_settings'; -import { CommonChildren } from '../navigation/types'; -import { HostDetailsBody } from './body'; -import { useKibanaCore } from '../../../lib/compose/kibana_core'; - -const mockUseKibanaCore = useKibanaCore as jest.Mock; -jest.mock('../../../lib/compose/kibana_core'); -mockUseKibanaCore.mockImplementation(() => ({ - uiSettings: mockUiSettings, -})); - -jest.mock('../../../containers/source', () => ({ - indicesExistOrDataTemporarilyUnavailable: () => true, - WithSource: ({ - children, - }: { - children: (args: { - indicesExist: boolean; - indexPattern: StaticIndexPattern; - }) => React.ReactNode; - }) => children({ indicesExist: true, indexPattern: mockIndexPattern }), -})); - -describe('body', () => { - test('render snapshot', () => { - const child: CommonChildren = () => {'I am a child'}; - const wrapper = shallow( - - {}} - to={0} - /> - - ); - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - test('it should pass expected object properties to children', () => { - const child = jest.fn(); - mount( - - {}} - to={0} - /> - - ); - // match against everything but the functions to ensure they are there as expected - expect(child.mock.calls[0][0]).toMatchObject({ - endDate: 0, - filterQuery: - '{"bool":{"must":[],"filter":[{"match_all":{}},{"match_phrase":{"host.name":{"query":"host-1"}}}],"should":[],"must_not":[]}}', - skip: false, - startDate: 0, - type: 'details', - indexPattern: { - fields: [ - { name: '@timestamp', searchable: true, type: 'date', aggregatable: true }, - { name: '@version', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.ephemeral_id', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.hostname', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.id', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test1', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test2', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test3', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test4', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test5', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test6', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test7', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test8', searchable: true, type: 'string', aggregatable: true }, - { name: 'host.name', searchable: true, type: 'string', aggregatable: true }, - ], - title: 'filebeat-*,auditbeat-*,packetbeat-*', - }, - hostName: 'host-1', - }); - }); -}); diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.tsx deleted file mode 100644 index ae8ebcf41cd56..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/body.tsx +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { getEsQueryConfig } from '@kbn/es-query'; -import React from 'react'; -import { connect } from 'react-redux'; - -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../../containers/source'; -import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '../../../store/inputs/actions'; -import { scoreIntervalToDateTime } from '../../../components/ml/score/score_interval_to_datetime'; -import { Anomaly } from '../../../components/ml/types'; -import { convertToBuildEsQuery } from '../../../lib/keury'; -import { useKibanaCore } from '../../../lib/compose/kibana_core'; - -import { HostDetailsBodyComponentProps } from './types'; -import { type, makeMapStateToProps } from './utils'; - -const HostDetailsBodyComponent = React.memo( - ({ - children, - deleteQuery, - detailName, - filters, - from, - isInitializing, - query, - setAbsoluteRangeDatePicker, - setQuery, - to, - }) => { - const core = useKibanaCore(); - return ( - - {({ indicesExist, indexPattern }) => { - const filterQuery = convertToBuildEsQuery({ - config: getEsQueryConfig(core.uiSettings), - indexPattern, - queries: [query], - filters: [ - { - meta: { - alias: null, - negate: false, - disabled: false, - type: 'phrase', - key: 'host.name', - value: detailName, - params: { - query: detailName, - }, - }, - query: { - match: { - 'host.name': { - query: detailName, - type: 'phrase', - }, - }, - }, - }, - ...filters, - ], - }); - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - <> - {children({ - deleteQuery, - endDate: to, - filterQuery, - skip: isInitializing, - setQuery, - startDate: from, - type, - indexPattern, - hostName: detailName, - narrowDateRange: (score: Anomaly, interval: string) => { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }, - updateDateRange: (min: number, max: number) => { - setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); - }, - })} - - ) : null; - }} - - ); - } -); - -HostDetailsBodyComponent.displayName = 'HostDetailsBodyComponent'; - -export const HostDetailsBody = connect( - makeMapStateToProps, - { - setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, - } -)(HostDetailsBodyComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.test.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.test.tsx new file mode 100644 index 0000000000000..6ceebc1708b18 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.test.tsx @@ -0,0 +1,108 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { mount } from 'enzyme'; +import React from 'react'; +import { StaticIndexPattern } from 'ui/index_patterns'; +import { MemoryRouter } from 'react-router-dom'; + +import { mockIndexPattern } from '../../../mock/index_pattern'; +import { TestProviders } from '../../../mock/test_providers'; +import { mockUiSettings } from '../../../mock/ui_settings'; +import { HostDetailsTabs } from './details_tabs'; +import { SetAbsoluteRangeDatePicker } from './types'; +import { hostDetailsPagePath } from '../types'; +import { type } from './utils'; +import { useKibanaCore } from '../../../lib/compose/kibana_core'; + +jest.mock('../../../lib/settings/use_kibana_ui_setting'); + +const mockUseKibanaCore = useKibanaCore as jest.Mock; +jest.mock('../../../lib/compose/kibana_core'); +mockUseKibanaCore.mockImplementation(() => ({ + uiSettings: mockUiSettings, +})); + +jest.mock('../../../containers/source', () => ({ + indicesExistOrDataTemporarilyUnavailable: () => true, + WithSource: ({ + children, + }: { + children: (args: { + indicesExist: boolean; + indexPattern: StaticIndexPattern; + }) => React.ReactNode; + }) => children({ indicesExist: true, indexPattern: mockIndexPattern }), +})); + +// Test will fail because we will to need to mock some core services to make the test work +// For now let's forget about SiemSearchBar +jest.mock('../../../components/search_bar', () => ({ + SiemSearchBar: () => null, +})); + +describe('body', () => { + const scenariosMap = { + authentications: 'AuthenticationsQueryTabBody', + allHosts: 'HostsQueryTabBody', + uncommonProcesses: 'UncommonProcessQueryTabBody', + anomalies: 'AnomaliesQueryTabBody', + events: 'EventsQueryTabBody', + }; + + Object.entries(scenariosMap).forEach(([path, componentName]) => + test(`it should pass expected object properties to ${componentName}`, () => { + const wrapper = mount( + + + {}} + to={0} + setAbsoluteRangeDatePicker={(jest.fn() as unknown) as SetAbsoluteRangeDatePicker} + hostDetailsPagePath={hostDetailsPagePath} + indexPattern={mockIndexPattern} + type={type} + filterQuery='{"bool":{"must":[],"filter":[{"match_all":{}},{"match_phrase":{"host.name":{"query":"host-1"}}}],"should":[],"must_not":[]}}' + /> + + + ); + + // match against everything but the functions to ensure they are there as expected + expect(wrapper.find(componentName).props()).toMatchObject({ + endDate: 0, + filterQuery: + '{"bool":{"must":[],"filter":[{"match_all":{}},{"match_phrase":{"host.name":{"query":"host-1"}}}],"should":[],"must_not":[]}}', + skip: false, + startDate: 0, + type: 'details', + indexPattern: { + fields: [ + { name: '@timestamp', searchable: true, type: 'date', aggregatable: true }, + { name: '@version', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.ephemeral_id', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.hostname', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.id', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.test1', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.test2', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.test3', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.test4', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.test5', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.test6', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.test7', searchable: true, type: 'string', aggregatable: true }, + { name: 'agent.test8', searchable: true, type: 'string', aggregatable: true }, + { name: 'host.name', searchable: true, type: 'string', aggregatable: true }, + ], + title: 'filebeat-*,auditbeat-*,packetbeat-*', + }, + hostName: 'host-1', + }); + }) + ); +}); diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx new file mode 100644 index 0000000000000..48b6d34d0b28b --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/details_tabs.tsx @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback } from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import { scoreIntervalToDateTime } from '../../../components/ml/score/score_interval_to_datetime'; +import { Anomaly } from '../../../components/ml/types'; +import { HostsTableType } from '../../../store/hosts/model'; + +import { HostDetailsTabsProps } from './types'; +import { type } from './utils'; + +import { + HostsQueryTabBody, + AuthenticationsQueryTabBody, + UncommonProcessQueryTabBody, + AnomaliesQueryTabBody, + EventsQueryTabBody, +} from '../navigation'; + +const HostDetailsTabs = React.memo( + ({ + deleteQuery, + filterQuery, + from, + isInitializing, + detailName, + setAbsoluteRangeDatePicker, + setQuery, + to, + indexPattern, + hostDetailsPagePath, + }) => { + const narrowDateRange = useCallback( + (score: Anomaly, interval: string) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }, + [setAbsoluteRangeDatePicker, scoreIntervalToDateTime] + ); + + const updateDateRange = useCallback( + (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + [setAbsoluteRangeDatePicker, scoreIntervalToDateTime] + ); + + const tabProps = { + deleteQuery, + endDate: to, + filterQuery, + skip: isInitializing, + setQuery, + startDate: from, + type, + indexPattern, + hostName: detailName, + narrowDateRange, + updateDateRange, + }; + + return ( + + } + /> + } + /> + } + /> + } + /> + } + /> + + ); + } +); + +HostDetailsTabs.displayName = 'HostDetailsTabs'; + +export { HostDetailsTabs }; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx index d1d29c3d2ea82..aa81481bedbe7 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx @@ -11,6 +11,8 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { StickyContainer } from 'react-sticky'; +import { inputsSelectors, State } from '../../../store'; + import { FiltersGlobal } from '../../../components/filters_global'; import { HeaderPage } from '../../../components/header_page'; import { KpiHostDetailsQuery } from '../../../containers/kpi_host_details'; @@ -32,22 +34,19 @@ import { LastEventIndexKey } from '../../../graphql/types'; import { convertToBuildEsQuery } from '../../../lib/keury'; import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '../../../store/inputs/actions'; import { SpyRoute } from '../../../utils/route/spy_routes'; +import { useKibanaCore } from '../../../lib/compose/kibana_core'; -import { HostsQueryProps } from '../hosts'; import { HostsEmptyPage } from '../hosts_empty_page'; - -export { HostDetailsBody } from './body'; import { navTabsHostDetails } from './nav_tabs'; -import { HostDetailsComponentProps } from './types'; -import { makeMapStateToProps } from './utils'; -import { useKibanaCore } from '../../../lib/compose/kibana_core'; +import { HostDetailsComponentProps, HostDetailsProps } from './types'; +import { HostDetailsTabs } from './details_tabs'; +import { type } from './utils'; const HostOverviewManage = manageQuery(HostOverview); const KpiHostDetailsManage = manageQuery(KpiHostsComponent); const HostDetailsComponent = React.memo( ({ - detailName, filters, from, isInitializing, @@ -56,6 +55,9 @@ const HostDetailsComponent = React.memo( setHostDetailsTablesActivePageToZero, setQuery, to, + detailName, + deleteQuery, + hostDetailsPagePath, }) => { useEffect(() => { setHostDetailsTablesActivePageToZero(null); @@ -96,94 +98,111 @@ const HostDetailsComponent = React.memo( ], }); return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - + <> + + + + - - } - title={detailName} - /> - - {({ hostOverview, loading, id, inspect, refetch }) => ( - - {({ isLoadingAnomaliesData, anomaliesData }) => ( - { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }} - /> - )} - - )} - + + } + title={detailName} + /> + + {({ hostOverview, loading, id, inspect, refetch }) => ( + + {({ isLoadingAnomaliesData, anomaliesData }) => ( + { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }} + /> + )} + + )} + - + - - {({ kpiHostDetails, id, inspect, loading, refetch }) => ( - { - setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); - }} - /> - )} - + + {({ kpiHostDetails, id, inspect, loading, refetch }) => ( + { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }} + /> + )} + - + + + - - + ) : ( <> - ); @@ -197,7 +216,16 @@ const HostDetailsComponent = React.memo( HostDetailsComponent.displayName = 'HostDetailsComponent'; -export const HostDetails = compose>( +export const makeMapStateToProps = () => { + const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); + const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); + return (state: State) => ({ + query: getGlobalQuerySelector(state), + filters: getGlobalFiltersQuerySelector(state), + }); +}; + +export const HostDetails = compose>( connect( makeMapStateToProps, { diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/types.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/details/types.ts index b4dda2cee8760..9df57970176eb 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/types.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { StaticIndexPattern } from 'ui/index_patterns'; import { Filter } from '@kbn/es-query'; import { ActionCreator } from 'typescript-fsa'; import { Query } from 'src/plugins/data/common'; @@ -11,13 +12,10 @@ import { Query } from 'src/plugins/data/common'; import { InputsModelId } from '../../../store/inputs/constants'; import { HostComponentProps } from '../../../components/link_to/redirect_to_hosts'; import { HostsTableType } from '../../../store/hosts/model'; -import { HostsQueryProps } from '../hosts'; +import { HostsQueryProps } from '../types'; import { NavTab } from '../../../components/navigation/types'; -import { - AnomaliesChildren, - CommonChildren, - KeyHostsNavTabWithoutMlPermission, -} from '../navigation/types'; +import { KeyHostsNavTabWithoutMlPermission } from '../navigation/types'; +import { hostsModel } from '../../../store'; interface HostDetailsComponentReduxProps { query: Query; @@ -31,14 +29,16 @@ interface HostBodyComponentDispatchProps { to: number; }>; detailName: string; + hostDetailsPagePath: string; } interface HostDetailsComponentDispatchProps extends HostBodyComponentDispatchProps { setHostDetailsTablesActivePageToZero: ActionCreator; } -export interface HostDetailsBodyProps extends HostsQueryProps { - children: CommonChildren | AnomaliesChildren; +export interface HostDetailsProps extends HostsQueryProps { + detailName: string; + hostDetailsPagePath: string; } export type HostDetailsComponentProps = HostDetailsComponentReduxProps & @@ -46,10 +46,6 @@ export type HostDetailsComponentProps = HostDetailsComponentReduxProps & HostComponentProps & HostsQueryProps; -export type HostDetailsBodyComponentProps = HostDetailsComponentReduxProps & - HostBodyComponentDispatchProps & - HostDetailsBodyProps; - type KeyHostDetailsNavTabWithoutMlPermission = HostsTableType.authentications & HostsTableType.uncommonProcesses & HostsTableType.events; @@ -62,3 +58,16 @@ type KeyHostDetailsNavTab = | KeyHostDetailsNavTabWithMlPermission; export type HostDetailsNavTab = Record; + +export type HostDetailsTabsProps = HostBodyComponentDispatchProps & + HostsQueryProps & { + indexPattern: StaticIndexPattern; + type: hostsModel.HostsType; + filterQuery: string; + }; + +export type SetAbsoluteRangeDatePicker = ActionCreator<{ + id: InputsModelId; + from: number; + to: number; +}>; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/utils.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/details/utils.ts index 52efe93c0c8dc..7483636cfe03d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/utils.ts +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/utils.ts @@ -6,7 +6,7 @@ import { Breadcrumb } from 'ui/chrome'; -import { hostsModel, inputsSelectors, State } from '../../../store'; +import { hostsModel } from '../../../store'; import { HostsTableType } from '../../../store/hosts/model'; import { getHostsUrl, getHostDetailsUrl } from '../../../components/link_to/redirect_to_hosts'; @@ -15,15 +15,6 @@ import { RouteSpyState } from '../../../utils/route/types'; export const type = hostsModel.HostsType.details; -export const makeMapStateToProps = () => { - const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); - const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); - return (state: State) => ({ - query: getGlobalQuerySelector(state), - filters: getGlobalFiltersQuerySelector(state), - }); -}; - const TabNameMappedToI18nKey = { [HostsTableType.hosts]: i18n.NAVIGATION_ALL_HOSTS_TITLE, [HostsTableType.authentications]: i18n.NAVIGATION_AUTHENTICATIONS_TITLE, diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx index 5b6444148045d..d2c9822889c26 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx @@ -19,7 +19,8 @@ import { wait } from '../../lib/helpers'; import { TestProviders } from '../../mock'; import { mockUiSettings } from '../../mock/ui_settings'; import { InputsModelId } from '../../store/inputs/constants'; -import { Hosts, HostsComponentProps } from './hosts'; +import { HostsComponentProps } from './types'; +import { Hosts } from './hosts'; import { useKibanaCore } from '../../lib/compose/kibana_core'; jest.mock('../../lib/settings/use_kibana_ui_setting'); @@ -97,6 +98,7 @@ describe('Hosts - rendering', () => { }>, query: { query: '', language: 'kuery' }, filters: [], + hostsPagePath: '', }; beforeAll(() => { diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx index 7c54745f872a9..334d730378b23 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx @@ -5,13 +5,11 @@ */ import { EuiSpacer } from '@elastic/eui'; -import { Filter, getEsQueryConfig } from '@kbn/es-query'; +import { getEsQueryConfig } from '@kbn/es-query'; import * as React from 'react'; import { compose } from 'redux'; import { connect } from 'react-redux'; import { StickyContainer } from 'react-sticky'; -import { ActionCreator } from 'typescript-fsa'; -import { Query } from 'src/plugins/data/common'; import { FiltersGlobal } from '../../components/filters_global'; import { GlobalTimeArgs } from '../../containers/global_time'; @@ -27,41 +25,34 @@ import { SiemSearchBar } from '../../components/search_bar'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; import { LastEventIndexKey } from '../../graphql/types'; import { convertToBuildEsQuery } from '../../lib/keury'; -import { inputsSelectors, State } from '../../store'; +import { inputsSelectors, State, hostsModel } from '../../store'; import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; -import { InputsModelId } from '../../store/inputs/constants'; import { SpyRoute } from '../../utils/route/spy_routes'; +import { useKibanaCore } from '../../lib/compose/kibana_core'; import { HostsEmptyPage } from './hosts_empty_page'; import { navTabsHosts } from './nav_tabs'; import * as i18n from './translations'; -import { useKibanaCore } from '../../lib/compose/kibana_core'; +import { HostsComponentProps, HostsComponentReduxProps } from './types'; +import { HostsTabs } from './hosts_tabs'; const KpiHostsComponentManage = manageQuery(KpiHostsComponent); -interface HostsComponentReduxProps { - query: Query; - filters: Filter[]; -} - -interface HostsComponentDispatchProps { - setAbsoluteRangeDatePicker: ActionCreator<{ - id: InputsModelId; - from: number; - to: number; - }>; -} - -export type HostsQueryProps = GlobalTimeArgs; - -export type HostsComponentProps = HostsComponentReduxProps & - HostsComponentDispatchProps & - HostsQueryProps; - const HostsComponent = React.memo( - ({ isInitializing, filters, from, query, setAbsoluteRangeDatePicker, setQuery, to }) => { + ({ + deleteQuery, + isInitializing, + filters, + from, + query, + setAbsoluteRangeDatePicker, + setQuery, + to, + hostsPagePath, + }) => { const capabilities = React.useContext(MlCapabilitiesContext); const core = useKibanaCore(); + return ( <> @@ -73,48 +64,62 @@ const HostsComponent = React.memo( filters, }); return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - - - - + <> + + + + - } - title={i18n.PAGE_TITLE} - /> - <> - - {({ kpiHosts, loading, id, inspect, refetch }) => ( - { - setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); - }} - /> - )} - - - } + title={i18n.PAGE_TITLE} /> - - - + <> + + {({ kpiHosts, loading, id, inspect, refetch }) => ( + { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }} + /> + )} + + + + + + + + ) : ( <> @@ -142,8 +147,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; +interface HostsProps extends GlobalTimeArgs { + hostsPagePath: string; +} + // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const Hosts = compose>( +export const Hosts = compose>( connect( makeMapStateToProps, { diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx deleted file mode 100644 index 3d7e54b4a19ac..0000000000000 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_body.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { getEsQueryConfig } from '@kbn/es-query'; -import React, { memo } from 'react'; -import { connect } from 'react-redux'; - -import { scoreIntervalToDateTime } from '../../components/ml/score/score_interval_to_datetime'; -import { Anomaly } from '../../components/ml/types'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; -import { convertToBuildEsQuery } from '../../lib/keury'; -import { useKibanaCore } from '../../lib/compose/kibana_core'; -import { hostsModel, inputsSelectors, State } from '../../store'; -import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; - -import { HostsComponentProps } from './hosts'; -import { CommonChildren, AnomaliesChildren } from './navigation/types'; - -interface HostsBodyComponentProps extends HostsComponentProps { - children: CommonChildren | AnomaliesChildren; -} - -const HostsBodyComponent = memo( - ({ - children, - deleteQuery, - filters, - from, - isInitializing, - query, - setAbsoluteRangeDatePicker, - setQuery, - to, - }) => { - const core = useKibanaCore(); - return ( - - {({ indicesExist, indexPattern }) => { - const filterQuery = convertToBuildEsQuery({ - config: getEsQueryConfig(core.uiSettings), - indexPattern, - queries: [query], - filters, - }); - return indicesExistOrDataTemporarilyUnavailable(indicesExist) ? ( - <> - {children({ - deleteQuery, - endDate: to, - filterQuery, - skip: isInitializing, - setQuery, - startDate: from, - type: hostsModel.HostsType.page, - indexPattern, - narrowDateRange: (score: Anomaly, interval: string) => { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }, - updateDateRange: (min: number, max: number) => { - setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); - }, - })} - - ) : null; - }} - - ); - } -); - -HostsBodyComponent.displayName = 'HostsBodyComponent'; - -const makeMapStateToProps = () => { - const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); - const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); - const mapStateToProps = (state: State) => ({ - query: getGlobalQuerySelector(state), - filters: getGlobalFiltersQuerySelector(state), - }); - return mapStateToProps; -}; - -export const HostsBody = connect( - makeMapStateToProps, - { - setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, - } -)(HostsBodyComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx new file mode 100644 index 0000000000000..6dbfb422ed7a6 --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts_tabs.tsx @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { memo } from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import { HostsTabsProps } from './types'; +import { scoreIntervalToDateTime } from '../../components/ml/score/score_interval_to_datetime'; +import { Anomaly } from '../../components/ml/types'; +import { HostsTableType } from '../../store/hosts/model'; + +import { + HostsQueryTabBody, + AuthenticationsQueryTabBody, + UncommonProcessQueryTabBody, + AnomaliesQueryTabBody, + EventsQueryTabBody, +} from './navigation'; + +const HostsTabs = memo( + ({ + deleteQuery, + filterQuery, + setAbsoluteRangeDatePicker, + to, + from, + setQuery, + isInitializing, + type, + indexPattern, + hostsPagePath, + }) => { + const tabProps = { + deleteQuery, + endDate: to, + filterQuery, + skip: isInitializing, + setQuery, + startDate: from, + type, + indexPattern, + narrowDateRange: (score: Anomaly, interval: string) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }, + updateDateRange: (min: number, max: number) => { + setAbsoluteRangeDatePicker({ id: 'global', from: min, to: max }); + }, + }; + + return ( + + } + /> + } + /> + } + /> + } + /> + } + /> + + ); + } +); + +HostsTabs.displayName = 'HostsTabs'; + +export { HostsTabs }; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx index 72b19dbbb13b2..c8d450a62cc57 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx @@ -7,21 +7,13 @@ import React from 'react'; import { Redirect, Route, Switch, RouteComponentProps } from 'react-router-dom'; -import { HostDetailsBody, HostDetails } from './details'; -import { - HostsQueryTabBody, - AuthenticationsQueryTabBody, - UncommonProcessQueryTabBody, - AnomaliesQueryTabBody, - EventsQueryTabBody, -} from './navigation'; -import { HostsBody } from './hosts_body'; +import { HostDetails } from './details'; import { HostsTableType } from '../../store/hosts/model'; + import { GlobalTime } from '../../containers/global_time'; import { SiemPageName } from '../home/types'; import { Hosts } from './hosts'; - -const hostsPagePath = `/:pageName(${SiemPageName.hosts})`; +import { hostsPagePath, hostDetailsPagePath } from './types'; const getHostsTabPath = (pagePath: string) => `${pagePath}/:tabName(` + @@ -32,7 +24,7 @@ const getHostsTabPath = (pagePath: string) => `${HostsTableType.events})`; const getHostDetailsTabPath = (pagePath: string) => - `${pagePath}/:detailName/:tabName(` + + `${hostDetailsPagePath}/:tabName(` + `${HostsTableType.authentications}|` + `${HostsTableType.uncommonProcesses}|` + `${HostsTableType.anomalies}|` + @@ -44,191 +36,38 @@ export const HostsContainer = React.memo(({ url }) => ( {({ to, from, setQuery, deleteQuery, isInitializing }) => ( - ( - ( - <> - - - - )} - /> - )} - /> ( - <> - - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - + )} /> ( - <> - - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - ( - - )} - /> - + )} /> (({ url }) => ( }) => } /> ( - + )} /> diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts b/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts new file mode 100644 index 0000000000000..980c5535129aa --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/types.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { StaticIndexPattern } from 'ui/index_patterns'; +import { ActionCreator } from 'typescript-fsa'; +import { Filter } from '@kbn/es-query'; +import { Query } from 'src/plugins/data/common'; + +import { SiemPageName } from '../home/types'; +import { hostsModel } from '../../store'; +import { InputsModelId } from '../../store/inputs/constants'; +import { GlobalTimeArgs } from '../../containers/global_time'; + +export const hostsPagePath = `/:pageName(${SiemPageName.hosts})`; +export const hostDetailsPagePath = `${hostsPagePath}/:detailName`; + +export interface HostsComponentReduxProps { + query: Query; + filters: Filter[]; +} + +export interface HostsComponentDispatchProps { + setAbsoluteRangeDatePicker: ActionCreator<{ + id: InputsModelId; + from: number; + to: number; + }>; + hostsPagePath: string; +} + +export type HostsTabsProps = HostsComponentDispatchProps & + HostsQueryProps & { + filterQuery: string; + type: hostsModel.HostsType; + indexPattern: StaticIndexPattern; + }; + +export type HostsQueryProps = GlobalTimeArgs; + +export type HostsComponentProps = HostsComponentReduxProps & + HostsComponentDispatchProps & + HostsQueryProps; From d9a5acf971bbf32516dd77870dbad82de017b415 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Mon, 28 Oct 2019 09:37:34 -0400 Subject: [PATCH 191/191] FTR: clear browser storage between test suites (#48683) * clear browser storage on test suite completion * [logstash/pipeline_list] fix tests dependency * always load new index data --- test/functional/services/remote/remote.ts | 2 ++ .../functional/apps/logstash/pipeline_list.js | 16 ++++------------ .../anomaly_detection/multi_metric_job.ts | 2 +- .../anomaly_detection/population_job.ts | 2 +- .../anomaly_detection/saved_search_job.ts | 2 +- .../anomaly_detection/single_metric_job.ts | 2 +- 6 files changed, 10 insertions(+), 16 deletions(-) diff --git a/test/functional/services/remote/remote.ts b/test/functional/services/remote/remote.ts index 4dc608542c3c3..b30a0e50886d1 100644 --- a/test/functional/services/remote/remote.ts +++ b/test/functional/services/remote/remote.ts @@ -128,6 +128,8 @@ export async function RemoteProvider({ getService }: FtrProviderContext) { .manage() .window() .setRect({ width, height }); + await driver.executeScript('window.sessionStorage.clear();'); + await driver.executeScript('window.localStorage.clear();'); }); lifecycle.on('cleanup', async () => { diff --git a/x-pack/test/functional/apps/logstash/pipeline_list.js b/x-pack/test/functional/apps/logstash/pipeline_list.js index d04f50690368d..ce0c9d881f51b 100644 --- a/x-pack/test/functional/apps/logstash/pipeline_list.js +++ b/x-pack/test/functional/apps/logstash/pipeline_list.js @@ -22,6 +22,9 @@ export default function ({ getService, getPageObjects }) { originalWindowSize = await browser.getWindowSize(); await browser.setWindowSize(1600, 1000); await esArchiver.load('logstash/example_pipelines'); + }); + + beforeEach(async () => { await PageObjects.logstash.gotoPipelineList(); }); @@ -86,10 +89,6 @@ export default function ({ getService, getPageObjects }) { await pipelineEditor.assertExists(); await pipelineEditor.assertDefaultInputs(); }); - - after(async () => { - await PageObjects.logstash.gotoPipelineList(); - }); }); describe('delete button', () => { @@ -122,15 +121,12 @@ export default function ({ getService, getPageObjects }) { describe('row links', () => { it('opens the selected row in the editor', async () => { + await PageObjects.logstash.gotoPipelineList(); await pipelineList.setFilter('tweets_and_beats'); await pipelineList.clickFirstRowId(); await pipelineEditor.assertExists(); await pipelineEditor.assertEditorId('tweets_and_beats'); }); - - after(async () => { - await PageObjects.logstash.gotoPipelineList(); - }); }); describe('next page button', () => { @@ -225,10 +221,6 @@ export default function ({ getService, getPageObjects }) { queueCheckpointWrites, }); }); - - after(async () => { - await PageObjects.logstash.gotoPipelineList(); - }); }); }); } diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts index 06dd0df9e470c..6163e99b5eaa4 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/multi_metric_job.ts @@ -74,7 +74,7 @@ export default function({ getService }: FtrProviderContext) { describe('multi metric', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.loadIfNeeded('ml/farequote'); + await esArchiver.load('ml/farequote'); }); after(async () => { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts index cd88a9bba1769..7ccd9214591f2 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/population_job.ts @@ -88,7 +88,7 @@ export default function({ getService }: FtrProviderContext) { describe('population', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.loadIfNeeded('ml/ecommerce'); + await esArchiver.load('ml/ecommerce'); }); after(async () => { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts index 2cca37a944563..5645bc7277d19 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/saved_search_job.ts @@ -274,7 +274,7 @@ export default function({ getService }: FtrProviderContext) { describe('saved search', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.loadIfNeeded('ml/farequote'); + await esArchiver.load('ml/farequote'); }); after(async () => { diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts index 6e640f7d173d5..06ec840b36aae 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts @@ -73,7 +73,7 @@ export default function({ getService }: FtrProviderContext) { describe('single metric', function() { this.tags(['smoke', 'mlqa']); before(async () => { - await esArchiver.loadIfNeeded('ml/farequote'); + await esArchiver.load('ml/farequote'); }); after(async () => {